How to override the values in an xml using xsl
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 salienc开发者_运维问答e 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.
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>
精彩评论