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

В этом случае children включает в себя все элементы родителя и все дочерние элементы. Каков наилучший способ захватить только прямые потомки из <Root>?LINQ to XML: как получить только прямые потомки XElement?

Должен ли я писать запрос LINQ, который выбирает элементы, где parent = <Root>? Или есть какой-то встроенный метод, который я пропускаю, чтобы получить это для меня?

EDIT: У меня было некоторое замешательство между XElement.Elements и XElement.Descendants. Как отметил Рубен Бартелькин, XElement.Elements даст мне именно то, что я искал.

+0

Можете ли вы изменить в действительном заклинании, в котором вы закончили использовать? BTW, пожалуйста, скачайте LINQPAd и попробуйте - он отлично подходит для тестирования таких вещей. См. Примеры по адресу http://www.dimecasts.net/Casts/ByTag/LinqPad –

ответ

17

Exec резюме - Вы хотите:

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

Первый ответ:

XElement.Descendants, или это вопрос с подвохом? : P There's an example of usage of Descendants here

Пересмотренный ответ, спасибо Tormod - что-то действительно чувствовал себя неправильно !:

Элементы дает прямые потомки, как вы ищете. Потомки дают полную иерархию [как вы утверждаете, Элементы]. .! (В качестве примера я связан проясняет это Извиняюсь за сумбур

Итак, наконец-то, что вы ищете, (на этот раз в 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") 

Каждый из них даст вам 3 `` `элементы по разным причинам, как покрытых РЗМ

(Paste выше непосредственно в LINQPad в режиме VB заявление)

теперь я вижу, что может сбить с толку вас -. при использовании элементов и смотреть у него в визуализаторе вы все еще видя детей: -

Dim parents = xml.Elements 

Если вы хотите только фактические имена, вы можете использовать что-то вроде:

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

Обратите внимание, что в каждом из этих случаев, вы получаете два результата.

Если вы действительно хотите, чтобы вычистить Детское, вы хотите:

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

Вы можете расширить свой вопрос, чтобы показать, что вы действительно ищете?

+3

Метод Descendants() получает все потомки, а не только прямые потомки. В этом случае потомки «root» будут включать все дочерние элементы. – Tormod

+0

@ Тормод, ты уверен? См. Пример? Если нет, то какая разница между потомками и элементами? –

+0

@Tormod, mea culpa, редактирование! –

-1

Почему бы не использовать 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 

Возьмите это с щепоткой соли - я только что преобразовал его из C# в VB.

+0

XLinq делает это довольно аккуратно, как [когда-то получилось понять, какой метод использовать: P] –

+1

Достаточно справедливо: P Мне нужно будет изучить его, я думаю, XPath устаревает, если вы все двигаетесь на XLinq! –

0

Если все прямые потомки имеют одно и то же известное имя элемента, и это имя элемента не может отображаться на другом уровне, вы можете использовать xml.Descendants («Родительский»).

15

XElement.Elements получает набор дочерних элементов. Например ...

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

Используя Linq, мы можем это сделать.

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 
} 

Надеюсь, это поможет. Спасибо.

Смежные вопросы