如何在XSLT中限制祖先搜索的范围?

时间:2017-06-06 14:28:17

标签: xslt xslt-2.0

示例输入:

<body>
  <ul>
     <li>
       <p>Some text with <b><i><span style="color:red">formatting</span></i></b></p>
   </li>
</ul>
</body>

&#39; inline&#39;元素为bispan

假设上下文节点是示例中的嵌套span元素。

如何在没有搜索超过包含p元素的情况下获取所有祖先内联元素?

表达式ancestor-or-self::*[self::b | self::i | self::span]实际上应该有效,因为不能包含&#39; block&#39;的祖先内联元素。等级元素,例如pul

但是,我想知道是否有一些可以避免的性能成本,因为我认为搜索将继续超过包含p元素。有没有办法避免这种情况?

修改

这是我到目前为止所提出的:

<xsl:function name="my:getInlineSeq" as="element() *">
    <xsl:param name="pElem" as="element()" />
    <xsl:if test="$pElem[self::b | self::i | self::span]">
        <xsl:sequence select="my:getInlineSeq($pElem/parent::*)" />
        <xsl:sequence select="$pElem" />
    </xsl:if>
</xsl:function>

但是,我不确定是否有更好的标准&#39;解决这个问题的方法。

注意:代码中的$pElem/parent::*将始终返回一个元素,因为内联项必须具有块元素容器,例如ph1等。此外,假设是最初提供的$pElem参数始终是内联元素。

1 个答案:

答案 0 :(得分:3)

使用

<xsl:function name="mf:block" as="element()">
    <xsl:param name="inline" as="element()"/>
    <xsl:sequence select="$inline/ancestor::*[self::h1 | self::h2 | self::h3 | self::h4 | self::h5 | self::h6 | self::li | self::p][1]"/>
</xsl:function>

以及关于块和内联元素的假设,您可以在ancestor-or-self::*[self::b | self::i | self::span]

的上下文中重写match="span | b | i"
for $block in mf:block(.) return ancestor-or-self::*[. >> $block]

我认为(或假设你使用<xsl:variable name="block" select="mf:block(.)"/>ancestor-or-self::*[. >> $block]。我不知道这是否比你的尝试更好。

试图在http://xsltransform.net/3MvmrzK

处测试表达式
<xsl:template match="span | b | i">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="inline-ancestor" select="ancestor-or-self::*[self::b | self::i | self::span]/name()"/>
        <xsl:attribute name="test-block" select="for $block in mf:block(.) return ancestor-or-self::*[. >> $block]/name()"/>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

使用

为内联元素提供相同的结果
   <p>Some text with <b inline-ancestor="b" test-block="b"><i inline-ancestor="b i" test-block="b i"><span style="color:red" inline-ancestor="b i span" test-block="b i span">formatting</span></i></b></p>