【问题标题】:XSL: How to test if the current node is a descendent of another nodeXSL:如何测试当前节点是否是另一个节点的后代
【发布时间】:2009-12-11 06:17:02
【问题描述】:

我对 XSLT 还很陌生,但目前需要将它用于 CMS。我已经提出了一个问题,但我将尝试描述我的问题,而不涉及太多有关底层 CMS 的信息。如果您需要更多上下文来帮助我,我可以添加。

所以我要做的就是测试我的 xml 的节点是否是特定节点的后代。

<xsl:if test="$currentNode::IsADescendantOf($someNode)">
Write this out.
</xsl:if>

有什么想法吗?

提前致谢:)

【问题讨论】:

    标签: xml xslt descendant


    【解决方案1】:

    你应该使用联合操作和节点集大小比较:

    <xsl:if test="count($someNode|$currentNode/ancestor::*) = count($currentNode/ancestor::*)">
    Write this out.
    </xsl:if>
    

    如果 $someNode$currentNode 的祖先,$someNode|$currentNode/ancestor::* 将返回与 $currentNode/ancestor 相同的节点集: :*(节点集没有任何双标)。

    如果没有,由于联合,第一个节点集将比第二个多一个节点。

    【讨论】:

    • @Erlock:非常感谢您的帮助。辛苦了。
    【解决方案2】:

    一种可移植的(XPath 1.0 和 2.0)解决方案是:

    <xsl:if test="
      $currentNode/ancestor::*[generate-id() = generate-id($someNode)]
    ">
    Write this out.
    </xsl:if>
    

    这会沿着祖先轴并检查其中的每个元素。如果(且仅当)其中一个祖先的唯一 ID 与 $someNode 的唯一 ID 匹配,则生成的节点集不为空。

    非空节点集评估为真,因此条件满足。

    测试 - 查找所有 &lt;baz&gt; 的后代 &lt;foo&gt;

    <xml>
      <foo>
        <bar>
          <baz>Test 1</baz>
        </bar>
      </foo>
      <baz>Test 2</baz>
    </xml>
    

    <xsl:stylesheet 
      version="1.0" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    >
      <xsl:template match="/">
        <xsl:variable name="someNode" select="//foo[1]" />
    
        <!-- test each <baz> node if it has <foo> as a parent -->
        <xsl:for-each select="//baz">
          <xsl:if test="
            ancestor::*[generate-id() = generate-id($someNode)]
          ">
            <xsl:copy-of select="." />
          </xsl:if>
    
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>
    

    结果

    <baz>Test 1</baz>
    

    请注意,如果您指的是 实际 当前节点,就像我在 for-each 中所做的那样,则不需要单独的 $currentNode 变量。默认情况下,所有 XPath 都是相对于当前节点的。

    一种变体将是自上而下的方式。虽然它的效率较低(可能是几个数量级):

    <xsl:if test="
      $someNode[//*[generate-id() = generate-id($currentNode)]]
    ">
    Write this out.
    </xsl:if>
    

    【讨论】:

      【解决方案3】:

      查看 XSL/XPath 参考中的“祖先”轴

      <xsl:if test="ancestor::*[. is $somenode]">
      

      编辑:我正在和你一起学习。看看这是否可行(我希望我的 XSL 调试器可以在这个系统上使用 :-)

      【讨论】:

      • @Jim Garrison:感谢您的快速回复。这对我来说似乎很合理,但我收到了这个错误:System.Xml.Xsl.XslLoadException: Expected a node test, found '$'.
      • 你说得对,我的解决方案不完整。我没有方便的 XSL ref,但基本思想是您需要使用祖先轴来选择所有祖先节点,然后根据节点相等性将其过滤为 $somenode。
      • 非常感谢。现在我得到“is-same-node()' 是一个未知的 XSLT 函数”我会继续搞砸它,但如果你有任何其他想法,请告诉我。
      • 编辑为使用is 节点比较。见w3.org/TR/xpath20/#id-node-comparisons
      • 您应该指出,is 运算符在 XPath 1.0 中不可用,但 XPath 1.0 是迄今为止更常见的实现。
      【解决方案4】:

      答案很简单,

      你所要做的就是:

      <xsl:if test="count(ancestor::somenode)>0">
      

          ...然后添加其余部分

      逻辑是,如果节点是某个节点的后代,那么它将具有该节点的一个或多个。

      【讨论】:

        【解决方案5】:

        后代检查

        最好的方法是使用 descendant::* 轴。

        如果您有一段类似这样的 XML,并且想要匹配来自第一个 &lt;alpha&gt; 节点的后代 &lt;a&gt; 节点。

        XML

        <root>
        <!-- check for descendants of the following alpha node-->
        <alpha>
          <!-- match the following node-->
          <a>...</a>
          <b>...</b>
          <c>...</c>
        </alpha>
        <alpha>
          <a>...</a>
          <c>...</c>
        </alpha>
        </root>
        

        XSLT

        <xsl:if test="/root/alpha[1]/descendant::a[. is current()]">
        

        祖先检查

        这可能适用于大多数情况。

        <xsl:if test="ancestor::*[name() = $node]">
        

        在哪里

        <xsl:variable name="node" select="name(//alpha)"/>
        

        或者,如果您有多个要比较的节点并且需要确保它是节点匹配而不是名称匹配,则可以只使用 generate-id()。

        <xsl:variable name="node" select="generate-id(//alpha[3])"/>
        <xsl:if test="ancestor::*[generate-id(.) = $node]">
        

        is 比较运算符不能在比较祖先时使用 IMO,因为它需要叶节点,而叶节点没有后代。

        但我建议使用 descendant::* 轴,因为它更具可读性和灵活性。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-01-01
          • 2013-09-17
          • 2021-10-16
          • 1970-01-01
          • 2017-11-03
          • 1970-01-01
          • 2015-09-13
          相关资源
          最近更新 更多