Is there a way to query an XML document to return the maximum of a given attribute using Xpath 1.0 ?
有没有办法查询XML文档以使用Xpath 1.0返回给定属性的最大值?
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>
6 个解决方案
#1
8
In XPath 2.0, use the max
function. To find the book with the highest id
, do
在XPath 2.0中,使用max函数。要找到id最高的书,请执行
/library/book[@id = max(/library/book/@id)]
#2
3
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)]
#3
2
If you're willing to use external tooling - which depends on your implementation featuring implementations of these tools - try the EXSLT:Math function highest()
.
如果您愿意使用外部工具 - 这取决于您实现这些工具的实现 - 请尝试EXSLT:Math函数最高()。
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中不能直接使用。如果你没有使用变形,或者想要纯粹坚持使用符合标准的标记,那么其他海报的建议将是更好的选择。
#4
2
Note: The following information assumes use of XPath 1.0.
注意:以下信息假定使用XPath 1.0。
The following expression returns the element(s) with the largest id
value:
以下表达式返回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将返回none)。如果在这种情况下只需要一个元素,那么您需要一个解决策略。要按文档顺序选择第一个此类元素,请使用以下命令:
/*/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:
这种方法效率非常低(O(n ^ 2)),因为它要求您将每个元素与每个其他潜在的最大值进行比较。因此,最好使用主机编程语言来选择最大元素。只需先选择所有书籍元素,然后从该列表中选择最大值。这(很可能)是线性操作(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.
请注意,这只是一个演示;一定要在适当的地方加入空值检查。
#5
1
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或者timbooo这样的答案对于表示只有一位数的数字的属性来说很好。但是,如果属性是一个具有多个数字的数字,则在比较属性值时似乎会发生外部事件。例如,尝试使用以下内容更改原始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!
这将给出正确的答案!
#6
0
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- LINQ /
#1
8
In XPath 2.0, use the max
function. To find the book with the highest id
, do
在XPath 2.0中,使用max函数。要找到id最高的书,请执行
/library/book[@id = max(/library/book/@id)]
#2
3
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)]
#3
2
If you're willing to use external tooling - which depends on your implementation featuring implementations of these tools - try the EXSLT:Math function highest()
.
如果您愿意使用外部工具 - 这取决于您实现这些工具的实现 - 请尝试EXSLT:Math函数最高()。
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中不能直接使用。如果你没有使用变形,或者想要纯粹坚持使用符合标准的标记,那么其他海报的建议将是更好的选择。
#4
2
Note: The following information assumes use of XPath 1.0.
注意:以下信息假定使用XPath 1.0。
The following expression returns the element(s) with the largest id
value:
以下表达式返回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将返回none)。如果在这种情况下只需要一个元素,那么您需要一个解决策略。要按文档顺序选择第一个此类元素,请使用以下命令:
/*/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:
这种方法效率非常低(O(n ^ 2)),因为它要求您将每个元素与每个其他潜在的最大值进行比较。因此,最好使用主机编程语言来选择最大元素。只需先选择所有书籍元素,然后从该列表中选择最大值。这(很可能)是线性操作(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.
请注意,这只是一个演示;一定要在适当的地方加入空值检查。
#5
1
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或者timbooo这样的答案对于表示只有一位数的数字的属性来说很好。但是,如果属性是一个具有多个数字的数字,则在比较属性值时似乎会发生外部事件。例如,尝试使用以下内容更改原始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!
这将给出正确的答案!
#6
0
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- LINQ /