对于XML数据
<X>
<Y1>ABC1</Y1>
<Y2>ABC2</Y2>
<Z>
<T>
<R1>ABC3</R1>
<R2>ABC4</R2>
</T>
<T>
<R1>ABC5</R1>
<R2>ABC6</R2>
</T>
</Z>
<Y1>ABC7</Y1>
<Y2>ABC8</Y2>
<Z>
<T>
<R1>ABC3</R1>
<R2>ABC9</R2>
</T>
<T>
<R1>ABC5</R1>
<R2>ABC9</R2>
</T>
</Z>
</X>
我编写了一个示例python文件,如下所示
from lxml import etree
tree = etree.parse('test.xml')
for i in tree.xpath("//X/Z/T[R1='ABC3']/parent::*/preceding-sibling::*"):
print(i.tag, " - ", i.text)
我期望像这样的输出
Y1 - ABC1
Y2 - ABC2
Y1 - ABC1
Y2 - ABC2
Z -
Y1 - ABC7
Y2 - ABC8
但是收到了一个类似的
Y1 - ABC1
Y2 - ABC2
Z -
Y1 - ABC7
Y2 - ABC8
它应该打印所有前面的同级。对于“R1=ABC3”的第一个匹配,应打印Y1和Y2。对于“R1=ABC”的第二个匹配,它应该打印5个同级。总共应打印7个元素。 这里的错误是什么
XPath 1.0有一个节点集的概念,其中每个
/
步骤根据节点标识消除重复项,因此您使用的单个XPath表达式不会给出两次包含同一节点的集,任何重复项都会被消除在XPath2.0中,当然
/
步骤操作符仍然具有相同的重复消除语义,但有一个更通用的序列概念,它使用for .. return
(for $p in //X/Z/T[R1='ABC3']/parent::* return $p/preceding-sibling::*
)或XPath3.1!
(//X/Z/T[R1='ABC3']/parent::*!preceding-sibling::*
)允许包含重复项,请参见https://xqueryfiddle.liberty-development.net/eiZQFoV在XPath1.0中,您需要在宿主语言(例如Python)的循环中使用多个XPath求值,或者在Python中,您可以使用列表理解
element_list = [el for parent in tree.xpath("//X/Z/T[R1='ABC3']/parent::*") for el in parent.xpath("preceding-sibling::*")]
问题被标记为
xslt
,但您没有使用XSLT。可以使用以下样式表实现预期输出:XSLT1.0
正如Martin Honnen在回答中指出的那样,有必要分别处理每个匹配节点的前面兄弟节点,以获得两个单独的列表
还要注意,您的表达式:
是不必要的复杂:显然,匹配的
T
的父级必须是Z
,因此您可以简单地编写:相关问题 更多 >
编程相关推荐