提问人:freefaller 提问时间:1/27/2023 最后编辑:freefaller 更新时间:1/28/2023 访问量:60
在 .Net 中将 CDATA 节点转换为编码字符串
Convert CDATA node to encoded string in .Net
问:
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 列中时,将自动删除 并对内部文本进行编码...这是 SQLServer 的标准,它不“做”。<![CDATA[..]]>
CDATA
我的问题是我有复杂的代码,它采用一个类的两个实例,并且审计跟踪它们之间的差异......一个或多个可以是包含 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&cd</one><two><inner>xy<z</inner></two></data>
在 .Net 中是否有一种简单的方法来处理手动生成的 XML 并将每个节点转换为其编码版本,以便我可以将字符串与 SQLServer 返回的字符串进行比较?CDATA
有没有一个 XPath 可以找到所有这些元素?SelectNodes
(在任何人陈述之前,显而易见的解决方案是首先不要在手动创建 XML 时使用......但是,由于实例数量庞大,这是不可能的。CDATA
答:
只需一个循环即可轻松实现: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 < 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&cd</one><two><inner>xy<z</inner></two><three><inner>a < 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>
评论
XmlDocument
XDocument
Regex.Replace