我在犹豫是否在XSL中编写preceding
或preceding-sibling
,例如下面的示例xml。
<sales_division>
<team area="Tokyo">
<staff>Sato</staff>
<staff>Tanaka</staff>
</team>
<team area="Osaka">
<staff>Ueda</staff>
<staff>Suzuki</staff>
</team>
</sales_division>
如果当前节点为team(@Osaka)
,并且我想获得staff(Sato)
的第一子节点team(@Tokyo)
,那么我应该如何正确编写Xpath?
我想下面有三个选项。
1) preceding-sibling::team/staff[1]<br>
2) preceding::staff[2]<br>
3) ../team[1]/staff[1]
请给我你的意见和建议。
答案 0 :(得分:4)
在我看来,你(也)问这些轴实际上做了什么。正如迈克尔和哈尔已经指出的那样,这取决于更大的图景是否选择一个而不是另一个。在实践中,preceding
和较小范围preceding-sibling
的需要可能是代码嗅觉的标志,它们的性能可能是有害的,具体取决于输入和谓词。
我们假设您的输入略有不同:
<sales_division>
<team area="New York">
<staff>John</staff>
</team>
<team area="Tokyo">
<staff>Sato</staff>
<staff>Tanaka</staff>
</team>
<staff />
<team area="Osaka">
<staff>Ueda</staff>
<staff>Suzuki</staff>
</team>
</sales_division>
1)previous-sibling :: team / staff [1]
前一个兄弟轴是一个反向轴,这意味着它通过你的兄弟姐妹从下到上。 staff
步骤实际上是child::staff
,这本身就是一个前进的步骤。
在这里你要问:
team
staff
2)前面:: staff [2]
前面的轴也是一个反向轴,但它不是遍历兄弟节点,而是覆盖已经传递的所有节点(意思是:如果节点仍在当前的祖先轴中) ,它没有被选中),深度优先(意思是:staff
中的文本节点来自staff
个孩子,它们来自team
兄弟姐妹。)
在这里你要问:
staff
匹配的所有前面的节点,即空,Tanaka,Sato和John(按此顺序)。3)../ team [1] / staff [1]
..
是parent::node()
的缩写。这意味着取当前节点的父节点(它是根元素sales_division
)
在这里你要问:
sales_division
team
staff
因此,总之,它取决于实际的XML结构。 preceding-sibling
的典型用例是XML的顺序已知并且有意义(例如,两个坐标,其中前一个兄弟是经度,当前是纬度)。
在实践中,我经常看到你需要一个元素,它是之前的或之后的当前节点。在这种情况下,..
(父)语法可能是最好的方法,可能从节点集中排除当前节点。这在XSLT 2.0和3.0中比在1.0中更容易。
答案 1 :(得分:1)
最好编写一个有意义的 XPath,因为它更易于阅读,并且更易于维护。所以,我会说我更喜欢第一种方式,因为它最接近你的意图的英文描述:
preceding-sibling::team/staff[1]
或甚至更具体(如有必要):
preceding-sibling::team[@area='Tokyo']/staff[1]
此外,元素位置通常不那么有意义,并且在XML排列稍有变化时容易破解,因此我建议不要过多依赖元素位置索引。
答案 2 :(得分:1)
如果您确切知道XML中的内容,则不需要任何这些表达式,您只需编写“Sato”即可。您可能需要导航XML,因为您对其结构有所了解,但您并不完全了解其内容。因此,您浏览它的方式是使用您所知道的内容来发现您不知道的内容。这使我们无法帮助您,因为您没有告诉我们有多少XML是可变的以及修复了多少。