我应该使用哪个:前::或前兄弟::?

时间:2015-08-09 04:19:43

标签: xml xslt xpath

我在犹豫是否在XSL中编写precedingpreceding-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]

请给我你的意见和建议。

3 个答案:

答案 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
  • 在增强的XML中,这将选择“John”
  

2)前面:: staff [2]

前面的轴也是一个反向轴,但它不是遍历兄弟节点,而是覆盖已经传递的所有节点(意思是:如果节点仍在当前的祖先轴中) ,它没有被选中),深度优先(意思是:staff中的文本节点来自staff个孩子,它们来自team兄弟姐妹。)

在这里你要问:

  • 获取与staff匹配的所有前面的节点,即空,Tanaka,Sato和John(按此顺序)。
  • 选择您找到的第二个
  • 在增强的XML中,这将选择Tanaka
  

3)../ team [1] / staff [1]

..parent::node()的缩写。这意味着取当前节点的父节点(它是根元素sales_division

在这里你要问:

  • 转到父sales_division
  • 从那里开始,找到第一个匹配team
  • 的孩子
  • 从那里找到匹配staff
  • 的第一个孩子
  • 在增强的XML中,这是John

因此,总之,它取决于实际的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是可变的以及修复了多少。