【问题标题】:How to remove href tag from CDATA如何从 CDATA 中删除 href 标签
【发布时间】:2012-04-09 17:44:50
【问题描述】:

我在 xml 文档中有以下 CDATA:

<![CDATA[ <p xmlns="">Refer to the below: <br/>
</p>
<table xmlns:abc="http://google.com pic.xsd" cellspacing="1" class="c" type="custom" width="100%">
    <tbody>
        <tr xmlns="">            
            <th style="text-align: left">Basic offers...</th>
        </tr>
        <tr xmlns="">
            <td style="text-align: left">Faster network</td>
            <td style="text-align: left">
            <ul>                
                <li>Session</li>
            </ul>
            </td>
        </tr>
        <tr xmlns="">
            <td style="text-align: left">capabilities</td>
            <td style="text-align: left">
            <ul>                
                <li>Navigation,</li>
                <li>message, and</li>
                <li>contacts</li>
            </ul>
            </td>
        </tr>
        <tr xmlns="">
            <td style="text-align: left">Data</td>
            <td style="text-align: left">
            <p>Here visit google for more info <a href="http://www.google.com" target="_blank"><font color="#0033cc">www.google.com</font></a>.</p>
            <p>Remove this href tag <a href="/abc/def/{T}/t/1" target="_blank">Information</a> remove the tag.</p>
            </td>
        </tr>
    </tbody>
</table>
<p xmlns=""><br/>
</p>
  ]]> 

我想了解如何扫描 href="/abc/def 并删除以 abc/def 开头的 href 标签。在​​上面的示例中,删除 href 标签并在标签内留下“信息”文本。CDATA 可以有多个带有“abc/def ...”的href标签。 我在这个应用程序中使用 C#。有人可以帮助我并告诉我如何做到这一点吗?我应该使用正则表达式还是有办法用 xml 本身来做?

这是我正在尝试的正则表达式:

"<a href=\"/abc/def/.*></a>"

我想保留 a href 标记的内部文本,只需删除标记即可。但是上面的正则表达式不起作用。

【问题讨论】:

  • @RoyiNamir - 是的,我在 C# 中使用 XmlDocument 来加载 xml 文档。比使用节点将 CDATA 提取到字符串中。

标签: c# xml xmldocument


【解决方案1】:

使用HtmlAgilityPack

HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);

var nodes = doc.DocumentNode
    .Descendants("a")
    .Where(n => n.Attributes.Any(a => a.Name == "href" && a.Value.StartsWith("/abc/def")))
    .ToArray();

foreach(var node in nodes)
{
    node.ParentNode.RemoveChild(node,true);
}

var newHtml = doc.DocumentNode.InnerHtml;

【讨论】:

  • 嗨,我必须下载这个 HtmlAgilityPack 吗?我以前从未使用过这个?
  • 是的,我在答案中给出了链接。它是每个开发人员的必备工具之一。
  • 甚至比解析为 XML 更好,如果 HTML 不是 XML 格式良好,这可以防止异常。注意 LB:OP 提到它可以包含多个具有给定属性的 a 元素。
  • 惊人的惊人答案。不能给出超过加一的答案,否则将给出我对这个答案的所有观点。谢谢@L.B
【解决方案2】:

我会使用HtmlAgilityPack 来完成这项任务。任务本身非常简单:使用 xpath 选择节点,然后删除它们。剩下的就是得到结果 HTML:

它是一个 .NET 代码库,可让您解析“网络外” HTML 文件。解析器对“真实世界”的格式错误非常宽容 HTML。对象模型与 System.Xml 的提议非常相似, 但对于 HTML 文档(或流)。

var doc = new HtmlDocument();
doc.LoadHtml(xml);

var anchors = doc.DocumentNode.SelectNodes("//a[starts-with(@href, '/abc/def')]");
foreach (var anchor in anchors.ToList())
    anchor.Remove();

var result= doc.DocumentNode.OuterHtml;

这会得到你想要的。

编辑:

如果您只想删除 href 属性,请将这一行 anchor.Remove() 更改为这一行 anchor.Attributes["href"].Remove();

