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 

W tym przypadku children zawiera wszystkie elementy nadrzędne i wszystkie elementy podrzędne. Jaki jest najlepszy sposób na pobranie tylko bezpośrednich potomków z <Root>?LINQ do XML: jak uzyskać tylko bezpośrednich potomków XElement?

Czy powinienem napisać zapytanie LINQ, które wybiera elementy, w których parent = <Root>? A może brakuje jakiejś wbudowanej metody, która może mi pomóc?

EDYCJA: Miałem pewne zamieszanie między XElement.Elements i XElement.Descendants. Jak zauważył Ruben Bartelink, XElement.Elements da mi dokładnie to, czego szukam.

+0

Czy możesz edytować w prawdziwej inkantacji, której używałeś? BTW proszę pobrać LINQPAd i wypróbować - świetnie nadaje się do testowania takich rzeczy. Zobacz przykłady na http://www.dimecasts.net/Casts/ByTag/LinqPad –

Odpowiedz

17

Exec Podsumowanie - chcesz:

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

pierwsza odpowiedź:

XElement.Descendants, czy jest to podchwytliwe pytanie? : P There's an example of usage of Descendants here

Zmieniona odpowiedź, dzięki Tormod - coś czułem się źle !:

Elements daje bezpośrednich potomków, jak szukasz. Potomkowie podają pełną hierarchię [tak jak twierdzisz, że Elementy]. .! (Przykład I związana sprawia, że ​​ten wyraźny Przepraszamy za zamieszanie

Więc wreszcie, czego szukasz (tym razem w 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") 

z których każdy będzie cię otrzymując 3 `` `elementy różnych powodów, o których mowa w Rems

(wklej powyżej bezpośrednio do LINQPad w trybie wyciągu VB)

teraz widzę, co może być mylące cię. - podczas korzystania z elementów i wygląd w wizualizatorze wciąż jesteś widząc dzieci: -

Dim parents = xml.Elements 

Jeśli chcesz tylko rzeczywiste nazwy, można użyć coś takiego:

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

pamiętać, że w każdym z tych przypadków, dostajesz dwa wyniki.

Jeśli naprawdę chce się rozebrać na zewnątrz chidren, chcesz:

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

można rozszerzyć swoje pytanie, aby zobaczyć to, czego naprawdę szukasz?

+3

Metoda Descendants() pobiera wszystkich potomków, a nie tylko bezpośrednich potomków. W tym przypadku potomkowie "root" będą również obejmowali wszystkie elementy Child. – Tormod

+0

@Tormod, jesteś pewien? Zobacz przykład? Jeśli nie, to jaka jest różnica między potomkami a elementami? –

+0

@Tormod, mea culpa, edycja! –

-1

Dlaczego nie używać 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 

Weź to z przymrużeniem oka - po prostu przerobiłem go z C# na VB.

+0

XLinq robi to całkiem zgrabnie, tak jak jest [gdy ktoś ma wątpliwości co do jakiej metody użyć: P] –

+1

Wystarczająco uczciwe: P Będę musiał to sprawdzić, myślę, że XPath staje się nieaktualny, jeśli wszyscy jesteście w ruchu na XLinq! –

0

Jeśli wszyscy bezpośredni potomkowie mają tę samą nazwę znanego elementu, a nazwa tego elementu nie może pojawić się na innym poziomie, można użyć xml.Descendants ("Parent").

15

otrzymuje kolekcję elementów podrzędnych. Na przykład ...

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

Za pomocą Linq możemy to zrobić.

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 
} 

Mam nadzieję, że to pomoże. Dziękuję Ci.

Powiązane problemy