2016-04-08 6 views
1

Warum XPath über ein System.Xml.XmlDocument nicht neben Text und CData Knoten finden?Warum findet XPath über ein System.Xml.XmlDocument keinen angrenzenden Text und keine CData-Knoten?

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 

Wir können aus dem oben sehen, dass der CDATA-Knoten den Textknoten hat, wie es nächstes Geschwister ist, so würden Sie denken, dass der Ausdruck /root/test/text() würde es finden.

gleiche Ergebnisse mit XPath: /root/test/node()

+0

Betrachten wir die Frage 'Warum XPath über einen System.Xml.XmlDocument nicht neben Text zu ändern und CData Knoten finden?' Wie das ganze Problem und Ihre Antwort auf die DOM-Implementierung im .NET Framework und Ihre Annahme spezifischer "Wir können von oben sehen, dass der CDATA-Knoten den Textknoten als nächstes Geschwister hat, also würden Sie denken, dass der Ausdruck/root/test/text()" keine Basis im XPath-Datenmodell hat, das keine CDATA kennt Knoten. –

+0

@Martin, guter Punkt - danke. Ich habe das OP aktualisiert :) –

Antwort

2

Wenn mit XML-Dokumenten arbeiten, werden Sie wahrscheinlich auf das Document Object Model (DOM) verwendet, wobei CDATA Knoten Textknoten getrennt ist. Das XPath-Datenmodell sieht text() Knoten als alle benachbarten CDATA- und Text-DOM-Knoten-Geschwister zusammen.

Daher versuchen, eine Abfrage zu schreiben, die eine spezifische DOM text/CDATA Knoten, der nicht der erste einer benachbarten Serie wird fehlschlagen ist, zum Beispiel:

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

und in der Tat versucht, die "zu wählen Text“DOM-Knoten durch andere XPath bedeutet:

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

werden die gleichen Ergebnisse wie die anfängliche /root/test/text() Abfrage in dem OP geben.

Was Sie sehen, ist eine Mischung aus den beiden Modellen - das Ergebnis aus der XPath-Abfrage wird wieder in einen DOM-Knoten übersetzt; Es gibt also den ersten Knoten text(), der in diesem Fall der CDATA-Knoten ist.

Wenn Sie wirklich mit separatem Text und CDATA-Knoten in XPath arbeiten müssen, müssen Sie sicherstellen, dass ein XML-Kommentar die Knoten im Quelldokument, wie dies trennt:

<root> 
    <test> 
     <![CDATA[This is a CDATA node]]><!-- separator comment -->And this is an adjacent text node 
    </test> 
</root> 

so dass

var results = doc.SelectNodes("/root/test/text()"); 
Console.WriteLine(results.Count); 

wird 2 geben.

Verwandte Themen