Xpath Query Result Order

XPath query result order

I could find the following bug-report which looks like the issue: Bug 363252 - proximity position in libxml2's xmlXPathEvalExpression() reported 18 Oct 2006 and confirmed dating back since May 2006 which is before the 2.6.26 version in question.

This should have been fixed in libxml2 2.6.27.

XPATH -- Result order defined by query

The | operator computes the union of its operands and with XPath 1.0 you simply get a set of nodes, the order is undefined, though most XPath APIs then return the result in document order or allow you to say which order you want or whether order matters (see for instance http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult).

With XPath 2.0 you get a sequence of nodes ordered in document order, with XPath 2.0 if you want the order of your subexpressions you would need to use the comma operator, not the union operator i.e. element[@attr="a"] , element[@attr="b"] , element[@attr="c"].

Sorting XPath results in the same order as multiple select parameters

An XSLT example:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="pSequence" select="'2 1'"/>
<xsl:template match="objects">
<xsl:for-each select="object[contains(concat(' ',$pSequence,' '),
concat(' ',@uid,' '))]">
<xsl:sort select="substring-before(concat(' ',$pSequence,' '),
concat(' ',@uid,' '))"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Output:

<object uid="2" /><object uid="1" />

Sorting Results returned by SimpleXML, and Xpath in PHP

You can probably do it with XPath or something, but SimpleXMLElement::xpath() returns an array that is easy to sort:

usort($xQuery, function ($a, $b) { return strcmp($a->Make, $b->Make); });
foreach ($xQuery as $results) {
// …
}

How do I guarantee node order for an XPath 'OR' query

As I understand it, .NET supports
XPath 1.0 which does not guarantee
node order

When an XPath 1.0 expression that selects nodes is evaluated, the selected nodes form a node-set. A node-set is a set and this, among many other things, means that it is unordered.

For practical purposes, though, there is one main ordering chosen to enumerate the nodes of a node set: document order. In practice, all XPath 1.0 engines I know (and certainly in .NET) return the selected nodes in document order. In the future this is unlikely to change, because vendors try to preserve backwards compatibility.

Therefore, just try using the SelectNodes() or Evaluate() methods and verify that the nodes in the results are in document order.

Do note: The order of the following cannot be guaranteed and is implementation-dependent:

  1. Attributes of the same element.

  2. Nodes belonging to different documents (a node-set containing nodes from different documents can be produced using the XSLT function document(), so this most probably is of no concern to you).

Xpath 1.0 query to sorting and extract minimum date value doesn't work

The < and > operators in XPath 1.0 are defined only on numbers, not on strings (or dates/times). If you use them on strings, the system will attempt to convert strings to numbers, generally resulting in a NaN < NaN comparison, which is always false.

For comparing dates a popular XPath 1.0 workaround is to strip out the punctuation and then compare say 20190430 and 20190101 as numbers.

How to sort values via XPath

You can use xsl:sort to sort matching nodes. This will allow you to sort by your val element. However, XPath 1.0 does not have a date data-type. A reasonable solution to this problemm is to split your date into its year, month and day components and sort by each individually. The following should do the trick:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates>
<xsl:sort select="val" data-type="number" order="descending"/>

<!-- year sort -->
<xsl:sort select="substring(date,7,4)" data-type="number" />
<!-- month sort -->
<xsl:sort select="substring(date,4,2)" data-type="number" />
<!-- day sort -->
<xsl:sort select="substring(date,1,2)" data-type="number" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>


Related Topics



Leave a reply



Submit