2009-08-04 39 views
17
Dim xml = <Root> 
      <Parent id="1"> 
       <Child>Thomas</Child> 
      </Parent> 
      <Parent id="2"> 
       <Child>Tim</Child> 
       <Child>Jamie</Child> 
      </Parent> 
      </Root> 

Dim parents = xml.Elements 

En este caso, children incluye todos los elementos principales y todos los elementos secundarios. ¿Cuál es la mejor manera de tomar solo los descendientes directos de <Root>?LINQ to XML: ¿cómo obtengo solo descendientes directos de un XElement?

¿Debo escribir una consulta LINQ que seleccione elementos donde parent = <Root>? ¿O hay algún método incorporado que me falta que pueda obtener esto para mí?

EDIT: Tuve cierta confusión entre XElement.Elements y XElement.Descendants. Como señaló Ruben Bartelink, XElement.Elements me dará exactamente lo que estaba buscando.

+0

¿Se puede editar con el encantamiento real que terminó usando? Por cierto, descargue LINQPAd y pruébelo: es genial para probar cosas como esta. Consulte ejemplos en http://www.dimecasts.net/Casts/ByTag/LinqPad –

Respuesta

17

Resumen Exec - que desea:

xml.Elements.Select(function(element) new XElement(element.Name,element.Attributes)) 

Primera respuesta:

XElement.Descendants, o se trata de una pregunta con trampa? : P There's an example of usage of Descendants here

respuesta revisada, gracias Tormod - algo que se sentía mal !:

Elementos da descendientes directos, ya que usted está buscando. Descendientes da la jerarquía completa [como alegas que hace Elements]. .! (El ejemplo que vincula a deja esto claro disculpas por la confusión

Así que, finalmente, lo que estás buscando es (esta vez en VB):

Dim xml = <Root> 
     <Parent id="1"> 
      <Child>Thomas</Child> 
     </Parent> 
     <Parent id="2"> 
      <Child>Tim</Child> 
      <Child>Jamie</Child> 
     </Parent> 
     </Root> 

REM All nodes two levels down in the hierarchy 
Dim level2Nodes = xml.Elements.SelectMany(function(element) element.Elements) 
level2Nodes.Dump 

REM All Child nodes, no matter where they are: 
Dim children = xml.Descendants("Child") 

Cada uno de los cuales dará lugar a que el 3 `` `elementos para diferentes razones, según se regulan en los REM

(pasta de lo anterior directamente en LINQPad en modo de declaración VB)

ahora veo lo que podría usted ser confuso -. cuando se utiliza elementos y miro en un visualizador, todavía estás ver a los niños: -

Dim parents = xml.Elements 

Si sólo desea los nombres reales, puede usar algo como:

Dim parentNames = xml.Elements.Select(function(element) element.Name) 

Tenga en cuenta que en cada uno de estos casos, que está recibiendo dos resultados.

Si realmente quiere que se deben eliminar los Chidren, que desea:

Dim parentElements = xml.Elements.Select(function(element) new XElement(element.Name,element.Attributes)) 

¿Se puede extender su pregunta para mostrar lo que realmente está buscando?

+3

El método Descendants() obtiene todos los descendientes, no solo los descendientes directos. En este caso, los descendientes de "raíz" incluirían también todos los elementos secundarios. – Tormod

+0

@Tormod, ¿estás seguro? Mira el ejemplo? Si no, ¿cuál es la diferencia entre Descendientes y Elementos? –

+0

@Tormod, mea culpa, edición! –

-1

¿Por qué no utilizar XPath?

Dim myXML As var = New XmlDocument() 
myXML.Load(myXML.xml) 

For Each node As XmlNode In myXML.SelectNodes("//") 
    Dim myVar As var = node.SelectSingleNode("Parent").InnerText 
Next 

Tome esto con una pizca de sal - Acabo de convertirlo de C# a VB.

+0

XLinq lo hace muy bien como es [una vez que uno supera la confusión de qué método usar: P] –

+1

Bastante: P Voy a tener que investigarlo, supongo que XPath se está quedando obsoleto si todos se están moviendo a XLinq! –

0

Si todos los descendientes directos tienen el mismo nombre de elemento conocido, y este nombre de elemento no puede aparecer en otro nivel, puede usar xml.Descendants ("Parent").

15

XElement.Elements obtiene la colección de elementos secundarios. Por ejemplo ...

var s = @"<root> 
      <e1> 
       <e2> 
       </e2> 
      </e1> 
      <e1> 
       <e2> 
       </e2> 
      </e1> 
      <e1> 
       <e2> 
       </e2> 
      </e1> 
      </root>"; 

var doc = XElement.Load(new StringReader(s)); 

Console.WriteLine(doc.Elements().Count()); // 3 
Console.WriteLine(doc.Descendants().Count()); //6 
2

Usando Linq podemos hacer eso.

string s = "<Root><Parent id=\"1\"><Child>Thomas</Child></Parent><Parent id=\"2\"><Child>Tim</Child><Child>Jamie</Child></Parent></Root>"; 
XDocument xdoc = XDocument.Parse(s); 
foreach (XElement DirectChild in xdoc.Descendants().Where(child => child.Parent == xdoc.Root)) 
{ 
//Do stuff here 
} 

Espero que esto ayude. Gracias.

Cuestiones relacionadas