Подтвердить что ты не робот

LINQ to XML: как получить только прямые потомки XElement?

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, который выбирает элементы, где parent = <Root>? Или есть какой-то встроенный метод, который я пропускаю, чтобы получить это для меня?

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

Спасибо!

4b9b3361

Ответ 1

Exec summary - вы хотите:

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

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

XElement.Descendants, или это трюк?: P Вот пример использования потомков здесь

Пересмотренный ответ, спасибо 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 `` `элементы по разным причинам, как описано в REM.

(Вставьте вышеуказанное прямо в LINQPad в режиме инструкции VB)

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

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))

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

Ответ 2

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

Ответ 3

Используя 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
}

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

Ответ 4

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

Ответ 5

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

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