将CDATA节点转换为.Net中的编码字符串

np8igboo  于 2023-02-01  发布在  .NET
关注(0)|答案(1)|浏览(136)

TL;DR-在.Net和XmlDocument/XDocument中,是否有一种简单的方法(XPath?)可以找到CDATA节点,以便删除它们并对内容进行编码?
详细信息...

我的系统在很多情况下都需要手动构建XML字符串(例如字符串连接,而不是通过XmlDocument或XDocument构建),这些字符串可能包含多个<![CDATA[...]]>节点(可能出现在结构的任何级别)...例如

<data><one><![CDATA[ab&cd]]></one><two><inner><![CDATA[xy<z]]></inner></two></data>

当在SQLServer XML列中存储此数据时,<![CDATA[..]]>将自动删除,内部文本将被编码...这是不“执行”CDATA的SQLServer的标准。
我的问题是,我有复杂的代码,需要一个类的两个示例,并审计跟踪它们之间的差异...一个或多个可能是包含XML的字符串属性。
这会导致不匹配(从而导致审计跟踪条目),而实际上什么都没有更改,因为代码创建一种格式的XML,而SQLServer返回一种不同的格式,例如..

// Manually generated XML string...
<data><one><![CDATA[ab&cd]]></one><two><inner><![CDATA[xy<z]]></inner></two></data>
// SQLServer returned string...
<data><one>ab&amp;cd</one><two><inner>xy&lt;z</inner></two></data>

在.Net中是否有一种简单的方法来处理手动生成的XML并将每个CDATA节点转换为它的编码版本,以便我可以将该字符串与SQLServer返回的字符串进行比较?
有没有SelectNodes XPath可以找到所有这些元素?
(And在任何人说明之前,显而易见的解决方案是首先不要在手动创建XML时使用CDATA......但是,由于示例的数量太多,这是不可能的。)

gstyhher

gstyhher1#

只需一个foreach线圈和ReplaceChild

using System.Xml;

var doc = new XmlDocument();
doc.LoadXml(@"<data><one><![CDATA[ab&cd]]></one><two><inner><![CDATA[xy<z]]></inner></two><three><inner>a &lt; b</inner></three></data>");

foreach (var cdata in doc.SelectNodes("//text()").OfType<XmlCDataSection>())
{
   cdata.ParentNode.ReplaceChild(doc.CreateTextNode(cdata.Data), cdata);
}

Console.WriteLine(doc.OuterXml);

产出

<data><one>ab&amp;cd</one><two><inner>xy&lt;z</inner></two><three><inner>a &lt; b</inner></three></data>

另一种选择是使用XslCompiledTransform通过XSLT标识转换运行XML,例如:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

相关问题