如何使用 Xpath 1.0 从 XML 文档中查找 max 属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8702039/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to find the max attribute from an XML document using Xpath 1.0
提问by HerbSpiral
Is there a way to query an XML document to return the maximum of a given attribute using Xpath 1.0 ?
有没有办法使用 Xpath 1.0 查询 XML 文档以返回给定属性的最大值?
For example is there a way to get the max id ?
例如,有没有办法获得最大 id ?
<?xml version="1.0" encoding="utf-8"?>
<library>
<book id="2" name="Dragon Tatoo"/>
<book id="7" name="Ender's Game"/>
<book id="3" name="Catch 22"/>
<book id="1" name="Lord of the rings"/>
</library>
回答by Fred Foo
In XPath 2.0, use the maxfunction. To find the book with the highest id, do
在 XPath 2.0 中,使用该max函数。要找到最高的书id,请执行
/library/book[@id = max(/library/book/@id)]
回答by dertkw
The following XPath selects the book with highest id:
以下 XPath 选择具有最高 id 的书:
/library/book[not(@id <= preceding-sibling::book/@id) and not(@id <=following-sibling::book/@id)]
回答by Tom W
If you're willing to use external tooling - which depends on your implementation featuring implementations of these tools - try the EXSLT:Mathfunction highest().
如果您愿意使用外部工具 - 这取决于您的实现具有这些工具的实现 - 尝试EXSLT:Math函数highest()。
The fact that EXSLT implements this implies that such a feature isn't directly available in plain xpath, of course. If you're not using Transforms, or want to stick purely with standards-compliant markup, other posters' suggestions would be a better choice.
EXSLT 实现这一点的事实意味着,当然,这种功能不能直接在普通 xpath 中使用。如果您不使用 Transforms,或者只想坚持使用符合标准的标记,其他海报的建议将是更好的选择。
回答by Wayne
Note:The following information assumes use of XPath 1.0.
注意:以下信息假定使用 XPath 1.0。
The following expression returns the element(s) with the largest idvalue:
以下表达式返回具有最大值的元素id:
/*/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:
请注意,这与@timbooo 的答案略有不同,因为当存在具有相同最大值的重复项时,这将返回多个元素(@timbooo 将不返回任何元素)。如果在这种情况下您只需要一个元素,那么您需要一个解析策略。要按文档顺序选择第一个这样的元素,请使用:
/*/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 bookelements 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:
这种方法非常低效 ( O(n^2)),因为它需要您将每个元素与每个其他潜在的最大值进行比较。出于这个原因,最好使用您的宿主编程语言来选择最大元素。只需先选择所有book元素,然后从该列表中选择最大值。这是(最有可能的)线性操作 ( O(n)),在非常大的文档上会明显更快。例如,在 Java (JAXP) 中,您可以这样做:
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.
请注意,这只是一个演示;确保在适当的地方包括空检查。
回答by Ricardo
I've found that answers like the lwburk's or timbooo's work fine for attributes representing numbers having just one digit. However, if the attribute is a number having more than one digit, extrange things seem to happen when comparing between attributes' values. For example, try changing the original XML data with something like this:
我发现像 lwburk's 或 timbooo's 这样的答案适用于表示只有一位数的数字的属性。但是,如果属性是一个多于一位的数字,则在比较属性值时似乎会发生一些奇怪的事情。例如,尝试使用以下内容更改原始 XML 数据:
<?xml version="1.0" encoding="utf-8"?>
<library>
<book id="250" name="Dragon Tatoo"/>
<book id="700123" name="Ender's Game"/>
<book id="305" name="Catch 22"/>
<book id="1070" name="Lord of the rings"/>
</library>
Running the suggested snippets won't work. I got a solution using the casting operator xs:int() applied on id attribute, like in:
运行建议的片段将不起作用。我使用在 id 属性上应用的强制转换运算符 xs:int() 得到了一个解决方案,例如:
/library/book[not(xs:int(@id) <= preceding-sibling::book/@id) and not(xs:int(@id) <=following-sibling::book/@id)]
That will give the correct answer!
这将给出正确的答案!
回答by serge
XPath 1.0
XPath 1.0
/library/book[not(@id < /library/book/@id)]
This query style is more generic and works even if books are grouped i.e.
这种查询风格更通用,即使书籍分组也有效,即
<?xml version="1.0" encoding="utf-8"?>
<library>
<genre id="1">
<book id="2" name="Dragon Tatoo"/>
<book id="7" name="Ender's Game"/>
</genre>
<genre id="2">
<book id="3" name="Catch 22"/>
<book id="1" name="Lord of the rings"/>
</genre>
</library>
Same query still works (the path should be modified)
相同的查询仍然有效(应该修改路径)
/library/genre/book[not(@id < /library/genre/book/@id)]
or even
甚至
//book[not(@id < //book/@id)]
To avoid performance troubles use XPath 2 max()instead
为了避免性能问题使用XPath 2max()代替
回答by Jpepper
This example can be used to find the max.
此示例可用于查找最大值。
XmlDocument doc = new XmlDocument();
doc.Load("../../Employees.xml");
XmlNode node = doc.SelectSingleNode("//Employees/Employee/@Id[not(. <=../preceding-sibling::Employee/@id) and not(. <=../following-sibling::Employee/@Id)]");
int maxId = Convert.ToInt32(node.Value);
For other similar topics on xpath and linq check out http://rmanimaran.wordpress.com/2011/03/20/xml-find-max-and-min-value-in-a-attribute-using-xpath-and-linq/
有关 xpath 和 linq 的其他类似主题,请查看http://rmanimaran.wordpress.com/2011/03/20/xml-find-max-and-min-value-in-a-attribute-using-xpath-and-林克/

