2013-07-17 5 views
6

Ich habe ein XML-Beispiel:Wie erhalten Sie alle XML-Knoten mit demselben Namen, ohne deren Level zu kennen?

<Fruits> 
    <Red_fruits> 
     <Red_fruits></Red_fruits> 
    </Red_fruits> 
    <Yellow_fruits> 
     <banana></banana> 
    </Yellow_fruits> 
    <Red_fruits> 
     <Red_fruits></Red_fruits> 
    </Red_fruits> 
</Fruits> 

I 4 Red_fruits Tags, 2 von ihnen teilt die gleichen ParentNode (Früchte), möchte ich denen erhalten, die die gleiche ParentNode haben.

Aber ich will nur diejenigen, die den gleichen Namen haben (Red_fruits), was bedeutet, Yellow_fruits-Tag ist nicht enthalten.

Dies ist die Art, wie ich jetzt die Sprache C# tue:

XmlDocument doc = new XmlDocument(); 
string selectedTag = cmbX.text; 

if (File.Exists(txtFile.text)) 
{ 
    try 
    { 
     //Load 
     doc.Load(cmbFile.text); 

     //Select Nodes 
     XmlNodeList selectedNodeList = doc.SelectNodes(".//" + selectedTag); 
    } 
    Catch 
    { 
     MessageBox.show("Some error message here"); 
    } 
} 

Dies kehrt mir alle red_fruits, nicht nur diejenigen, die Früchte gehört.

Ich kann XmlNodeList = doc.SelectNodes ("/ Fruits/Red_fruits") nicht machen, weil ich diesen Code verwenden möchte, um zufällige XML-Dateien zu lesen, daher kenne ich nicht den genauen Namen, den ein bestimmter Knoten haben wird. Ich muss nur alle Knoten mit demselben Namen und derselben Ebene in eine XmlNodeList mit C# Language setzen.

Gibt es eine Möglichkeit, dies zu erreichen, ohne LINQ zu verwenden? Wie geht das?

+2

Haben Sie wirklich einen Versuch ohne einen Haken? Ich glaube nicht –

+0

Warum die Einschränkung "ohne LINQ"? Was ich tun würde ist, die Ergebnisse dessen, was Sie haben, nach Tiefe zu gruppieren und dann die gewünschte Gruppe auszuwählen. – millimoose

+0

Catch tut nichts zeigt nur eine Fehlermeldung, werde den Beitrag mit catch bearbeiten –

Antwort

3

Wenn Sie einfach nur ich versuchen, die „nächste“ oder „Zurück“ Iteration eines einzelnen Knotens zu finden, können Sie folgendes tun und dann vergleichen Sie es mit dem Namen

XmlNode current = doc.SelectSingleNode("Fruits").SelectSingleNode("Red_fruits"); 

XmlNode previous = current.NextSibling; 
XmlNode next = current.NextSibling; 

und Sie können bis iterieren finden Sie den richtigen Geschwister

while(next.Name != current.Name) 
{ 
    next = next.NextSibling; 
} 

oder Sie können sogar Ihre Liste erhalten, indem die ‚Eltern‘ Eigenschaft Aufruf

XmlNodeList list = current.ParentNode.SelectNodes(current.Name); 
+1

Das ist genau das, was ich brauchte, diese einfache Zeile: XmlNodeList list = current.ParentNode.SelectNodes (current.Name); Arbeitete gut. –

+1

Gonna die anderen Lösungen von Ihnen und den anderen getestet, aber vielen Dank im Voraus. –

1

Im schlimmsten Fall können Sie die XMLNode-Elemente in selectedNodeList durchlaufen und die ParentNode-Eigenschaften überprüfen. Bei Bedarf können Sie bei der ParentNode-Überprüfung rekursiv arbeiten und die Anzahl der erforderlichen Schritte zum Erreichen des Stammknotens zählen. Dies würde Ihnen die Tiefe eines Knotens geben. Oder Sie können den ParentNode auf jeder Ebene vergleichen, um festzustellen, ob es sich um das übergeordnete Element handelt, an dem Sie interessiert sind, wenn dieses übergeordnete Element nicht das Stammverzeichnis ist.

public void Test(){ 


     XmlDocument doc = new XmlDocument(); 
     string selectedTag = cmbX.text; 

     if (File.Exists(txtFile.text)) 
     { 
      try 
      { 
       //Load 
       doc.Load(cmbFile.text); 

       //Select Nodes 
       XmlNodeList selectedNodeList = doc.SelectNodes(".//" + selectedTag); 
       List<XmlNode> result = new List<XmlNode>(); 
       foreach(XmlNode node in selectedNodeList){ 
        if(depth(node) == 2){ 
         result.Add(node); 
        } 
       } 
       // result now has all the selected tags of depth 2 
      } 
      Catch 
      { 
       MessageBox.show("Some error message here"); 
      } 
     } 

    } 

    private int depth(XmlNode node) { 
     int depth = 0; 
     XmlNode parent = node.ParentNode; 
     while(parent != null){ 
      parent = node.ParentNode; 
      depth++; 
     } 
     return depth; 
    } 
5

Ein Verständnis über die Verwendung von Einzel Slash / und Double Slash // hier helfen kann.

Mal sehen, wie / und // in Bezug auf den Wurzelknoten arbeiten. Wenn / am Anfang eines Pfades verwendet wird:

/a 

wird es einen absoluten Pfad definiert a relativ zu der Wurzel zu dem Knoten. In diesem Fall wird es nur a Knoten im Stamm der XML-Struktur finden.

Wenn // am Anfang eines Weges verwendet wird:

//a 

es einen Pfad a einer beliebigen Stelle innerhalb des XML-Dokuments mit dem Knoten definieren. In diesem Fall wird es a Knoten finden, die sich in beliebiger Tiefe innerhalb der XML-Baumstruktur befinden.

Diese XPath-Ausdrücke können auch in der Mitte eines XPath-Werts verwendet werden, um Vorfahren-Nachkommen-Beziehungen zu definieren. Wenn / in der Mitte eines Pfads verwendet wird:

/a/b 

wird es einen Pfad definieren b Knoten, der ein unmittelbarer direkter Nachkomme ist (dh ein Kind.) Des Knotens a.

// Wenn in der Mitte eines Pfads verwendet:

/a//b 

es wird einen Pfad definieren b Knoten, die ANY Nachkomme des Knotens a ist.

auf Ihre Frage zurückzukommen:

// mit GetElementsByTagName() return alle Elemente Namen mit: Red_Fruits

XmlDocument doc = new XmlDocument(); 
XmlNodeList nodes= doc.GetElementsByTagName("Red_Fruits"); 

// Mit SelectNodes() Methode

XmlNodelist nodes = doc.SelectNodes("//Fruits/Red_Fruits"); 

// Diese wählt alle Elemente, die Kinder des Elements <Fruits> sind.

Falls <Fruits> das Wurzelelement ist, verwenden Sie den Xpath: /Fruits/Red_Fruits. [ein einzelner Schrägstrich /]

Verwandte Themen