I have an XML document, I want one of the attributes to change it's value.
First I copied everything from input to output using:
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
And now I want to change the attribute "type" in any element named "property". But I don't know how to do it. Could someone please help? Thanks!
-
You need a template that will match your target attribute, and nothing else.
<xsl:template match='XPath/@myAttr'> <xsl:attribute name='myAttr'>This is the value</xsl:attribute> </xsl:template>This is in addition to the "copy all" you already have (and is actually always present by default in XSLT). Having a more specific match it will be used in preference.
tomato : I've tried it without the "copy all" part and it only got what was between the tags. None of the tag themselves or the attributes got copied.Richard : @coderx: Would need to see a sample, not sure what you mean. -
Tested on a simple example, works fine:
<xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="@type[parent::property]"> <xsl:attribute name="type"> <xsl:value-of select="'your value here'"/> </xsl:attribute> </xsl:template>Edited to include Tomalak's suggestion.
Tomalak : An alternative version would beWelbog : Agreed. Your way is probably more intuitive as it matches up more logically with what the template is for.Tomalak : That's what I wanted to say in the original comment as well, but forgot to actually type it. ;-)Richard : @Tomalak: Depends. I would prefer the parent/@type. But this is clearly subjective.Dimitre Novatchev : property/@type is better as it is more clear and understandable. Probably even more efficient (by several microseconds :) ) -
For the following XML:
<?xml version="1.0" encoding="utf-8"?> <root> <property type="foo"/> <node id="1"/> <property type="bar"> <sub-property/> </property> </root>I was able to get it to work with the following XSLT:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="//property"> <xsl:copy> <xsl:attribute name="type"> <xsl:value-of select="@type"/> <xsl:text>-added</xsl:text> </xsl:attribute> <xsl:copy-of select="child::*"/> </xsl:copy> </xsl:template> </xsl:stylesheet> -
This problem has a classical solution: Using and overriding the identity template is one of the most fundamental and powerful XSLT design patterns:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <!-- --> <xsl:param name="pNewType" select="'myNewType'"/> <!-- --> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <!-- --> <xsl:template match="property/@type"> <xsl:attribute name="type"> <xsl:value-of select="$pNewType"/> </xsl:attribute> </xsl:template> </xsl:stylesheet>When applied on this XML document:
<t> <property>value1</property> <property type="old">value2</property> </t>the wanted result is produced:
<t> <property>value1</property> <property type="myNewType">value2</property> </t> -
I had a similar case where I wanted to delete one attribute from a simple node, and couldn't figure out what axis would let me read the attribute name. In the end, all I had to do was use
@*[name(.)!='AttributeNameToDelete'] -
Hello
I have below XSLT which copies XML form source to destination.
<xsl:param name="seq" select="position()"/> <xsl:template match="@*|node()">But position() is assigning only one value to all nodes in the output, Can some one please tell me how to generate sequence in the Rollnumber should increase with a value of 1 for every node
0 comments:
Post a Comment