我目前正在将内容从一个CMS导出/导入另一个CMS。
我有出口到位。我将旧CMS中的所有内容导出到XML文件,保留文档的结构等。 导入也就位,映射到新的PageTypes,映射文本字段等。 我还导出并导入了从旧CMS到新CMS的所有媒体。
我唯一关心的问题是,在每个页面的RichText字段内处理内部链接和媒体项链接。
因此,每个页面都包含一个Header,一些通用信息和一个RichTextField,其中包含HTML页面内容。 此字段可以包含指向同一站点内其他页面的链接,以及内部链接和媒体项链接。
我的问题是,我怎样才能找到这些,并将它们映射到我的新结构。
所有内部链接都是这样的:<a href="/mycms/~/link.aspx?_id=D9423CEFED254610A5DC6B096A297E17&_z=z">...</a>
(可能在某些链接上有更多属性,例如style=".."
,class=".."
等。
ID是对旧CMS的ID的引用,它总是32个字符长。
媒体项目(图片)可能如下所示:<img src="/mycms/~/media/B1FB91AC357347BD84913D56B8791D03.ashx" alt="" width="690" height="202" />
。此外,id总是32个字符。
在导入期间,我生成了一个json文件,其中包含旧CMS中的所有mediaId,并将其映射到新CMS中的新ID。 所以它看起来像这样;
{
"{0CFBBD0A-9156-4AD9-8A8A-7D30B2D7213B}":1095,
"{BE9BEAAA-F04D-42DA-B52A-44B4B31A389E}":1096,
etc.
}
请注意旧CMS ID的ID格式与链接和媒体中使用的格式不同。剥去花括号和短划线,它会匹配。
最好的方法是什么?我猜一个RegEx将是要走的路 - 但是那会是什么样子?
谢谢:)
答案 0 :(得分:5)
您最好的选择是使用类似HtmlAgilityPack的内容。纯正则表达式通常太粗糙无法成功解析HTML ...这不是一项不可能的任务,但比使用HtmlAgilityPack更难。
The post Eric在他的评论中链接的是历史上臭名昭着的StackOverflow和多个回复,其中详细介绍了为什么不推荐使用Regex解析HTML的方法。根据我的个人经验提供TLDR:HTML页面通常充满了小错误&#34;。例如,您经常会有<img>
个未正确关闭的标记(例如<img />
)。确定性匹配和替换也很困难。
因此,尝试使用正确的工具来完成工作 - 在这种情况下,正确的工具是HtmlAgilityPack。
当谈到HtmlAgilityPack的使用时 - they have good documentation。在您的情况下,您可能希望查看Replace Child功能。要从他们的文档中重现示例,请使用以下测试HTML:
<body>
<h1>This is <b>bold</b> heading</h1>
<p>This is <u>underlined</u> paragraph</p>
</body>
要操纵它,并替换您要执行的<h1>
节点:
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html); // where html = @"content previously mentioned"
var htmlBody = htmlDoc.DocumentNode.SelectSingleNode("//body");
HtmlNode oldChild = htmlBody.ChildNodes[1];
HtmlNode newChild = HtmlNode.CreateNode("<h2> This is h2 new child heading</h2>");
htmlBody.ReplaceChild(newChild, oldChild);
// now htmlBody has <h2> node instead of old <h1>
在您的情况下,您可能希望使用SelectNodes而不是SelectSingleNode,在XPath中,您将定位要替换的元素。在列表中包含这些元素后,您将迭代它们并根据条件替换内容。
要记住一件事 - 因为您的ID非常详细,有32个字符,您可能会将它们与纯字符串搜索匹配。所以如果你不是针对某些HTML元素,而是ID - 那么你甚至不需要使用HtmlAgilityPack或Regex - 做简单的String.Replace("OLDUID", "NEWUID")
。
答案 1 :(得分:0)
如果你将非HTML与html混合使用,最好使用正则表达式 这是一种进行替换的方法。
链接:
(?i)(<a)(?=((?:[^>"']|"[^"]*"|'[^']*')*?\shref\s*=\s*(['"])/mycms/~/link\.aspx\?_id=)([a-f0-9]{32})(&_z=z\3(?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>))\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>
替换为$1$2
+ key{$4}
+ $5
其中key{$4}
是字典中的新链接ID值。
https://regex101.com/r/xRf1xN/1
# https://regex101.com/r/ieEBj8/1
(?i) # Case insensitive modifier
( < a ) # (1), The a tag
(?= # Asserttion (a pseudo atomic group)
( # (2 start), Up to the ID num
(?: [^>"'] | " [^"]* " | ' [^']* ' )*?
\s href \s* = \s* # href attribute
( ['"] ) # (3), Quote
/mycms/~/link\.aspx\?_id= # Prefix link static text
) # (2 end)
( [a-f0-9]{32} ) # (4), hex link ID
( # (5 start), All past the ID num
&_z=z # Postfix link static text
\3 # End quote
# The remainder of the tag parts
(?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
>
) # (5 end)
)
# All the parts have already been found via assertion
# Just match a normal tag closure to advance the position
\s+
(?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
>
媒体:
(?i)(<img)(?=((?:[^>"']|"[^"]*"|'[^']*')*?\ssrc\s*=\s*(['"])/mycms/~/media/)([a-f0-9]{32})(\.ashx\3(?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>))\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>
替换为$1$2
+ key{$4}
+ $5
其中key{$4}
是字典中的新媒体ID值。
https://regex101.com/r/pwyjoK/1
# https://regex101.com/r/ieEBj8/1
(?i) # Case insensitive modifier
( < img ) # (1), The img tag
(?= # Asserttion (a pseudo atomic group)
( # (2 start), Up to the ID num
(?: [^>"'] | " [^"]* " | ' [^']* ' )*?
\s src \s* = \s* # src attribute
( ['"] ) # (3), Quote
/mycms/~/media/ # Prefix media static text
) # (2 end)
( [a-f0-9]{32} ) # (4), hex media ID
( # (5 start), All past the ID num
\.ashx # Postfix media static text
\3 # End quote
# The remainder of the tag parts
(?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
>
) # (5 end)
)
# All the parts have already been found via assertion
# Just match a normal tag closure to advance the position
\s+
(?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
>
如果我想a)在link / src标签中提取ID,b)替换整个href =&#34; ..&#34;或src =&#34; ..&#34;价值(而不是ID部分,在RegEx中看起来如何?
要执行此操作,只需重新排列捕获组即可。
链接:
(?i)(<a)(?=((?:[^>"']|"[^"]*"|'[^']*')*?\s)(href\s*=\s*(['"])/mycms/~/link\.aspx\?_id=([a-f0-9]{32})&_z=z\4)((?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>))\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>
替换为$1$2href='NEWID:key{$5}'$6
其中key{$5}
是字典中的新链接ID值。
https://regex101.com/r/FxpJVl/1
(?i) # Case insensitive modifier
( < a ) # (1), The a tag
(?= # Asserttion (a pseudo atomic group)
( # (2 start), Up to the href attribute
(?: [^>"'] | " [^"]* " | ' [^']* ' )*?
\s
) # (2 end)
( # (3 start), href attribute
href \s* = \s*
( ['"] ) # (4), Quote
/mycms/~/link\.aspx\?_id= # Prefix link static text
( [a-f0-9]{32} ) # (5), hex link ID
&_z=z # Postfix link static text
\4 # End quote
) # (3 end)
( # (6 start), remainder of the tag parts
(?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
>
) # (6 end)
)
# All the parts have already been found via assertion
# Just match a normal tag closure to advance the position
\s+
(?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
>
媒体:
(?i)(<img)(?=((?:[^>"']|"[^"]*"|'[^']*')*?\s)(src\s*=\s*(['"])/mycms/~/media/([a-f0-9]{32})\.ashx\4)((?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>))\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>
替换为$1$2src='NEWID:key{$5}'$6
其中key{$5}
是字典中的新媒体ID值。
https://regex101.com/r/EqKYjM/1
(?i) # Case insensitive modifier
( < img ) # (1), The img tag
(?= # Asserttion (a pseudo atomic group)
( # (2 start), Up to the src attribute
(?: [^>"'] | " [^"]* " | ' [^']* ' )*?
\s
) # (2 end)
( # (3 start), src attribute
src \s* = \s*
( ['"] ) # (4), Quote
/mycms/~/media/ # Prefix media static text
( [a-f0-9]{32} ) # (5), hex media ID
\.ashx # Postfix media static text
\4 # End quote
) # (3 end)
( # (6 start), remainder of the tag parts
(?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
>
) # (6 end)
)
# All the parts have already been found via assertion
# Just match a normal tag closure to advance the position
\s+
(?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
>