如何使用xsl覆盖xml中的值

时间:2011-07-25 05:58:53

标签: xslt

我有一个xml文件,如下所示。

<rule>  
<ruleType>IC</ruleType>
    <attributes>
        <attribute>
            <attributeName>salience</attributeName>
            <value>5</value>
        </attribute>


     <attribute>
        <attributeName>abc</attributeName>
        <value>123</value>
    </attribute>
    </attributes>
</rule>

我需要根据ruleType更改显着值。

例如,如果ruleType(<ruleType>IC</ruleType>)是IC,那么我需要生成如下的xml。

<rule>  
<ruleType>IC</ruleType>
    <attributes>
        <attribute>
            <attributeName>salience</attributeName>
            <value>100</value>
        </attribute>

     <attribute>
        <attributeName>abc</attributeName>
        <value>123</value>
    </attribute>
    </attributes>
</rule>

如果规则类型是GC(<ruleType>GC</ruleType>),那么我需要生成如下。

<rule>  
<ruleType>GC</ruleType>
    <attributes>
        <attribute>
            <attributeName>salience</attributeName>
            <value>50</value>
        </attribute>

     <attribute>
        <attributeName>abc</attributeName>
        <value>123</value>
    </attribute>

    </attributes>
</rule>

有时我可能会将ruleType视为空,在这种情况下我需要生成如下。

<rule>  
<ruleType/>
    <attributes>
        <attribute>
            <attributeName>salience</attributeName>
            <value>10</value>
        </attribute>

     <attribute>
        <attributeName>abc</attributeName>
        <value>123</value>
    </attribute>
    </attributes>
</rule>

即使它获得空属性,我也需要生成如上所示的默认显着值为10.

我需要修改值元素只有assosciated attributeName(显着性)。 如果attributeName不是显着性,那么我需要将其放在我的结果xml中。

我正在使用xsl 1.0。

请提供一些指示来做同样的事情。

1 个答案:

答案 0 :(得分:1)

您的任务的关键是使用众所周知的身份转换并根据需要覆盖所需的节点。


[XSLT 2.0]您可以利用新的XPath 2.0 if构造和XSLT 2.0来定义自定义函数,从而将代码最小化为两个易读的模板。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:empo="http://stackoverflow.com/users/253811/empo"
    exclude-result-prefixes="empo">
    <xsl:output indent="yes"/>

    <xsl:function name="empo:default" as="item()">
        <xsl:param name="default"/>
        <attributes>
            <attribute>
                <attributeName>salience</attributeName>
                <value><xsl:value-of select="$default"/></value>
            </attribute>
        </attributes>
    </xsl:function>

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

    <xsl:template match="value[preceding-sibling::attributeName='salience']">
        <xsl:variable name="vRT" select="preceding::ruleType[1]"/>
        <xsl:copy>
            <xsl:value-of select="if ($vRT='IC') then 100
                else if ($vRT='GC') then 50
                else 10"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="attributes[count(attribute)=0]">
        <xsl:variable name="vRT" select="preceding-sibling::ruleType[1]"/>
        <xsl:copy-of select="if ($vRT='IC') then empo:default(100)
            else if ($vRT='GC') then empo:default(50)
            else empo:default(10)"/>
    </xsl:template>

</xsl:stylesheet>

[XSLT 1.0] 例如,即使您可以使用基于xsl:choose指令的单个模板,我也会使用单独的模板来覆盖每个值,主要是为了便于阅读。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

    <xsl:template match="value[preceding::ruleType[1]='IC' 
        and preceding-sibling::attributeName='salience']">
        <xsl:copy>100</xsl:copy>
    </xsl:template>

    <xsl:template match="value[preceding::ruleType[1]='GC'
        and preceding-sibling::attributeName='salience']">
        <xsl:copy>50</xsl:copy>
    </xsl:template>

    <xsl:template match="value[preceding::ruleType[1]=''
        and preceding-sibling::attributeName='salience']">
        <xsl:copy>10</xsl:copy>
    </xsl:template>

    <xsl:template match="attributes[count(attribute)=0 
        and preceding-sibling::ruleType[1]='IC']">
        <attributes>
            <attribute>
                <attributeName>salience</attributeName>
                <value>100</value>
            </attribute>
        </attributes>
    </xsl:template>

    <xsl:template match="attributes[count(attribute)=0 
        and preceding-sibling::ruleType[1]='GC']">
        <attributes>
            <attribute>
                <attributeName>salience</attributeName>
                <value>50</value>
            </attribute>
        </attributes>
    </xsl:template>

    <xsl:template match="attributes[count(attribute)=0 
        and preceding-sibling::ruleType[1]='']">
        <attributes>
            <attribute>
                <attributeName>salience</attributeName>
                <value>10</value>
            </attribute>
        </attributes>
    </xsl:template>

</xsl:stylesheet>