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
даст мне именно то, что я искал.
Спасибо!
Ответы
Ответ 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.