2009-08-04 13 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 

In questo caso, children include tutti gli elementi padre e tutti gli elementi figlio. Qual è il modo migliore per afferrare solo i discendenti diretti di <Root>?LINQ to XML: come ottengo solo i discendenti diretti di XElement?

Devo scrivere una query LINQ che seleziona elementi in cui parent = <Root>? O c'è qualche metodo integrato che mi manca e che può ottenere questo per me?

MODIFICA: Ho avuto un po 'di confusione tra XElement.Elements e XElement.Descendants. Come ha sottolineato Ruben Bartelink, XElement.Elements mi darà esattamente quello che stavo cercando.

+0

Puoi modificare l'incantesimo che hai utilizzato? Per favore, scarica LINQPAd e provalo, è ottimo per testare cose del genere. Vedi esempi su http://www.dimecasts.net/Casts/ByTag/LinqPad –

risposta

17

sintesi Exec - desideri:

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

Prima risposta:

XElement.Descendants, o è una domanda trabocchetto? : P There's an example of usage of Descendants here

risposta riveduta, grazie Tormod - qualcosa che si sentiva male !:

Elementi dà discendenti diretti, come si sta cercando. I discendenti danno la gerarchia completa [come si asserisce che gli Elementi lo facciano]. .! (L'esempio che ho legato alla chiarisce questo punto Ci scusiamo per la confusione

Così, finalmente, quello che stai cercando è (questa volta in 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") 

Ognuno dei quali produrrà voi il 3 `` `elementi per diversi motivi contemplati nelle REM

(pasta di quanto sopra direttamente in LINQPad in modalità dichiarazione VB)

ora vedo che cosa potrebbe si essere fonte di confusione -. quando si utilizza Elements e guardo a questo in un visualizzatore, sei ancora vedere i bambini: -

Dim parents = xml.Elements 

Se desideri solo i nomi reali, si può usare qualcosa di simile a:

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

Si noti che in ognuno di questi casi, si stanno ottenendo due risultati.

Se davvero si vuole mettere a nudo le chidren, si vuole:

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

Puoi estendere la vostra domanda per mostrare ciò che siete veramente cercando?

+3

Il metodo Descendants() ottiene tutti i discendenti, non solo i discendenti diretti. In questo caso, i discendenti di "root" includeranno anche tutti gli elementi secondari. – Tormod

+0

@ Tempod, sei sicuro? Vedi l'esempio? In caso contrario, qual è la differenza tra discendenti ed elementi? –

+0

@Tormod, mea culpa, editing! –

-1

Perché non utilizzare 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 

Prendere questo con un pizzico di sale - Ho appena convertito da C# a VB.

+0

XLinq lo fa in modo abbastanza preciso [una volta superata la confidenza di quale metodo usare: P] –

+1

Abbastanza corretto: P Dovrò esaminarlo, suppongo che XPath stia diventando obsoleto se ti stai muovendo tutti su XLinq! –

0

Se tutti i discendenti diretti hanno lo stesso nome di elemento noto e questo nome di elemento non può essere visualizzato in un altro livello, è possibile utilizzare xml.Descendants ("Parent").

15

XElement.Elements ottiene la raccolta di elementi figlio. Ad esempio ...

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

Utilizzando Linq possiamo farlo.

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 
} 

Spero che questo aiuti. Grazie.