Get all specific nodes inside a specific parent node of an XML using XMLDocument

346 views Asked by At

I have the following XML:

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
  <entity name="contact">
    <attribute name="contactid" />
    <link-entity name="ccl1007_studentjourney" from="ccl1007_contactid" to="contactid">
      <filter type="and">
        <condition attribute="statecode" operator="eq" value="0" />
        <filter type="or">
          <condition attribute="ccl1007_sjapplicantdayattendedon" operator="last-x-months" value="12" />
          <condition attribute="ccl1007_sjapplicantdayattendedon" operator="next-x-years" value="5" />
        </filter>
      </filter>
    </link-entity>
    <filter>
      <condition attribute="contactid" operator="eq" value="234" />
    </filter>
  </entity>
</fetch>

What I want to do is get all <condition/> nodes inside the <link-entity/> node and ignore other instances of the <condition/>.

Using my example, I want the output to only return the following nodes

<condition attribute="statecode" operator="eq" value="0" />
<condition attribute="ccl1007_sjapplicantdayattendedon" operator="last-x-months" value="12" />
<condition attribute="ccl1007_sjapplicantdayattendedon" operator="next-x-years" value="5" />

I tried the following but it was only able to loop on the first <filter/> tag that contains the first <condition/> tag

XmlNode linkEntityElem = doc.GetElementsByTagName("link-entity")[0];
foreach (XmlNode child in linkEntityElem.SelectNodes("filter"))
{
   var g = child.Attributes["attribute"];
}
2

There are 2 answers

0
Peter Csala On

All you need is two xpath queries:

var linkEntity = doc.SelectSingleNode("//fetch/entity/link-entity");
var conditions = linkEntity.SelectNodes(".//condition");
foreach (XmlElement condition in conditions)
{
    Console.WriteLine(condition.OuterXml);
}
  • The SelectSingleNode's parameter will find the <lint-entity> node
  • The SelectNodes's parameter will find all <condition> nodes under the <link-entity> node regardless of the depth
    • NOTE: The result of SelectNodes is an XmlNodeList so you have to explicitly use XmlElement inside the foreach to be able to use OuterXml

The output will be

<condition attribute="statecode" operator="eq" value="0" />
<condition attribute="ccl1007_sjapplicantdayattendedon" operator="last-x-months" value="12" />
<condition attribute="ccl1007_sjapplicantdayattendedon" operator="next-x-years" value="5" />

Here you can find the working demo on sharplab.

0
pfx On

Below XPATH statement will allow you to get those conditions in a single call.
Notice the // in filter//condition to allow the match at more than 1 level, starting from //fetch/entity/link-entity/filter which excludes the level you don't need.

//fetch/entity/link-entity/filter//condition

var conditions = doc.SelectNodes("//fetch/entity/link-entity/filter//condition");
foreach (var condition in conditions)
{
    Console.WriteLine(condition.OuterXml);
}