为什么System.Xml.XmlDocument
上的XPath找不到相邻的文本和CData节点?
var raw_xml = @"
<root>
<test>
<![CDATA[This is a CDATA node]]>And this is an adjacent text node
</test>
</root>
";
var doc = new XmlDocument();
doc.LoadXml(raw_xml);
var results = doc.SelectNodes("/root/test/text()");
Console.WriteLine(results.Count); // gives: 1
Console.WriteLine(results[0].Value); // gives: This is a CDATA node
Console.WriteLine(results[0].Name); // gives: #cdata-section
Console.WriteLine(results[0].GetType().FullName); // gives: System.Xml.XmlCDataSection
Console.WriteLine(results[0].NextSibling.Name); // gives: #text
Console.WriteLine(results[0].NextSibling.Value.Trim()); // gives: And this is an adjacent text node
我们可以从上面看到CDATA节点有文本节点作为它的下一个兄弟,所以你会认为表达式/root/test/text()
会找到它。
与XPath相同的结果:/root/test/node()
答案 0 :(得分:2)
使用XML文档时,您可能习惯于文档对象模型(DOM),其中CDATA节点与文本节点分开。 XPath数据模型将text()
个节点视为所有相邻的CDATA和文本DOM节点兄弟节点。
因此,尝试编写将不是相邻系列的第一个特定DOM文本/ CDATA节点的查询将失败,例如:
var results = doc.SelectNodes("/root/test/text()[starts-with(., 'And')]");
Console.WriteLine(results.Count); // gives: 0
确实,试图选择&#34;文本&#34;其他XPath的DOM节点意味着:
var results = doc.SelectNodes("/root/test/text()[contains(., 'text node')]");
将提供与OP中的初始/root/test/text()
查询相同的结果。
你看到的是两个模型的混合 - 来自XPath查询的结果被转换回DOM节点;所以它为你提供了第一个text()
节点,在这种情况下,它是CDATA节点。
如果您确实需要在XPath中使用单独的文本和CDATA节点,则需要确保XML注释分隔源文档中的节点,如下所示:
<root>
<test>
<![CDATA[This is a CDATA node]]><!-- separator comment -->And this is an adjacent text node
</test>
</root>
这样
var results = doc.SelectNodes("/root/test/text()");
Console.WriteLine(results.Count);
将提供2
。