xml – XPath拉多个匹配
(BaseX)错误
我在BaseX中的一个大型数据集上运行查询,但是一个XQuery正在崩溃我的程序,出现错误[XPTY0004]项目预期,序列找到:(属性begin {“6”},…).. 在我的查询中,我试图通过比较begin(XML中存在的一个属性)和number()来确保一个元素来到另一个元素之前.但是每当我在我的数据集上尝试最基本的XQueries(返回匹配节点)(例如,使用this online tool),我会收到类似于之前的错误:
所以我猜测节点的兄弟姐妹会发生什么事情,即这些节点有不止一个,而且还不清楚应该比较哪个节点.示例如下. 为什么订单很重要? XPath用于树形库的查询引擎:语言注释语料库.在某些情况下,我们希望节点按顺序进行匹配,有时并不重要.作为一个简单的例子:有时候,我们想要匹配一些具体的东西,如有关的人,订单文章,形容词,名词重要.在其他查询中,这并不重要,我们也想匹配短语,例如可用的时间,文章,名词的顺序可以是任何顺序. 换句话说,在第一种情况下,要尊重元素的顺序,在第二种情况下,它不应该遵循.这是一个可能的XPath表示,这种结构包含一个文章,一个形容词和一个名词. node[@cat="np" and node[@pt="art"] and node[@pt="adj"] and node[@pt="n"]] 默认情况下,XPath不关心这些元素的顺序,并且进行贪心搜索,即它也将匹配诸如可用时间(art,n,adj)之类的项目.但是我想重写上述XPath,以确保节点的顺序得到尊重,因此可以使用的时间(art,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> 一种方法是使用语料库中可用的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> 这个XPath应该匹配: /node/node[number(@begin) < number(../node/@begin)] 但是,当通过XQuery处理器时,您会得到上述错误.不允许多个项目的序列作为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 数据 <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> 错误
2017年4月19日更新 我今天碰到一些意想不到的行为,这使得@ 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] 但是增加的要求是遵循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 ] 所以rel =“det”必须在XML中的两个rel =“mod”之前发生.这工作正常,所有匹配都是正确的,但并不是所有的预期匹配都找到.原因是not()行显然是针对所有的XML节点而不是XPath指定的节点.如果找到不符合不规则的节点的行,则不会有匹配 – 即使在XPath中没有指定该节点.例如,上述XPath将不匹配以下XML,因为在cat =“np”内部存在一个开始属性大于其下一个兄弟节点的节点,这不是不允许的. <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> 然而,我希望这个cat =“np”匹配,并且使not()函数更不具有攻击性,即只需要在XPath中指定的节点(在这个例子中,rel =“det”pt =“vnw”lemma =“die “,并且两个rel =”mod“pt =”adj“节点)遵循begin属性应小于XPath结构的下一个项的顺序要求.在XPath中未指定的cat =“np”中的其他项目允许具有大于其下一个兄弟节点的属性. 请注意,XPath结构的最后一个项目(与示例XML中的id =“11”匹配)不一定必须具有低于XML中以下节点的begin属性(在XPath中未指定) . 像以前一样,我对如何用纯XPath选项来解决这个问题特别感兴趣,但XQuery的替代方案也是受欢迎的.优选地,作为将XPath结构作为输入的函数,并且将“单词顺序”应用于其最上面的节点及其所有后代.鼓励使用XPath作为示例的示例代码和用法.
关于您正在面对的一个以上的一个项目不允许的异常,请注意,XPath 2.0及更高版本和XQuery支持在路径步骤(… / number(…)上的函数调用)).也就是说,您可以在单个节点上调用number()一次传递一个begin属性,以避免异常:
/node/node[number(@begin) < ../node/number(@begin)] 但是,当至少存在一个具有begin属性值的同级节点大于当前节点的begin属性时,上述XPath中使用的谓词表达式将为true,这似乎不是所需的行为. 您可以对建议的XQuery应用相同的修复,但显然还有另一个类似的问题,因为用于将值与一系列值进行比较(很明显,我指的是建议的XQuery中的第2个) .您可以尝试以下,轻微修改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
如果我正确理解,您可以使用以下XPath: /node/node[ not( node[position() < last()] [number(@begin) > following-sibling::node/number(@begin)] ) ]
XPath应该返回所有第二级节点元素,其中,除了当前第二级节点中最后一个之外的每个子节点,以下兄弟节点中没有一个与当前子节点相比数字较小的begin属性值. 给出以下示例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> 只能选择第二个节点,因为它是唯一的以升序开始属性值的二级节点: <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> 2017年4月19日更新:
那么我们需要添加另一个谓词来指定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) ] 所以完整的表达如下: //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 ]
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |