对于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个元素。 这里的错误是什么?你知道吗
XPath1.0有一个节点集的概念,其中每个
/
步骤根据节点标识消除重复项,因此您使用的单个XPath表达式不会给出包含同一节点的集两次,任何重复项都会被消除。你知道吗在XPath2.0中,当然
/
步骤运算符仍然具有相同的重复消除语义,但是在XPath3.1中有一个更通用的序列概念,它使用for .. return
(for $p in //X/Z/T[R1='ABC3']/parent::* return $p/preceding-sibling::*
)或!
(//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。使用以下样式表可以实现预期的输出:XSLT 1.0
正如Martin Honnen在回答中所指出的,为了得到两个单独的列表,有必要分别处理每个匹配节点的前面的兄弟节点。你知道吗
还要注意您的表达式:
是不必要的复杂:很明显,匹配的
T
的父级必须是Z
,因此您可以简单地编写:相关问题 更多 >
编程相关推荐