Reputation: 87
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.
Upvotes: 1
Views: 2048
Reputation: 24826
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>
Upvotes: 1