How to: Filter on an Optional Element
Sometimes you want to filter for an element even though you are not sure it exists in your XML document. The search should be executed so that if the particular element does not have the child element, you do not trigger a null reference exception by filtering for it. In the following example, the Child5 element does not have a Type child element, but the query still executes correctly.
Example
This example uses the Elements extension method.
XElement root = XElement.Parse(@"<Root>
<Child1>
<Text>Child One Text</Text>
<Type Value=""Yes""/>
</Child1>
<Child2>
<Text>Child Two Text</Text>
<Type Value=""Yes""/>
</Child2>
<Child3>
<Text>Child Three Text</Text>
<Type Value=""No""/>
</Child3>
<Child4>
<Text>Child Four Text</Text>
<Type Value=""Yes""/>
</Child4>
<Child5>
<Text>Child Five Text</Text>
</Child5>
</Root>");
var cList =
from typeElement in root.Elements().Elements("Type")
where (string)typeElement.Attribute("Value") == "Yes"
select (string)typeElement.Parent.Element("Text");
foreach(string str in cList)
Console.WriteLine(str);
Dim root As XElement = _
<Root>
<Child1>
<Text>Child One Text</Text>
<Type Value="Yes"/>
</Child1>
<Child2>
<Text>Child Two Text</Text>
<Type Value="Yes"/>
</Child2>
<Child3>
<Text>Child Three Text</Text>
<Type Value="No"/>
</Child3>
<Child4>
<Text>Child Four Text</Text>
<Type Value="Yes"/>
</Child4>
<Child5>
<Text>Child Five Text</Text>
</Child5>
</Root>
Dim cList As IEnumerable(Of String) = _
From typeElement In root.Elements().<Type> _
Where typeElement.@Value = "Yes" _
Select typeElement.Parent.<Text>.Value
Dim str As String
For Each str In cList
Console.WriteLine(str)
Next
This code produces the following output:
Child One Text
Child Two Text
Child Four Text
The following example shows the same query for XML that is in a namespace. For more information, see Working with XML Namespaces.
XElement root = XElement.Parse(@"<Root xmlns='http://www.adatum.com'>
<Child1>
<Text>Child One Text</Text>
<Type Value=""Yes""/>
</Child1>
<Child2>
<Text>Child Two Text</Text>
<Type Value=""Yes""/>
</Child2>
<Child3>
<Text>Child Three Text</Text>
<Type Value=""No""/>
</Child3>
<Child4>
<Text>Child Four Text</Text>
<Type Value=""Yes""/>
</Child4>
<Child5>
<Text>Child Five Text</Text>
</Child5>
</Root>");
XNamespace ad = "http://www.adatum.com";
var cList =
from typeElement in root.Elements().Elements(ad + "Type")
where (string)typeElement.Attribute("Value") == "Yes"
select (string)typeElement.Parent.Element(ad + "Text");
foreach (string str in cList)
Console.WriteLine(str);
Imports <xmlns='http://www.adatum.com'>
Module Module1
Sub Main()
Dim root As XElement = _
<Root>
<Child1>
<Text>Child One Text</Text>
<Type Value="Yes"/>
</Child1>
<Child2>
<Text>Child Two Text</Text>
<Type Value="Yes"/>
</Child2>
<Child3>
<Text>Child Three Text</Text>
<Type Value="No"/>
</Child3>
<Child4>
<Text>Child Four Text</Text>
<Type Value="Yes"/>
</Child4>
<Child5>
<Text>Child Five Text</Text>
</Child5>
</Root>
Dim cList As IEnumerable(Of String) = _
From typeElement In root.Elements().<Type> _
Where typeElement.@Value = "Yes" _
Select typeElement.Parent.<Text>.Value
Dim str As String
For Each str In cList
Console.WriteLine(str)
Next
End Sub
End Module
This code produces the following output:
Child One Text
Child Two Text
Child Four Text
See Also
Reference
XML Child Axis Property (Visual Basic)
XML Attribute Axis Property (Visual Basic)
XML Value Property (Visual Basic)