XSLT有条件地处理兄弟属性

时间:2015-01-29 06:15:37

标签: xml xslt

我有一个像这样的XML元素:

<element addr="::" value="1">

现在,如果value"0",我想将addr的值更改为"::"
对我来说,一个合乎逻辑的解决方案是这样的:

<xsl:template match="element/@*">
    <xsl:if test="@addr = '::'">
        <xsl:message>Matched</xsl:message>
        <xsl:attribute name="value">0</xsl:attribute>
    </xsl:if>
    <xsl:copy>
        <xsl:apply-templates select="node()" />
    </xsl:copy>
</xsl:template>

但这似乎不起作用。
我怎么能纠正这个?

2 个答案:

答案 0 :(得分:4)

使用复制所有内容的身份模板:

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

并使用修改您要修改的内容的模板规则覆盖它:

<xsl:template match="@value[../@addr = '::']">
  <xsl:attribute name="value">0</xsl:attribute>
</xsl:template>

答案 1 :(得分:1)

您尝试无效的原因是您的模板与"element/@*"匹配,即element的每个属性。在该上下文中,条件<xsl:if test="@addr = '::'">将永远不会返回true,因为这两个属性都没有(或可以拥有)名为addr的子属性。

要仅修改value属性,请将模板明确地与其匹配,或者:

<xsl:template match="@value">

或 - 如果您有其他具有名为value的属性的元素,并且您希望确保将其排除在外: -

<xsl:template match="element/@value">

然后您可以通过以下方式有条件地替换它(

<xsl:choose>
    <xsl:when test="../@addr = '::'">
        <xsl:attribute name="value">0</xsl:attribute>
    </xsl:when>
    <xsl:otherwise>
        <xsl:copy/>
    </xsl:otherwise>
</xsl:choose>

或者,你可以这样做:

<xsl:template match="element[@value and @addr = '::']">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="value">0</xsl:attribute>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

即。匹配具有需要更改的属性的元素并覆盖该属性。

请注意,我们假设您还有一个身份转换模板。