XSLT - 检查节点是否存在使用函数

时间:2016-04-21 11:29:40

标签: xml xslt xslt-2.0

我有xml如下,

<doc>
    <meta-data>
        <paper-name>ABC</paper-name>
        <paper-type>fi</paper-type>
    </meta-data>

    <section>
        <figure>fig1</figure>
        <figure>fig2</figure>
    </section>
</doc>

我的要求是,如果<paper-type>节点在<meta-data><figure>节点更改为<image>节点,则该节点可用。

所以,输出应该是,

<doc>
    <meta-data>
        <paper-name>ABC</paper-name>
        <paper-type>fi</paper-type>
    </meta-data>

    <section>
        <image>fig1</image>
        <image>fig2</image>
    </section>
</doc>

我写了以下xsl来完成这项任务,

<xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:function name="abc:check-paper-type" as="xs:boolean">
        <xsl:sequence select="root()//meta-data/paper-type"/>
    </xsl:function>

    <xsl:template match="figure[abc:check-paper-type()]">
        <image>
            <xsl:apply-templates/>
        </image>
    </xsl:template>

要在<paper-type>内查看<meta-data>节点,我在这里写了一个名为&#39; check-paper-type&#39;的函数。但是没有按预期工作。

有任何建议我如何组织我的功能检查,<paper-type>是否可用?

请注意,我需要通过检查<paper-type>节点是否存在来更改大量节点。因此,使用函数检查<paper-type>是否存在非常重要。

1 个答案:

答案 0 :(得分:1)

你的尝试无法工作的原因是:

  

在样式表函数的主体内,最初的重点是   不确定的;这意味着任何引用上下文项的尝试,   上下文位置或上下文大小是不可恢复的动态错误。   [XPDY0002]

http://www.w3.org/TR/xslt20/#stylesheet-functions

你可以做到:

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="figure[../../meta-data/paper-type]">
    <image>
        <xsl:apply-templates select="@*|node()"/>
    </image>
</xsl:template>

根据您的输入,这将产生:

<?xml version="1.0" encoding="UTF-8"?>
<doc>
   <meta-data>
      <paper-name>ABC</paper-name>
      <paper-type>fi</paper-type>
   </meta-data>
   <section>
      <image>fig1</image>
      <image>fig2</image>
   </section>
</doc>

或者,如果您需要重复引用节点的存在,可以将其定义为变量,而不是函数

<xsl:variable name="check-paper-type" select="exists(/doc/meta-data/paper-type)" />

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="figure[$check-paper-type]">
    <image>
        <xsl:apply-templates select="@*|node()"/>
    </image>
</xsl:template>