How to override the values in an xml using xsl

2019-08-10 07:56发布

i have an xml file as below.

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


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

I need to change the salience value based on the ruleType.

For example if the ruleType(<ruleType>IC</ruleType>) is IC then i need to generate an xml as below.

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

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

if the ruletype is GC(<ruleType>GC</ruleType>) then i need to generate as below.

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

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

    </attributes>
</rule>

and sometimes i may get ruleType as empty in that case i need to generate as below.

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

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

Even if it get empty attributes then also i need to generate as above with some default salience value as 10.

I need to modifyc the value elements only assosciated attributeName(salience). If the attributeName is other than salience then i need to put as it is in my resultant xml.

I am using xsl 1.0.

Please provide me some pointers to do the same.

标签: xslt
1条回答
走好不送
2楼-- · 2019-08-10 07:58

The key to your task is to use the well known Identity Transformation and override the wanted nodes as required.


[XSLT 2.0] You can exploit new XPath 2.0 if construct and XSLT 2.0 possibility to define custom function, thus minimizing the code to two , easy readable, templates.

<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] For example, even if you could use a single template based on xsl:choose instruction, I would use a separate template for each value to be overridden, mainly for readability.

<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>
查看更多
登录 后发表回答