对原子值进行排序的 XPath 查询的语法是什么?
What is the syntax for a sorted XPath query on atomic values?
我正在尝试在我的 Java 代码中执行以下 select:
// initialized earlier
private XdmNode xmlDocument;
private XPathCompiler xPath;
// ... the code that's a problem:
XPathExecutable exec = xPath.compile("sort(distinct-values(/root/data/hasTransaction/element/hasAssets/element/associatedAttributes/element[(value != '') and (dataParamName != 'modelNomenclature')]/name), (), function($node) { $node/displaySeq })");
XPathSelector selector = exec.load();
selector.setContextItem(xmlDocument);
selector.evaluate();
调用 evaluate() 抛出异常:
net.sf.saxon.trans.XPathException: The required item type of the first operand of '/' is node(); the supplied value u"Model Name" is an atomic value
查询有什么问题?我知道 distinct-values() returns 原子值,但为什么对这些值进行排序时出现问题? $node 对原子值排序没有意义吗?但是 select (没有排序)是:
/root/data/hasTransaction/element/hasAssets/element/associatedAttributes/element[(value != '') and (dataParamName != 'modelNomenclature')]/name
/root/data/hasTransaction/element/hasAssets/element/associatedAttributes:
<associatedAttributes>
<element>
<uom>N/A</uom>
<name>Model Name</name>
<dataParamName>modelName</dataParamName>
<seq />
<value>A17-230P1A</value>
<displayLevel>0</displayLevel>
<displaySeq>5</displaySeq>
<displayLevelTitle />
<displayName>Model Name</displayName>
<dataGroup />
</element>
所以(对我来说)这似乎是合乎逻辑的,因为它是“...[...]/name”,它可以在 displaySeq
上排序
“/”运算符需要 LHS 上的节点(不是原子值)(如错误消息所述)。
我认为,如果 element
个元素具有相同的 name
个子元素,那么您正在尝试将它们作为重复项消除,然后按 displaySeq
的值对它们进行排序。不幸的是 distinct-values()
只保留(原子)值,它失去了这些值从中派生的节点的知识。 (至少在原则上,具有相同 name
的两个元素可以具有不同的 displaySeq
值,因此不清楚您要保留哪个。
理想情况下,您会为此使用 XSLT 或 XQuery 分组,而不是不同的值。如果你必须使用 XPath,你可以考虑创建一个映射来进行重复数据删除:
let $index := map:merge(/root/data/hasTransaction/element/hasAssets
/element/associatedAttributes/element[
(value != '') and (dataParamName != 'modelNomenclature')
]!map{displaySeq : .}/name)
return sort(map:for-each($index, function($k, $v){$v}),
(), function($node) { $node/displaySeq })
未测试。
也许
distinct-values(sort(/root/data/hasTransaction/element/hasAssets/element/associatedAttributes/element[(value != '') and (dataParamName != 'modelNomenclature')], (), function($node) { $node/displaySeq })!name)
给你正确的结果,它按 displaySeq
对 element
元素进行排序,然后选择 name
子元素并计算不同的元素。
你也可以写成
(/root/data/hasTransaction/element/hasAssets/element/associatedAttributes/element[(value != '') and (dataParamName != 'modelNomenclature')] => sort((), function($node) { $node/displaySeq })) ! name => distinct-values()
我正在尝试在我的 Java 代码中执行以下 select:
// initialized earlier
private XdmNode xmlDocument;
private XPathCompiler xPath;
// ... the code that's a problem:
XPathExecutable exec = xPath.compile("sort(distinct-values(/root/data/hasTransaction/element/hasAssets/element/associatedAttributes/element[(value != '') and (dataParamName != 'modelNomenclature')]/name), (), function($node) { $node/displaySeq })");
XPathSelector selector = exec.load();
selector.setContextItem(xmlDocument);
selector.evaluate();
调用 evaluate() 抛出异常:
net.sf.saxon.trans.XPathException: The required item type of the first operand of '/' is node(); the supplied value u"Model Name" is an atomic value
查询有什么问题?我知道 distinct-values() returns 原子值,但为什么对这些值进行排序时出现问题? $node 对原子值排序没有意义吗?但是 select (没有排序)是:
/root/data/hasTransaction/element/hasAssets/element/associatedAttributes/element[(value != '') and (dataParamName != 'modelNomenclature')]/name
/root/data/hasTransaction/element/hasAssets/element/associatedAttributes:
<associatedAttributes>
<element>
<uom>N/A</uom>
<name>Model Name</name>
<dataParamName>modelName</dataParamName>
<seq />
<value>A17-230P1A</value>
<displayLevel>0</displayLevel>
<displaySeq>5</displaySeq>
<displayLevelTitle />
<displayName>Model Name</displayName>
<dataGroup />
</element>
所以(对我来说)这似乎是合乎逻辑的,因为它是“...[...]/name”,它可以在 displaySeq
上排序“/”运算符需要 LHS 上的节点(不是原子值)(如错误消息所述)。
我认为,如果 element
个元素具有相同的 name
个子元素,那么您正在尝试将它们作为重复项消除,然后按 displaySeq
的值对它们进行排序。不幸的是 distinct-values()
只保留(原子)值,它失去了这些值从中派生的节点的知识。 (至少在原则上,具有相同 name
的两个元素可以具有不同的 displaySeq
值,因此不清楚您要保留哪个。
理想情况下,您会为此使用 XSLT 或 XQuery 分组,而不是不同的值。如果你必须使用 XPath,你可以考虑创建一个映射来进行重复数据删除:
let $index := map:merge(/root/data/hasTransaction/element/hasAssets
/element/associatedAttributes/element[
(value != '') and (dataParamName != 'modelNomenclature')
]!map{displaySeq : .}/name)
return sort(map:for-each($index, function($k, $v){$v}),
(), function($node) { $node/displaySeq })
未测试。
也许
distinct-values(sort(/root/data/hasTransaction/element/hasAssets/element/associatedAttributes/element[(value != '') and (dataParamName != 'modelNomenclature')], (), function($node) { $node/displaySeq })!name)
给你正确的结果,它按 displaySeq
对 element
元素进行排序,然后选择 name
子元素并计算不同的元素。
你也可以写成
(/root/data/hasTransaction/element/hasAssets/element/associatedAttributes/element[(value != '') and (dataParamName != 'modelNomenclature')] => sort((), function($node) { $node/displaySeq })) ! name => distinct-values()