How to use fn: max in SelectSingleNode

When I ran this:

XmlDocument xmlResponse = new XmlDocument(); XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlResponse.NameTable); nsmgr.AddNamespace("fn", " http://www.w3.org/2005/xpath-functions"); xmlResponse.LoadXml( "<LIST>" + "<ITEM NUMBER='3' TEXT='C'/>" + "<ITEM NUMBER='2' TEXT='B'/>" + "<ITEM NUMBER='1' TEXT='A'/>" + "</LIST>"); XmlNode xmlNode = xmlResponse.SelectSingleNode("//ITEM[fn:max(@NUMBER)]", nsmgr); 

I get the exception "XsltContext is required for this request due to an unknown function." on the last line. I am trying to select the ITEM element with the highest attribute NUMBER. Is this possible with XPATH?

I am using .Net 2.0 and Linq is not an option.

thanks

+4
source share
3 answers
 XmlNode xmlNode = xmlResponse.SelectSingleNode("//ITEM[fn:max(@NUMBER)]", nsmgr); 

max() is an XPath 2.0..NET function that only supports XPath1.0.

In XPath 1.0 you can use:

 /*/ITEM[not(@NUMBER > ../@NUMBER)] 

Even if .NET implemented XPath 2.0, the XPath expression from the question does not select ITEM with a maximum attribute of NUMBER . The correct XPath 2.0 expression, using max() to select:

 /*/ITEM[xs:integer(@NUMBER) eq max(../@NUMBER/xs:string(.))] 

This is because the max() argument must be a sequence of elements in which we need to define the maximum element. Instead, in the XPath expression from the question:

 //ITEM[fn:max(@NUMBER)] 

max has only one argument - the NUMBER attribute of the node context. Therefore, the above is equivalent to:

 //ITEM[@NUMBER] 

which selects all ITEM elements that have the NUMBER attribute.

+4
source

you can use the following mechanism to find the node with the highest value for any given attribute:

 XmlNode xmlNode = xmlResponse.SelectSingleNode( "//ITEM[not(preceding-sibling::ITEM/@NUMBER > @NUMBER or following-sibling::ITEM/@NUMBER > @NUMBER)]", nsmgr ); 

In XPath, you can implement your own XsltContext and pass it to the XPathExpression.SetContext () method. This XstlContext is called whenever an XPath function is unknown, and this is a way to extend XPath with custom functions and variables.

+2
source

As explained, Microsoft.NET Framework XML interfaces such as XmlDocument and XPathDocument / XPathNavigator only support XPath 1.0, and the maximum function you want to use is XPath 2.0. To find the element with the maximum value, there is another solution with the Microsoft API: sorting (for the maximum in descending order) and accessing the first element in sorted order:

 XmlDocument xmlResponse = new XmlDocument(); xmlResponse.LoadXml( "<LIST>" + "<ITEM NUMBER='3' TEXT='C'/>" + "<ITEM NUMBER='2' TEXT='B'/>" + "<ITEM NUMBER='1' TEXT='A'/>" + "</LIST>"); XPathNavigator nav = xmlResponse.CreateNavigator(); XPathExpression exp = nav.Compile("LIST/ITEM"); exp.AddSort("@NUMBER", XmlSortOrder.Descending, XmlCaseOrder.None, "", XmlDataType.Number); XmlNode item = nav.SelectSingleNode(exp).UnderlyingObject as XmlNode; Console.WriteLine(item.OuterXml); 
+1
source

Source: https://habr.com/ru/post/1315394/


All Articles