[C#] Consulta un XDocument para elementos por nombre a cualquier profundidad


Answers

Un ejemplo que indica el espacio de nombres:

String TheDocumentContent =
@"
<TheNamespace:root xmlns:TheNamespace = 'http://www.w3.org/2001/XMLSchema' >
   <TheNamespace:GrandParent>
      <TheNamespace:Parent>
         <TheNamespace:Child theName = 'Fred'  />
         <TheNamespace:Child theName = 'Gabi'  />
         <TheNamespace:Child theName = 'George'/>
         <TheNamespace:Child theName = 'Grace' />
         <TheNamespace:Child theName = 'Sam'   />
      </TheNamespace:Parent>
   </TheNamespace:GrandParent>
</TheNamespace:root>
";

XDocument TheDocument = XDocument.Parse( TheDocumentContent );

//Example 1:
var TheElements1 =
from
    AnyElement
in
    TheDocument.Descendants( "{http://www.w3.org/2001/XMLSchema}Child" )
select
    AnyElement;

ResultsTxt.AppendText( TheElements1.Count().ToString() );

//Example 2:
var TheElements2 =
from
    AnyElement
in
    TheDocument.Descendants( "{http://www.w3.org/2001/XMLSchema}Child" )
where
    AnyElement.Attribute( "theName" ).Value.StartsWith( "G" )
select
    AnyElement;

foreach ( XElement CurrentElement in TheElements2 )
{
    ResultsTxt.AppendText( "\r\n" + CurrentElement.Attribute( "theName" ).Value );
}
Question

Tengo un objeto XDocument . Deseo consultar elementos con un nombre particular a cualquier profundidad usando LINQ. Cuando uso Descendants("element_name") , solo obtengo elementos que son hijos directos del nivel actual. Lo que estoy buscando es el equivalente de "// element_name" en XPath ... ¿debería usar XPath , o hay una forma de hacerlo con los métodos LINQ? Gracias.




Estoy usando el método de extensión XPathSelectElements que funciona de la misma manera que el método XmlDocument.SelectNodes :

using System;
using System.Xml.Linq;
using System.Xml.XPath; // for XPathSelectElements

namespace testconsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            XDocument xdoc = XDocument.Parse(
                @"<root>
                    <child>
                        <name>john</name>
                    </child>
                    <child>
                        <name>fred</name>
                    </child>
                    <child>
                        <name>mark</name>
                    </child>
                 </root>");

            foreach (var childElem in xdoc.XPathSelectElements("//child"))
            {
                string childName = childElem.Element("name").Value;
                Console.WriteLine(childName);
            }
        }
    }
}



(El código y las instrucciones son para C # y es posible que deba modificarse levemente para otros idiomas)

Este ejemplo funciona perfecto si desea leer desde un nodo principal que tenga muchos elementos secundarios, por ejemplo, consulte el siguiente XML;

<?xml version="1.0" encoding="UTF-8"?> 
<emails>
    <emailAddress>jdoe@set.ca</emailAddress>
    <emailAddress>jsmith@hit.ca</emailAddress>
    <emailAddress>rgreen@set_ig.ca</emailAddress> 
</emails>

Ahora con este código a continuación (tenga en cuenta que el archivo XML se almacena en los recursos (consulte los enlaces al final del fragmento para obtener ayuda sobre los recursos). Puede obtener cada dirección de correo electrónico dentro de la etiqueta "correos electrónicos".

XDocument doc = XDocument.Parse(Properties.Resources.EmailAddresses);

var emailAddresses = (from emails in doc.Descendants("emailAddress")
                      select emails.Value);

foreach (var email in emailAddresses)
{
    //Comment out if using WPF or Windows Form project
    Console.WriteLine(email.ToString());

   //Remove comment if using WPF or Windows Form project
   //MessageBox.Show(email.ToString());
}

Resultados

  1. jdoe@set.ca
  2. jsmith@hit.ca
  3. rgreen@set_ig.ca

Nota: Para la aplicación de consola y WPF o formularios de Windows, debe agregar "using System.Xml.Linq;" Con la directiva en la parte superior de su proyecto, para Console también necesitará agregar una referencia a este espacio de nombres antes de agregar la directiva Using. Además, para la consola no habrá ningún archivo de recursos de forma predeterminada en la "carpeta de propiedades", por lo que deberá agregar manualmente el archivo de recursos. Los artículos de MSDN a continuación, explican esto en detalle.

Agregar y editar recursos

Cómo agregar o eliminar recursos




Los descendientes harán exactamente lo que necesiten, pero asegúrese de haber incluido un nombre de espacio de nombres junto con el nombre del elemento. Si lo omite, probablemente obtendrá una lista vacía.