How to: Chain Axis Method Calls (LINQ to XML)
A common pattern that you will use in your code is to call an axis method, then call one of the extension method axes.
There are two axes with the name of Elements that return a collection of elements: the System.Xml.Linq.XContainer.Elements method and the System.Xml.Linq.Extensions.Elements method. You can combine these two axes to find all elements of a specified name at a given depth in the tree.
Example
This example uses System.Xml.Linq.XContainer.Elements and System.Xml.Linq.Extensions.Elements to find all Name elements in all Address elements in all PurchaseOrder elements.
This example uses the following XML document: Sample XML File: Multiple Purchase Orders (LINQ to XML).
XElement purchaseOrders = XElement.Load("PurchaseOrders.xml");
IEnumerable<XElement> names =
from el in purchaseOrders
.Elements("PurchaseOrder")
.Elements("Address")
.Elements("Name")
select el;
foreach (XElement e in names)
Console.WriteLine(e);
Dim purchaseOrders As XElement = XElement.Load("PurchaseOrders.xml")
Dim names As IEnumerable(Of XElement) = _
From el In purchaseOrders.<PurchaseOrder>.<Address>.<Name> _
Select el
For Each e As XElement In names
Console.WriteLine(e)
Next
This example produces the following output:
<Name>Ellen Adams</Name>
<Name>Tai Yee</Name>
<Name>Cristian Osorio</Name>
<Name>Cristian Osorio</Name>
<Name>Jessica Arnold</Name>
<Name>Jessica Arnold</Name>
This works because one of the implementations of the Elements
axis is as an extension method on IEnumerable of XContainer. XElement derives from XContainer, so you can call the System.Xml.Linq.Extensions.Elements method on the results of a call to the System.Xml.Linq.XContainer.Elements method.
Sometimes you want to retrieve all elements at a particular element depth when there might or might not be intervening ancestors. For example, in the following document, you might want to retrieve all the ConfigParameter elements that are children of the Customer element, but not the ConfigParameter that is a child of the Root element.
<Root>
<ConfigParameter>RootConfigParameter</ConfigParameter>
<Customer>
<Name>Frank</Name>
<Config>
<ConfigParameter>FirstConfigParameter</ConfigParameter>
</Config>
</Customer>
<Customer>
<Name>Bob</Name>
<!--This customer doesn't have a Config element-->
</Customer>
<Customer>
<Name>Bill</Name>
<Config>
<ConfigParameter>SecondConfigParameter</ConfigParameter>
</Config>
</Customer>
</Root>
To do this, you can use the System.Xml.Linq.Extensions.Elements axis, as follows:
XElement root = XElement.Load("Irregular.xml");
IEnumerable<XElement> configParameters =
root.Elements("Customer").Elements("Config").
Elements("ConfigParameter");
foreach (XElement cp in configParameters)
Console.WriteLine(cp);
Dim root As XElement = XElement.Load("Irregular.xml")
Dim configParameters As IEnumerable(Of XElement) = _
root.<Customer>.<Config>.<ConfigParameter>
For Each cp As XElement In configParameters
Console.WriteLine(cp)
Next
This example produces the following output:
<ConfigParameter>FirstConfigParameter</ConfigParameter>
<ConfigParameter>SecondConfigParameter</ConfigParameter>
The following example shows the same technique for XML that is in a namespace. For more information, see Working with XML Namespaces.
This example uses the following XML document: Sample XML File: Multiple Purchase Orders in a Namespace.
XNamespace aw = "https://www.adventure-works.com";
XElement purchaseOrders = XElement.Load("PurchaseOrdersInNamespace.xml");
IEnumerable<XElement> names =
from el in purchaseOrders
.Elements(aw + "PurchaseOrder")
.Elements(aw + "Address")
.Elements(aw + "Name")
select el;
foreach (XElement e in names)
Console.WriteLine(e);
Imports <xmlns:aw="https://www.adventure-works.com">
Module Module1
Sub Main()
Dim purchaseOrders As XElement = XElement.Load("PurchaseOrdersInNamespace.xml")
Dim names As IEnumerable(Of XElement) = _
From el In purchaseOrders.<aw:PurchaseOrder>.<aw:Address>.<aw:Name> _
Select el
For Each e As XElement In names
Console.WriteLine(e)
Next
End Sub
End Module
This example produces the following output:
<aw:Name xmlns:aw="https://www.adventure-works.com">Ellen Adams</aw:Name>
<aw:Name xmlns:aw="https://www.adventure-works.com">Tai Yee</aw:Name>
<aw:Name xmlns:aw="https://www.adventure-works.com">Cristian Osorio</aw:Name>
<aw:Name xmlns:aw="https://www.adventure-works.com">Cristian Osorio</aw:Name>
<aw:Name xmlns:aw="https://www.adventure-works.com">Jessica Arnold</aw:Name>
<aw:Name xmlns:aw="https://www.adventure-works.com">Jessica Arnold</aw:Name>