XPath拉多个匹配项

(BaseX)错误

我正在BaseX中的一个大数据集上运行查询,但一个XQuery正在使我的程序崩溃,出现错误[XPTY0004]项预期,找到序列:(属性begin{“6”},…)

在我的查询中,我试图通过比较begin(XML中的一个属性)和number()来确保一个元素位于另一个元素之前。但每当我在我的数据集上尝试最基本的XQuery(返回匹配节点)(例如,使用此在线工具)时,我会得到一个类似于我以前遇到的错误:

[错误]SaxonCE.XSLT20Processor 14:08:39.692严重:XPathException在中
invokeTransform:不允许包含多个项的序列作为
number()的第一个参数(“6”,“10”)

因此,我猜测节点的兄弟节点有问题,也就是说,这些节点不止一个,而且不清楚应该比较哪一个。下面是一些例子

为什么顺序很重要

XPath用于树库的查询引擎:语言注释语料库。在某些情况下,我们希望节点按顺序匹配,有时这并不重要。举一个简单的例子:有时我们想要匹配一些特定的东西,比如相关的人,其中顺序冠词、形容词、名词很重要。在其他查询中,这并不重要,我们还希望匹配短语,如可用时间,其中冠词、形容词、名词的顺序可以是任意顺序

换句话说,在第一种情况下,元素的顺序应该得到尊重,在第二种情况下则不应该。下面是包含冠词、形容词和名词的此类结构的可能XPath表示

节点[@cat=“np”和节点[@pt=“art”]以及节点[@pt=“adj”]和节点[@pt=“n”]]

