2011-09-19 16 views
10

Czy istnieje prosty sposób na uzyskanie wszystkich węzłów z dokumentu XML? Potrzebuję każdego węzła, childnode i tak dalej, aby sprawdzić, czy mają pewne atrybuty.C#: Pobieranie wszystkich węzłów dokumentu XML

Czy będę musiał przeczołgać dokument, prosząc o childnodes?

+0

Jeśli chcesz sprawdzić pewne atrybuty, nie musisz przechodzić przez _wszysty węzeł_ (węzeł tekstowy, węzeł dokumentu, węzeł komentarza). Wystarczy przejść przez każdy węzeł elementu lub każdy węzeł atrybutu (tj. Za pomocą LINQ lub XSLT). Węzły elementów są jedynym typem węzła z atrybutami. – Abel

+0

Jak duży jest ten dokument? Czy warto byłoby zoptymalizować? –

+0

Zobacz linki [http://forums.asp.net/t/1285409.aspx/1](http://forums.asp.net/t/1285409.aspx/1) [http: //www.developerfusion .com/article/4078/reading-storing-and-transforming-xml-data-in-net/5 /] (http://www.developerfusion.com/article/4078/reading-storing-and-transforming-xml -data-in-net/5 /) [http://weblogs.asp.net/karan/archive/2010/04/29/parse-an-xml-file.aspx](http://weblogs.asp. net/karan/archive/2010/04/29/parse-an-xml-file.aspx) – Prasanth

Odpowiedz

20

W LINQ to XML niezwykle proste:

XDocument doc = XDocument.Load("test.xml"); // Or whatever 
var allElements = doc.Descendants(); 

więc znaleźć wszystkie elementy z konkretnego atrybutu, na przykład:

var matchingElements = doc.Descendants() 
          .Where(x => x.Attribute("foo") != null); 

Zakładamy, że chcesz wszystkie elementy . Jeśli chcesz wszystkie węzły węzłów (w tym węzły tekstowe itp., Ale nie, w tym atrybuty jako oddzielne węzły), należy zamiast tego użyć DescendantNodes().

EDYCJA: Przestrzenie nazw w LINQ do XML są ładne. Można by użyć:

var matchingElements = doc.Descendants() 
          .Where(x => x.Attribute(XNamespace.Xmlns + "aml") != null); 

lub do innej przestrzeni nazw:

XNamespace ns = "http://some.namespace.uri"; 

var matchingElements = doc.Descendants() 
                         .Where(x => x.Attribute(ns + "foo") != null); 
+0

@Jeff: Czy chodzi ci o używanie indeksu zamiast wywoływania metody, aby uzyskać atrybut? Jeśli tak, naprawiono. Jeśli nie, jestem zdezorientowany ... –

+0

Tak, właśnie o to mi chodziło. :) –

+0

Doskonały. Abit nie ma związku, ale jak powinienem sprawdzić atrybuty, które mają przestrzeń nazw w ich nazwie? Podobne do: xmlns: aml? Mówi, że nie mogę: jest w moim imieniu. – Nicolai

6

zobaczyć tutaj: Iterating through all nodes in XML file

krótko:

string xml = @" 
    <parent> 
     <child> 
     <nested /> 
     </child> 
     <child> 
     <other> 
     </other> 
     </child> 
    </parent> 
    "; 

    XmlReader rdr = XmlReader.Create(new System.IO.StringReader(xml)); 
    while (rdr.Read()) 
    { 
    if (rdr.NodeType == XmlNodeType.Element) 
    { 
     Console.WriteLine(rdr.LocalName); 
    } 
    } 
+1

Ta metoda jest zazwyczaj bardzo, bardzo szybka w porównaniu do XDocument i innych metod DOM-podobnych. – Abel

0
protected void Page_Load(object sender, EventArgs e) 
    { 

      XmlDocument document = new XmlDocument(); 

      string xmlStr; 
      using (var wc = new WebClient()) 
      { 
       xmlStr = wc.DownloadString("test.xml"); 
      } 

      var xmlDoc = new XmlDocument(); 

      xmlDoc.LoadXml(xmlStr); 

      XmlNode xnod = xmlDoc.DocumentElement; 

      AddWithChildren(xnod, 1); 
} 
+0

Zrzuty kodów bez wyjaśnienia rzadko są pomocne. Zastanów się nad dodaniem kontekstu do swojej odpowiedzi. – Chris

0
public void AddWithChildren(XmlNode xnod, Int32 intLevel) //,XmlDocument xmlDoc 
    { 
     List<IEnumerable> item = new List<IEnumerable>(); 
     XmlNode xnodWorking; 
     String strIndent = new string('-', 2 * intLevel); 
     String strIndent1 = new string('@', 2 * intLevel); 
     if (xnod.NodeType == XmlNodeType.Element) 
     { 
      item.Add(new ListXML(strIndent + xnod.Name, strIndent + xnod.Name, "")); 
      XmlNamedNodeMap mapAttributes = xnod.Attributes; 
      foreach (XmlNode xnodAttribute in mapAttributes) 
      { 
       item.Add(new ListXML(strIndent1 + xnodAttribute.Name, strIndent1 + xnodAttribute.Name, "")); 
      } 
      if (xnod.HasChildNodes) 
      { 
       xnodWorking = xnod.FirstChild; 
       while (xnodWorking != null) 
       { 
        AddWithChildren(xnodWorking, intLevel + 1); 
        xnodWorking = xnodWorking.NextSibling; 
       } 
      } 
     } 
    } 
3

Moim zdaniem najprostszym rozwiązaniem jest przy użyciu XPath. To również działa, jeśli masz .NET 2:

var testDoc = new XmlDocument(); 
       testDoc.LoadXml(str); 
       var tmp = testDoc.SelectNodes("//*"); // match every element 
Powiązane problemy