【讨论】:

  • 哇,这东西太棒了。上面代码的唯一问题是它正在删除一个href的文本,在上面的例子中也是“信息”我怎么能避免呢?
  • @NoviceMe Alex 的代码删除了节点,你只想删除属性。选择属性并将其删除,或者查看 LB 的答案,它向您展示了操作方法(您可以结合两种技术:LB 使用 LINQ,而 Alex 使用 XPath)。
  • @NoviceMe,用代码更新了我的答案,仅删除 href 属性,而不是删除 whole 节点。
【解决方案3】:

如果 HTML 是格式良好的 XML(一目了然),您可以将 cdata 节点的文本加载到新的 XML 文档中,适当修改 XML,然后替换原始 cdata 节点的文本与您修改的文档的 XML 文本。

由于根据定义,原始 XML 文档中没有解析 cdata,这就是为什么您需要第二个。

【讨论】:

  • +1 比任何正则表达式都要好得多,后者总是处理 XML/HTML 的糟糕方法。如果不是有效的 XML,可以选择使用 HTMLTidy 或 TagSoup 使其有效。
  • @Abel 这并没有完全消除使用正则表达式的需要,它只是需要在每个节点内容上多次使用它。答案也无助于帮助用户解决他们面临的实际问题。
  • @Alain:正则表达式应该用于匹配文本,而不是结构化文档。是的,为了匹配属性href 中的文本值,您可以使用正则表达式(尽管在这种情况下可以使用其他方法)。正则表达式本身没有问题,只是不要将它们与结构化数据一起使用并尝试替换已经存在的内容。 ab c&amp;#x61;b cab&amp;nbsp;c 都可以是相同的文本(最后一个需要 dtd),使用正则表达式是不可能的。 XML解析后,这一切就变成了ab c
  • @Abel 这绝对消除了对 reg ex 的需要。单个 xpath 语句执行节点选择。如果有一个好的解析器(在这种情况下是 xml 或 html)可用,我永远不会推荐 reg ex
【解决方案4】:

注意:我不建议在整个 XML 字符串上运行此 Regex - 因为大多数人都认为这是不好的。在正确遍历期间,可以并且应该在文档的各个节点上运行以下正则表达式。 该解决方案已作为整个 xmlString 上的单个正则表达式替换发布,因为这是用户请求的内容,并且他们无法适应针对他们特定情况的正则表达式语句 - 我逐个字符地编写代码以匹配他们打算如何尽可能接近地使用它。


要去除所有以/abc/def/ 开头的网址的href 标签,最好使用正则表达式:

result = Regex.Replace(xmlString, @"<a href=\"/abc/def/.*>(.*)</a>", "$1");

以下 cmets 的跟进

MSDN

在指定的输入字符串内,用指定的替换字符串替换所有匹配指定正则表达式的字符串。

这种替换将发生在所有实例上,而不仅仅是第一个。如果其余的都不起作用,那是因为它们的某些不同之处与正则表达式不匹配。

例如,如果在某些情况下 a 和 href 之间有多余的空格,或者在 href 字段之前指定了目标字段,则需要使用不太具体的替换:

result = Regex.Replace(str, @"<a.*href=\"/OST/OSTdisplay/.*>(.*)</a>", "$1");

【讨论】:

  • 快速编辑 - 忘记了分组的语法是 (group) 并由 $1 引用(与 Visual Studio 不同,它使用完全不同的语法:{group} 和 /1 :p)跨度>
  • 我不想删除所有以 /abc/def 开头的 href 标签。你能告诉我那个正则表达式是什么吗?
  • 哦。好吧,那就把它改成@"&lt;a href=\"/abc/def/.*&gt;(.*)&lt;/a&gt;"
  • 正则表达式非常简单,只要记住the characters that need to be escaped
  • 很抱歉再次打扰您。它应该只删除 href 标记而不是其中的文本。上面的表达式也删除了文本。
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-05
  • 1970-01-01
  • 1970-01-01
  • 2017-04-21
  • 1970-01-01
相关资源
最近更新 更多