默认情况下,XPath不关心这些元素的顺序,而是进行贪婪搜索,即它还将匹配可用时间等项(artnadj)。但是我想重新编写上面的XPath,以确保节点的顺序得到尊重,因此像可用时间(artnadj)这样的结构不会与相关人员匹配(artadjn

可用时间的可能表示形式*
<节点id=“0”begin=“1”cat=“np”>
<节点id=“1”begin=“1”pt=“art”text=“the”/>
<节点id=“2”begin=“2”pt=“n”text=“time”/gt;
<节点id=“3”begin=“3”pt=“adj”text=“可用”/>
&lt/节点>
#有关人士的可能代表*
<节点id=“0”begin=“1”cat=“np”>
<节点id=“1”begin=“1”pt=“art”text=“the”/>
<节点id=“2”begin=“2”pt=“adj”text=“相关”/>
<节点id=“3”begin=“3”pt=“n”text=“man”/gt;
&lt/节点>

一种方法是使用语料库中可用的begin属性的数值比较。它是数字递增的,因此如果我们想确保XPath的顺序是完整的,我们可以使用@cat=“np”来说的每个子节点的数值应该小于下一个节点的数值()。但正如我在上面所展示的,这会导致一个错误——在我刚才展示的简单示例代码中不会发生这种错误

另一个例子

<节点id=“0”开始=“2”>
<节点id=“1”begin=“2”>
<节点id=“2”begin=“2”/>
<节点id=“3”begin=“3”/>
&lt/节点>
<节点id=“4”begin=“5”>
<节点id=“5”begin=“5”/>
&lt/节点>
<节点id=“6”begin=“6”/>
&lt/节点>

此XPath应匹配:

/node/node[编号(@begin)<编号(../node/@begin)]

但是当使用XQuery处理器时,会出现上述错误不允许将多个项目的序列作为number()的第一个参数(“2”、“5”和…)


我尝试了@Michael Kay提供的解决方案,但似乎也遇到了同样的问题

XQuery

对于节点中的$node[节点[position()lt last()]on 每$n满足(number($n/@begin)lt number($n/以下同级::node/@begin))]
返回$node

资料

<节点id=“0”开始=“2”>
<节点id=“1”begin=“2”>
<节点id=“2”begin=“2”/>
<节点id=“3”begin=“3”/>
&lt/节点>
<节点id=“4”begin=“5”>
<节点id=“5”begin=“5”/>
&lt/节点>
<节点id=“6”begin=“6”/>
&lt/节点>

错误

SaxonCE.xslt20处理器14:48:49.809严重:XPathException在中
invokeTransform:不允许包含多个项的序列作为
number()的第一个参数(“5”、“6”)


更新日期:2017年4月19日

今天我遇到了一些意想不到的行为,这使得@har07提供的解决方案不再足够。我错误地认为not()子句只影响XPath中的节点(而不是XML中的所有节点)。换句话说,当将not()子句添加到XPath的最顶层节点时,其XML中的所有子节点都将具有固定的排序词序。(现在我是这样读的,这似乎很正常。)然而,我真正想要的是,单词顺序只在XPath中指定的节点上设置,而不可能在匹配XML中的其他节点上设置。希望这一点能得到更明确的解释

假设我想匹配以下XPath,一个包含rel=“det”pt=“vnw”lemma=“die”且至少两次rel=“mod”pt=“adj”cat=“np”

//节点[@cat=“np”和节点[@rel=“det”和@pt=“vnw”和@lemma=“die”]和计数(节点[@rel=“mod”和@pt=“adj”])>1]

但是增加了遵循此XPath顺序的要求,即

//节点[
@cat=“np”和
非(节点[
position()<last()
][number(@begin)>以下同级节点::节点/编号(@begin)]和
节点[
@rel=“det”和
@pt=“vnw”和
@引理=“死亡”
]及
计数(节点[
@rel=“mod”和
@pt=“adj”
])>1
]

因此rel=“det”必须在XML中的两个rel=“mod”之前出现。这很好,所有匹配项都是正确的,但并没有找到所有预期的匹配项。原因是not()行显然针对所有XML节点,而不是XPath指定的节点。如果发现某个节点不符合not规则,则不会有匹配项-即使该节点未在XPath中指定。例如,上面的XPath将匹配以下XML,因为在cat=“np”内部有一个节点的begin属性大于其下一个同级节点,这是规则所不允许的

<节点begin=“4”cat=“np”id=“8”rel=“obj1”>
<node begin=“4”id=“9”pos=“det”pt=“vnw”rel=“det”word=“die”lemma=“die”/gt;
<node begin=“5”id=“10”pos=“adj”pt=“adj”rel=“mod”word=“veelzijdige”/gt;
<node begin=“6”id=“11”pos=“adj”pt=“adj”rel=“mod”word=“getalenterde”/gt;
<node begin=“7”id=“12”pos=“noun”pt=“n”rel=“hd”word=“figuren”/gt;
<node begin=“8”id=“31”index=“1”rel=“obj1”/>
<node begin=“2”id=“32”index=“2”rel=“obj2”/gt;
&lt/节点>

但是,我希望这个cat=“np”匹配,并使not()函数不那么具有攻击性,即只需要XPath中指定的节点(在本例中是rel=“det”pt=“vnw”lemma=“die”,以及两个rel=“mod”pt=“adj”节点)遵循顺序要求,其中begin属性应小于XPath结构的下一项。允许XPath中未指定的cat=“np”中的其他项具有大于其下一个同级项的属性

请注意,XPath结构的最后一项(与示例XML中的id=“11”相匹配)不一定要有一个begin属性,该属性低于其XML中的后续节点(XPath中未指定)

和前面一样,我对如何使用纯XPath选项解决这个问题特别感兴趣,但也欢迎使用XQuery替代方案。最好是将XPath结构作为输入,并将“字顺序”应用于最顶层节点及其所有子节点的函数。鼓励使用此处所示的XPath示例代码和用法

关于您面临的a-sequence-of-more-item-is-not-allowed异常,请注意XPath 2.0及以上版本和XQuery支持在路径步骤上调用函数(../number())。也就是说,您可以在单个节点上调用number(),一次传递一个begin属性以避免异常:

/node/node[number(@begin)<./node/number(@begin)]

但是,当至少有一个begin属性值大于当前节点的begin属性的同级node时,上述XPath中使用的谓词表达式的计算结果为true,这似乎不是所需的行为

您可以对建议的XQuery应用相同的修复程序,但显然还有另一个类似的问题,因为lt被用来比较一个值与一系列值(要清楚,我指的是建议的XQuery中的第二个lt)。您可以尝试以下稍加修改的XQuery:

节点中$node的

[
节点[position()lt last()]on 每$n
不满足($n/以下同级::节点[number(@begin)lt number($n/@begin)])
]
返回$node

<

发表评论