2011-11-28 2 views
10

Diciamo che ho il seguente codice XML (un esempio veloce)Utilizzando XPath per analizzare un documento XML

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

sto cercando di analizzare questo utilizzando XmlDocument e XPath (in ultima analisi, in modo da poter fare una lista di righe).

Per esempio ...

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

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

Perché, nel mio ciclo foreach, è RowName sempre "uno"? Mi aspetto che sia "uno" nella prima iterazione e "due" nella seconda.

Sembra che // nome ottenga la prima istanza nel documento, piuttosto che la prima istanza nella riga come mi aspetterei. Dopotutto, sto chiamando il metodo sul nodo "row". Se questo è "solo come funziona", allora qualcuno può spiegare come posso cambiarlo per funzionare secondo i miei bisogni?

Grazie

+0

come su selezionandolo da // riga/nome? funziona? – Steve

risposta

14

è il codice che avete inviato in realtà corretta? Ricevo un errore di compilazione su row.SelectNode() in quanto non è un membro di XmlNode.

Comunque, il mio esempio di cui sopra funziona, ma assume un solo <name> nodo all'interno del nodo <row> quindi potrebbe essere necessario utilizzare SelectNodes() invece di SelectSingleNode() se questo non è il caso.

Come altri hanno mostrato, utilizzare .InnerText per ottenere solo il valore.

+0

Grazie, e la tua velocità ti dà tutti i 25! Ero arrivato a tentare con una singola barra, ma quando ho lanciato un errore ho rinunciato e ho scritto una funzione per cercare i nodi figli. Sono di nuovo sul buon vecchio XPath' ora però :) – musefan

+0

dimenticato il '.InnerText' nel mio post originale, fissato ora ... e compilato male' SelectSingleNode' – musefan

3

Utilizzare un percorso relativo, ad es. string rowName = row.SelectSingleNode("name").InnerText;.

2

Il problema è nella query XPath secondo:

//row 

Questo ha una portata globale, quindi non importa dove tu lo chiami da, selezionerà tuttirow elementi.

Si dovrebbe funzionare se si sostituisce l'espressione con:

.//row 
2

userei SelectSingleNode, e quindi la proprietà InnerText.

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

Utilizzare LINQ su XML. Includi using System.Xml.Linq; nel file di codice e poi fare il seguente codice per ottenere la vostra lista

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

xNames = xDoc.Descendants("name"); 

che vi darà un elenco degli elementi di nome. Poi, se si vuole trasformarla in un List<string> solo fare questo:

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

tuo secondo XPath inizia con //. Questa è un'abbreviazione per /descendant-or-self::node(), che è possibile vedere inizia con /, ovvero cerca dalla radice del documento, indipendentemente dal contesto in cui viene utilizzato.

probabilmente volete uno di:

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

per trovare i name nodi che sono figli immediati del row, o

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

per trovare name nodi * ovunque sotto the fila . Note the .` in questo secondo xpath che fa in modo che xpath inizi dal nodo di contesto.

0

Utilizza il seguente

 doc.LoadXml(xml); 

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

che causerà lo stesso problema come ho dovuto cominciare, mi dispiace – musefan

+0

Lasciami riformulare lol, mi sono sbarazzato delle/righe e l'ho fatto come // riga e ha funzionato per me. –