2011-11-28 24 views
10

powiedzmy, że mam następujące XML (krótki przykład)Używanie XPath do analizowania dokumentu XML

<rows> 
    <row> 
     <name>one</name> 
    </row> 
    <row> 
     <name>two</name> 
    </row> 
</rows> 

Staram się analizować to za pomocą XmlDocument i XPath (ostatecznie więc mogę zrobić listę wierszy).

Na przykład ...

XmlDocument doc = new XmlDocument(); 
doc.LoadXml(xml); 

foreach(XmlNode row in doc.SelectNodes("//row")) 
{ 
    string rowName = row.SelectSingleNode("//name").InnerText; 
} 

Dlaczego w moim pętli foreach jest rowName zawsze "jeden"? Spodziewam się, że będzie to "jeden" w pierwszej iteracji, a "dwa" w drugiej.

Wygląda na to, że // nazwa dostaje pierwszą instancję w dokumencie, a nie pierwszą instancję w wierszu, jak można się było spodziewać. Wszakże wywołuję metodę w węźle "wiersz". Jeśli jest to "po prostu jak to działa", czy ktoś może wyjaśnić, w jaki sposób mogę go zmienić, aby działał zgodnie z moimi potrzebami?

Dziękuję

+0

jak o wybranie go przez // wiersza/nazwy? czy to działa? – Steve

Odpowiedz

14

Czy kod zostanie zaksięgowana rzeczywiście poprawna? Dostaję błąd kompilacji w wierszu.SelectNode(), ponieważ nie jest członkiem XmlNode.

W każdym razie, mój przykład powyżej prac, ale przyjmuje tylko jeden <name> węzeł w obrębie węzła <row> więc może trzeba użyć SelectNodes() zamiast SelectSingleNode() jeśli nie jest to przypadek.

Jak pokazali inni, użyj .InnerText, aby uzyskać tylko wartość.

+0

Dzięki, a Twoja prędkość przyniesie Ci pełne 25! Doszedłem do pojedynczego uderzenia, ale kiedy popełniłem błąd, poddałem się i napisałem funkcję przeszukiwania węzłów potomnych. Jestem teraz na dobrej ścieżce XPath :) – musefan

+0

Zapomniałem '.InnerText' w moim oryginalnym wpisie, naprawionym teraz ... i błędnie wpisanym' SelectSingleNode' – musefan

3

Użyj ścieżki względnej, np. string rowName = row.SelectSingleNode("name").InnerText;.

2

Problem jest w swoim drugim kwerendy XPath:

//row 

ten ma zasięg globalny, więc nie ma znaczenia, gdzie zadzwonić z, to wybrać wszystkierow elementy.

To powinno działać, jeśli zastąpić wyraz z:

.//row 
2

użyłbym SelectSingleNode, a następnie własności innerText.

var rowName = row.SelectSingleNode("name").InnerText; 
4

Użyj LINQ do XML. Obejmują using System.Xml.Linq; w pliku kodu, a następnie wykonaj poniższy kod, żeby dostać swoją listę

XDocument xDoc = XDocument.Load(filepath); 
IEnumerable<XElement> xNames; 

xNames = xDoc.Descendants("name"); 

To daje listę elementów nazw. Następnie, jeśli chcesz włączyć, że w List<string> prostu to zrobić:

List<string> list = new List<string>(); 
foreach (XElement element in xNames) 
{ 
    list.Add(element.value); 
} 
4

Twój drugi XPath zaczyna //. Jest to skrót od /descendant-or-self::node(), który można zobaczyć od /, co oznacza, że ​​wyszukuje z katalogu głównego dokumentu, niezależnie od kontekstu, w którym go używasz.

Prawdopodobnie chcesz jeden:

var rowName = row.SelectSingleNode("name"); 

znaleźć name węzły, które są natychmiastowe dzieci z row lub

var rowName = row.SelectSingleNode(".//name"); 

znaleźć name węzłów * nigdzie pod the rzędu . Note the .` w tym drugim xpath, który powoduje, że xpath zaczyna się od węzła kontekstu.

0

Użyj następującego

 doc.LoadXml(xml); 

      foreach(XmlNode row in doc.SelectNodes("/rows/row")) 
      { 
       string rowName = row.SelectSingleNode("//name").InnerText.ToString(); 
      } 
+0

To spowoduje ten sam problem, na początku, przepraszam – musefan

+0

Pozwól mi zmienić zdanie na lol, pozbyłem się/wierszy i zrobiłem to jako // wiersz i zadziałało to dla mnie. –

Powiązane problemy