0

在这个平面 XML 中,我如何获得具有给定名称的公司的“直系父母”?我的意思是一个具有 Level = 0 并且是给定公司之前的第一个元素的元素。

因此,鉴于公司名称是 VI 需要获得公司 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()
4

2 回答 2

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 中可能是合法的......我不确定)。相反,您希望它在 predicate[ ]中。谓词[last()]是 的简写[position() = last()]
  • 我之前把括号括起来[last()]的原因是@Lukasz 提到的一个原因: Thepreceding-sibling::有一个相反的方向。

因此,如果您说preceding-sibling::*[last()]您以相反的顺序获得最后一个前面的兄弟,即文档顺序中的第一个前面的兄弟!由于您实际上想要文档顺序中的最后一个同级,因此您可以preceding-sibling::*[1]像@Lukasz 那样做;或者你可以用我所做的(...)[last()]。两者都是有效的。我稍微喜欢后者,我将在下面解释。

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

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

于 2012-10-16T14:35:03.020 回答
1

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

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

这将是:

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

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

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

于 2012-10-16T14:28:48.580 回答