Is there a way to query an XML document to return the maximum of a given attribute using Xpath 1.0 ?
For example is there a way to get the max id ?
&
Note: The following information assumes use of XPath 1.0.
The following expression returns the element(s) with the largest id
value:
/*/book[not(@id < preceding-sibling::book/@id) and
not(@id < following-sibling::book/@id)]
Note that this is slightly different than @timbooo's answer in that this will return more than one element when there are duplicates with the same max value (@timbooo's would return none). If you want only one element in this case, then you need a resolution strategy. To choose the first such element in document order, use this:
/*/book[not(@id < preceding-sibling::book/@id) and
not(@id < following-sibling::book/@id)][1]
To choose the last one, use this:
/*/book[not(@id < preceding-sibling::book/@id) and
not(@id < following-sibling::book/@id)][last()]
This approach is very inefficient (O(n^2)
) because it requires you to compare each element to every other potential max. For this reason, it's probably best to use your host programming language to select the maximum element. Simply select all of the book
elements first and then choose the max from that list. This is (most likely) a linear operation (O(n)
), which would be noticeably faster on very large documents. For example, in Java (JAXP) you might do it like this:
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) xpath.evaluate("/*/book", doc,
XPathConstants.NODESET);
Node max = nodes.item(0);
for (int i = 0; i < nodes.getLength(); i++) {
int maxval = Integer.parseInt(max.getAttributes()
.getNamedItem("id").getNodeValue());
int curval = Integer.parseInt(nodes.item(i).getAttributes()
.getNamedItem("id").getNodeValue());
if (curval >= maxval)
max = nodes.item(i);
}
System.out.println(max.getAttributes().getNamedItem("name"));
Note that this is just a demonstration; be sure to include null-checks where appropriate.