2011-09-19 46 views
10

¿Hay una manera simple de obtener todos los nodos de un documento xml? Necesito cada nodo, nodo infantil, etc., para verificar si tienen ciertos atributos.C#: Obtener todos los nodos del documento XML

¿O tendré que arrastrarme por el documento, preguntando por los ninos infantiles?

+0

Si necesita verificar ciertos atributos, no necesita pasar por cada nodo_ (nodo de texto, nodo de documento, nodo de comentario). Simplemente revise cada nodo de elemento o cada nodo de atributo (es decir, con LINQ o XSLT). Los nodos de elemento son el único tipo de nodo con atributos. – Abel

+0

¿Qué tan grande es este documento? Vale la pena optimizar? –

+0

Ver los enlaces [http://forums.asp.net/t/1285409.aspx/1](http://forums.asp.net/t/1285409.aspx/1) [http: //www.developerfusion .com/article/4078/reading-storage-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

Respuesta

20

En LINQ to XML es muy fácil:

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

Así que para encontrar todos los elementos con un atributo particular, por ejemplo:

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

Eso es suponiendo que usted quería todos los elementos . Si quiere todos los nodos (incluidos los nodos de texto, etc., pero no incluyendo atributos como nodos separados) usaría DescendantNodes() en su lugar.

EDITAR: Los espacios de nombres en LINQ to XML son agradables. Tendrá que utilizar:

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

o para un espacio de nombres diferentes:

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

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

@Jeff: ¿Quiere decir en términos de utilizar un indexador en lugar de una llamada a método para obtener un atributo? Si es así, arreglado. Si no, estoy confundido ... –

+0

Sí, eso es lo que quise decir. :) –

+0

Excelente. Abit no relacionado, pero ¿cómo verificaría los atributos, que tienen un espacio de nombres en su nombre? Me gusta: xmlns: aml? Dice que no puedo tener: 's en mi nombre de atributo. – Nicolai

6

ver aquí: Iterating through all nodes in XML file

poco:

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

Este método es generalmente muy, muy rápido en comparación con XDocument y otros métodos tipo DOM. – 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

Los volcados de código sin explicación rara vez son útiles. Considere agregar un contexto a su respuesta. – 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

En mi opinión, la solución más simple está utilizando XPath. También esto funciona si tiene .NET 2:

var testDoc = new XmlDocument(); 
       testDoc.LoadXml(str); 
       var tmp = testDoc.SelectNodes("//*"); // match every element 
Cuestiones relacionadas