我想处理两个元素之间的节点;第二个由@xml:id标识,第一个通过此ID引用第二个。通常,其他兄弟元素(与该问题无关/应该照常处理)位于所讨论的两个元素之间。
<root>
... text i'm not interested in ...
<A ref="#id_1"/> interesting <C>text</C> no 1 <B xml:id="id_1"/>
... text i'm not interested in ...
<A ref="#id_2"/> interesting text no 2 <B xml:id="id_2"/>
... text i'm not interested in ...
</root>
我要寻找的是一个xPath命令,该命令为每个具有属性“ ref”的元素“ A”选择该元素之后的节点,直到具有a的“ ref”中提供的ID的特定元素“ B”。
因此在上面给出的示例中,对于第一个“ A”,应选择
"interesting <C>text</C> no 1"
第二个“ A”
"interesting text no 2"
(以此类推;“ A”和“ B”元素的数量非常高)。
到目前为止,我的粗略猜测是fn交集可能是解决方案的一部分。 (我正在使用xPath 2.0。)
答案 0 :(得分:0)
choroba用户在评论中写道,您可以使用XPath Axes获取值:
//A/following-sibling::text()[1]
要仅获取具有 ref 属性的元素,可以使用:
//A[@ref]/following-sibling::text()[1]
更新:也许节点集相交的凯西方法可以帮助您(see this SO):
/*/A[1]/following-sibling::node()[count(.|/*/B[1]/preceding-sibling::node()) = count(/*/B[1]/preceding-sibling::node())]
要再次发生,只需将所有[1]
替换为[2]
。
答案 1 :(得分:0)
此XPath 2.0表达式
/root/(
for $a in A,
$b in B[concat('#', @xml:id) = $a/@ref][1]
return .//text()[$b >> .][. >> $a]
)
选择此文本节点(为清楚起见添加了引号):
' interesting '
'text'
' no 1 '
' interesting text no 2 '
在https://xsltfiddle.liberty-development.net/bFN1y9t中测试
请注意:将for
expression用于“内部联接”。
在XPath 1.0中,没有办法声明关闭,因此也没有办法进行“内部联接”。但是,如果您确定开始和结束标记之间没有重叠,则可以使用:
/root//text()[
(preceding::A|preceding::B)[last()][self::A]
][(following::A|following::B)[1][self::B]
]
或
/root//text()[
preceding::*[self::A|self::B][1][self::A]
][following::*[self::A|self::B][1][self::B]
]
在http://www.xpathtester.com/xpath/a3051d2ad3af3423502b221bef6a580e中测试
我要寻找的是一个为每个选择的xPath命令 具有属性“ ref”的元素“ A”,此元素之后的节点 直到特定元素“ B”以及a的“ ref”中提供的ID。
如果现在要使用节点,则后代文本节点只需替换表达式中的路径即可:
XPath 2.0表达式
/root/(
for $a in A,
$b in B[concat('#', @xml:id) = $a/@ref][1]
return node()[$b >> .][. >> $a]
)
XPath 1.0表达式
/root/node()[
(preceding::A|preceding::B)[last()][self::A]
][(following::A|following::B)[1][self::B]
]