我正在BaseX中的大型数据集上运行查询,但是一个XQuery正在崩溃我的程序并出现错误[XPTY0004] Item expected, sequence found: (attribute begin {"6"}, ...)..
在我的查询中,我试图通过比较beginXML中存在的属性来确保一个元素位于另一个元素之前number().但每当我在我的数据集上尝试最基本的XQueries(返回匹配节点)时(例如使用这个在线工具),我得到的错误类似于我之前的错误:
[错误] SaxonCE.XSLT20Processor 14:08:39.692 SEVERE:invokeTransform中的XPathException:不允许多个项目的序列作为number()的第一个参数("6","10")
所以我猜测节点的兄弟节点正在发生一些事情,即这些节点不止一个,并且不清楚应该比较哪个节点.示例如下.
XPath用于树库的查询引擎:语言注释语料库.在某些情况下,我们希望节点按顺序匹配,有时无关紧要.作为一个简单的例子:有时我们想要匹配某些东西,如有关人物,其中订单文章,形容词,名词很重要.在其他查询中它并不重要,我们希望匹配诸如可用时间之类的短语,其中文章,形容词,名词的顺序可以是任何顺序.
换句话说,在第一种情况下,应该尊重元素的顺序,在第二种情况下,它不应该.这是一个可能的XPath表示这种结构,包含一篇文章,一个形容词和一个名词.
node[@cat="np" and node[@pt="art"] and node[@pt="adj"] and node[@pt="n"]]
Run Code Online (Sandbox Code Playgroud)
默认情况下,XPath不关心这些元素的顺序,并做了贪婪搜索,也就是说,它也将匹配的项目,如可用时间(art,n,adj).但我想重新写上面的XPath,以确保该节点的顺序被尊重,所以建筑,如可用时间(art,n,adj)没有被匹配有关的人(art,adj,n)是.
# Possible representation of *the time available*
<node id="0" begin="1" cat="np">
<node id="1" begin="1" pt="art" text="the" />
<node id="2" begin="2" pt="n" text="time" />
<node id="3" begin="3" pt="adj" text="available" />
</node>
# Possible representation of *the concerned man*
<node id="0" begin="1" cat="np">
<node id="1" begin="1" pt="art" text="the" />
<node id="2" begin="2" pt="adj" text="concerned" />
<node id="3" begin="3" pt="n" text="man" />
</node>
Run Code Online (Sandbox Code Playgroud)
一种方法是使用begin语料库中可用属性的数字比较.它是数字递增的,所以如果我们想确保XPath的顺序是完整的,我们可以说每个子节点的数值@cat="np"应该小于下一个使用的数值number().但正如我在上面所示,这会导致错误 - 在我刚刚展示的简单示例代码中不会出现错误.
另一个例子.
<node id="0" begin="2">
<node id="1" begin="2">
<node id="2" begin="2"/>
<node id="3" begin="3"/>
</node>
<node id="4" begin="5">
<node id="5" begin="5"/>
</node>
<node id="6" begin="6"/>
</node>
Run Code Online (Sandbox Code Playgroud)
此XPath应匹配:
/node/node[number(@begin) < number(../node/@begin)]
Run Code Online (Sandbox Code Playgroud)
但是当通过XQuery处理器时,你会得到上述错误.A sequence of more than one item is not allowed as the first argument of number() ("2", "5", ...).
我尝试了@Michael Kay提供的解决方案,但似乎也出现了同样的问题.
XQuery的
for $node in node[every $n in node[position() lt last()] satisfies (number($n/@begin) lt number($n/following-sibling::node/@begin))]
return $node
Run Code Online (Sandbox Code Playgroud)
数据
<node id="0" begin="2">
<node id="1" begin="2">
<node id="2" begin="2"/>
<node id="3" begin="3"/>
</node>
<node id="4" begin="5">
<node id="5" begin="5"/>
</node>
<node id="6" begin="6"/>
</node>
Run Code Online (Sandbox Code Playgroud)
错误
SaxonCE.XSLT20Processor 14:48:49.809 SEVERE:invokeTransform中的XPathException:不允许多个项目的序列作为number()的第一个参数("5","6")
今天我遇到了一些意想不到的行为,这使得@ har07提供的解决方案不再充分.我错误地认为该not()子句只对XPath中的节点产生影响(而不是XML中的所有节点).换句话说,当not()子句添加到XPath的最顶层节点时,XML中的所有子节点都将具有固定的排序字顺序.(现在我这样读了它,看起来很正常.)但是,我真正想要的是单词顺序只设置在XPath中指定的节点上,而不是匹配XML中的其他节点.希望和榜样将使这更清楚.
假设我要匹配以下XPath,cat="np"包含rel="det" pt="vnw" lemma="die"至少两次rel="mod" pt="adj".
//node[@cat="np" and node[@rel="det" and @pt="vnw" and @lemma="die"] and count(node[@rel="mod" and @pt="adj"]) > 1]
Run Code Online (Sandbox Code Playgroud)
但随着增加的要求遵循此XPath的顺序,即
//node[
@cat="np" and
not(node[
position() < last()
][number(@begin) > following-sibling::node/number(@begin)]) and
node[
@rel="det" and
@pt="vnw" and
@lemma="die"
] and
count(node[
@rel="mod" and
@pt="adj"
]) > 1
]
Run Code Online (Sandbox Code Playgroud)
所以rel="det"必须在XML中的两个s 之前发生rel="mod".这工作正常,所有匹配都是正确的,但找不到所有预期的匹配.原因是该not()行明显针对所有XML节点而不是XPath指定的节点.如果找到一个不符合not规则的节点,那么就不会有匹配 - 即使在XPath中没有指定该节点.例如,上面的XPath将不匹配以下XML,因为内部cat="np"存在一个节点,其begin属性大于其下一个兄弟节点,not规则不允许这样做.
<node begin="4" cat="np" id="8" rel="obj1">
<node begin="4" id="9" pos="det" pt="vnw" rel="det" word="die" lemma="die" />
<node begin="5" id="10" pos="adj" pt="adj" rel="mod" word="veelzijdige" />
<node begin="6" id="11" pos="adj" pt="adj" rel="mod" word="getalenteerde" />
<node begin="7" id="12" pos="noun" pt="n" rel="hd" word="figuren" />
<node begin="8" id="31" index="1" rel="obj1" />
<node begin="2" id="32" index="2" rel="obj2" />
</node>
Run Code Online (Sandbox Code Playgroud)
不过,我想这个cat="np"匹配,并进行not()功能较少攻击性,即只要求在XPath的指定节点(在这个例子中rel="det" pt="vnw" lemma="die",两个rel="mod" pt="adj"节点)按照订单的要求在开始的属性应该比下一个项目较小的XPath结构.cat="np"其中未在XPath中指定的其他项目允许具有大于其下一个兄弟的属性.
请注意,XPath结构的最后一项(id="11"在示例XML 中将匹配)不一定必须具有低于XML中的后续节点的begin属性(在XPath中未指定).
和以前一样,我对如何使用纯XPath选项解决这个问题特别感兴趣,但也欢迎使用XQuery替代方案.优选地,作为将XPath结构作为输入的函数,并将"单词顺序"应用于其最顶层节点及其所有后代.鼓励使用此处显示的XPath示例代码和用法作为示例.
关于您面临的“不允许多个项目的序列”异常.../number(),请注意 XPath 2.0 及更高版本和 XQuery 支持路径步骤 ( ) 上的函数调用。也就是说,您可以调用number()individual一次node传递一个属性以避免异常:begin
/node/node[number(@begin) < ../node/number(@begin)]
Run Code Online (Sandbox Code Playgroud)
然而,上面 XPath 中使用的谓词表达式的计算结果是true,至少有一个同级node的begin属性值大于begincurrent 的属性node,这似乎不是所需的行为。
您可以对建议的 XQuery 应用相同的修复,但显然由于lt用于将值与值序列进行比较而存在另一个类似的问题(需要明确的是,我指的是lt建议的 XQuery 中的第二个)。您可以尝试以下稍作修改的 XQuery:
for $node in node[
every $n in node[position() lt last()]
satisfies not($n/following-sibling::node[number(@begin) lt number($n/@begin)])
]
return $node
Run Code Online (Sandbox Code Playgroud)
“一种方法是使用
begin语料库中可用属性的数字比较。它是数字升序,因此如果我们想确保 XPath 的顺序完整,我们可以说每个子项的数值通过使用 ,的节点@cat="np"应该小于下一个节点number()。”
如果我理解正确,您可以使用以下 XPath :
/node/node[
not(
node[position() < last()]
[number(@begin) > following-sibling::node/number(@begin)]
)
]
Run Code Online (Sandbox Code Playgroud)
XPath 应该返回所有 2nd levelnode元素,其中,对于node当前 2nd level 内的除最后一个子级之外的每个子node级,没有一个后续同级的属性值比当前 child 的node属性值低。beginnode
给定以下示例 XML:
<node id="0" begin="2">
<node id="0" begin="1" cat="np">
<node id="1" begin="1" pt="art" text="the" />
<node id="2" begin="3" pt="n" text="time" />
<node id="3" begin="2" pt="adj" text="available" />
</node>
<node id="0" begin="1" cat="np">
<node id="1" begin="1" pt="art" text="the" />
<node id="2" begin="2" pt="adj" text="concerned" />
<node id="3" begin="3" pt="n" text="man" />
</node>
</node>
Run Code Online (Sandbox Code Playgroud)
node仅选择第二个,因为它是唯一node具有begin按升序排列属性值的第二个级别:
<node id="0" begin="1" cat="np">
<node id="1" begin="1" pt="art" text="the"/>
<node id="2" begin="2" pt="adj" text="concerned"/>
<node id="3" begin="3" pt="n" text="man"/>
</node>
Run Code Online (Sandbox Code Playgroud)
2017 年 4 月 19 日更新:
“ ...但是,我希望它能够
cat="np"匹配,并使not()函数不那么激进,即只要求 XPath 中指定的节点(在本例中rel="det" pt="vnw" lemma="die",以及两个rel="mod" pt="adj"节点)遵循顺序要求,其中 begin 属性应小于XPath 结构的下一项。 ”
然后我们需要添加另一个谓词来指定中的那些节点not(),这是我们检查属性顺序要求的地方:
node[(@rel="det" and @pt="vnw" and @lemma="die") or (@rel="mod" and @pt="adj")]
[position() < last()]
[number(@begin) >
following-sibling::node[(@rel="det" and @pt="vnw" and @lemma="die") or (@rel="mod" and @pt="adj")]/number(@begin)
]
Run Code Online (Sandbox Code Playgroud)
所以完整的表达式如下:
//node[@cat="np" and
not(node[(@rel="det" and @pt="vnw" and @lemma="die") or (@rel="mod" and @pt="adj")]
[position() < last()]
[number(@begin) >
following-sibling::node[
(@rel="det" and @pt="vnw" and @lemma="die") or (@rel="mod" and @pt="adj")
]/number(@begin)
]
)
and node[@rel="det" and @pt="vnw" and @lemma="die"]
and count(node[@rel="mod" and @pt="adj"]) > 1
]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1235 次 |
| 最近记录: |