0

I am writing a C# function where I need to fetch the value of a node using Xpath and if the fetched values matches a given string, I need to pass the Xpath to an API which replaces the current value of the node with value stored in Database.

The problem is there are multiple matches for the given Xpath, I filter those out with the string matching criteria and am able to figure out the node, however, I am not getting how to capture the exact Xpath of matching node and pass it to the API for it to work.

Lets take this XML as an example

<GrandParent>
  <Parent>
    <Child1>John
    </Child1>
    <Child2>Emily
    </Child2>
  </Parent>
  <Parent>
    <Child1>Frank
    </Child1>
    <Child2>Niki
    </Child2>
  </Parent>
  <Parent>
    <Child1>Mia
    </Child1>
    <Child2>Noah
    </Child2>
  </Parent>
</GrandParent>

Now I will have to fetch the node with Xpath /GrandParent/Parent/Child1 whose value would be John.

I am doing that in C# using XPathNavigator and XPathIterator

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(requestXML);

            XPathNavigator nav;
            nav = xmlDoc.CreateNavigator();

            XPathNodeIterator allMatchingNodes = nav.Select(SourceXPath);

            int countNodes = 1;

            foreach (XPathNavigator node in allMatchingNodes)
            {
                if(node.Value.Equals("John"))
                {
                  Xpath = SourceXPath + "[" + countNodes + "]";
                  break;
                }
                    
            }

However, this would be an incorrect approach as it will create xpath as /GrandParent/Parent/Child1[1] and hence the subsequeent API replaces is incorrectly.

I would want xpath as /GrandParent/Parent[1]/Child1 is there someway of doing that without using multiple foreach?

Karan Parikh
  • 311
  • 3
  • 18
  • There isn't really something like *the* XPath for a node. Also there have been updates to XPath both on the standards side as well as in the form of third party implementations. XPath 3 has a function https://www.w3.org/TR/xpath-functions/#func-path which can make that task as easy as a single function call. Saxon .NET supports XPath 3. But I don't know whether the result of the `path` function is consumable by your server API, you haven't described what is used there. – Martin Honnen Jul 12 '21 at 18:26
  • The API will take the XML, the exact xpath of matched string and replace that's node value. For Ex : If we pass the above XML along with xpath /GrandParent/Parent[1]/Child1 it will replace John with Jill. The func-path looks like something I can use, however I am not able to figure out how to do that using Saxon .NET, there is documentation, but to me it isn't really helpful, do you have something that might help? – Karan Parikh Jul 13 '21 at 03:02
  • The format the XPath 3 `fn:path` function returns is only consumable by another XPath 3 implementation, so that is more what my question is about, how exactly XPath is used on the server, whether there you also have an option to move to an XPath 3 or XQuery 3 implementation. – Martin Honnen Jul 13 '21 at 09:18

0 Answers0