获得元素的前一个兄弟?

时间:2012-10-16 14:18:20

标签: xslt

在这个扁平的XML中,如何才能获得具有指定名称的公司的“直接父母”? 我指的是一个Level = 0的元素,它是给定公司之前的第一个元素。

因此,鉴于公司名称为V,我需要获得Z公司。

<Companies>
  <Company>
     <Name>X</Name>
     <Level>1</Level>
   </Company>
   <Company>
     <Name>Y</Name>
     <Level>1</Level>
   </Company>
   <Company>
     <Name>Z</Name>
     <Level>0</Level>
   </Company>
  <Company>
     <Name>V</Name>
     <Level>1</Level>
   </Company>
</Companies>

这不起作用?

<xsl:value-of select="Companies/Company[Name='V']/preceding-sibling[Level=0]/last()

2 个答案:

答案 0 :(得分:2)

<xsl:value-of select="...">中,您可以更改

Companies/Company[Name='V']/preceding-sibling[Level=0]/last()

(Companies/Company[Name='V']/preceding-sibling::*[Level=0])[last()]

注意:

  • 前任兄弟轴与任何轴一样,必须后跟::和节点测试(例如*)。
  • last()不是您想要的位置步骤(尽管它在XSLT 2.0中可能是合法的......我不确定)。相反,您希望它位于谓词[ ]中。谓词[last()][position() = last()]
  • 的简写
  • 我在[last()]之前围绕所有内容放置括号的原因是@Lukasz提到的原因:preceding-sibling::有相反的方向。

因此,如果您说preceding-sibling::*[last()],您会以相反的顺序获得最后一个兄弟姐妹,即 document 顺序中的第一个兄弟姐妹!由于您实际上希望文档顺序中的 last 之前的兄弟姐妹,您可以像@Lukasz那样执行preceding-sibling::*[1];或者你可以用(...)[last()]做的。两者都有效。我稍微倾向于后者,我将在下面解释。

(...)[last()]表单有效,因为括号强制[last()]谓词应用于整个XPath表达式直到该点,而不仅仅是具有preceding-sibling::轴。因此,谓词将应用于不受preceding-sibling::轴'反向控制的表达式。因此,我们在文档顺序中选择最后一个节点(给定集合)。

如果没有括号,在某些XPath表达式中,谓词和轴的关联性可能会令人惊讶。您必须了解一些优先规则。不可否认,我对学习优先规则的细节有点懒惰。但是我的经验(在许多编程语言中)依赖于不那么明显的解析优先级规则是一种很好的方法,可以确保您的代码被下一个出现并试图调试或修改它的人误解或搞砸。 (一个月后,“下一个人”常常是我自己。)

答案 1 :(得分:1)

以下XSLT片段将从提供的示例XML中检索以前的Company元素:

<xsl:copy-of select="Companies/Company[Name='V']/preceding-sibling::*[1]" />

这将是:

<Company>
    <Name>Z</Name>
    <Level>0</Level>
</Company>

正如您所看到的那样,我们正在访问第一个节点(*[1]) - 这似乎违反了直觉 - 您可以找到进一步的解释here

编辑:我不确定你是否想要考虑Level = 0条件。