How do I extract child nodes from XML file using XPath when both child nodes must exist?
-
10-06-2021 - |
Question
I am trying to extract certain values from an xml document. In the example below, I want to store the values stored in the 'c' and 'd' nodes in a list, but only where the 'b' node contains both 'c' AND 'd'. The code I have so far loops through all of the 'b' nodes, but I am uncertain what to put in the while loop, or if this is the best approach.
XmlDocument attrsXML = new XmlDocument();
attrsXML.LoadXml(dbReader["SampleXml"].ToString());
XPathNavigator nav = attrsXML.CreateNavigator();
XPathNodeIterator attribNodes = nav.Select("/a/b");
while (attribNodes.MoveNext())
{
// What do I need to put here in order to extract the 'c' and 'd' nodes?
// Any other nodes can be ignored (such as 'e' above). I am only interested
// when 'b' contains both 'c' AND 'd'.
}
Where 'SampleXml' loaded from the database is:
<a>
<b>
<c>Extract this</c>
<d>And this</d>
<e>not this</e>
</b>
<b>
<c>not this</c>
<e>not this</e>
</b>
<b>
<c>Extract this</c>
<d>And this</d>
</b>
</a>
Any help appreciated.
Solution
You can use the following code:
XmlDocument attrsXML = new XmlDocument();
attrsXML.LoadXml(dbReader["SampleXml"].ToString());
XmlNodeList nodeList = attrsXML.SelectNodes("/a/b[c and d]");
foreach (XmlNode xmlNode in nodeList)
{
string cText = xmlNode.SelectSingleNode("c").InnerText;
string dText = xmlNode.SelectSingleNode("d").InnerText;
}
The XPath "/a/b[c and d]" returns all b elements which contain c and d elements as children, which means you don't need to check it inside the loop manually.
OTHER TIPS
I solved it this way:
while (attribNodes.MoveNext())
{
string cText = String.Empty;
string dText = String.Empty;
XPathNavigator nav2 = attribNodes.Current;
var cNode = nav2.SelectSingleNode("c");
if (cNode != null)
{
cText = nameNode.ToString();
var dNode = nav2.SelectSingleNode("d");
if (dNode != null)
{
dText = dNode.ToString();
}
}
if (dText != String.Empty && cText != String.Empty)
{
// Problem solved
}
}
Welcome any better solutions as it doesn't seem very elegant.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow