And this is an adjacent text node ";var doc = new XmlDocument();doc." />

Почему XPath поверх System.Xml.XmlDocument не находит смежные узлы текста и CData?

c# xml xpath cdata xpath-1.0

168 просмотра

1 ответ

Почему XPath поверх System.Xml.XmlDocumentне находит соседние узлы текста и 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()

Автор: Keith Hall Источник Размещён: 28.10.2019 11:13

Ответы (1)


2 плюса

Решение

При работе с документами XML вы, вероятно, привыкли к объектной модели документов (DOM), где узлы CDATA отделены от текстовых узлов. Модель данных XPath рассматривает text()узлы как все смежные CDATA и текстовые узлы DOM вместе.

Поэтому попытка написать запрос, который будет конкретным узлом DOM text / CDATA, который не является первым из соседней серии, завершится неудачей, например:

var results = doc.SelectNodes("/root/test/text()[starts-with(., 'And')]");
Console.WriteLine(results.Count); // gives: 0

и действительно, попытка выбрать «текстовый» узел DOM другим XPath означает:

var results = doc.SelectNodes("/root/test/text()[contains(., 'text node')]");

даст те же результаты, что и первоначальный /root/test/text()запрос в OP.

То, что вы видите, представляет собой смесь двух моделей - результат запроса XPath переводится обратно в узел DOM; поэтому он дает вам первый text()узел, который в данном случае является узлом CDATA.

Если вам действительно нужно работать с отдельными узлами text и CDATA в XPath, вам нужно убедиться, что 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.

Автор: Keith Hall Размещён: 08.04.2016 06:31
Вопросы из категории :
32x32