1

My requirement is to convert the following array

<array> <value>755</value> <value>5861</value> <value>4328</value> </array> 

to this array.

<array> <int>755</int> <int>5861</int> <int>4328</int> </array> 

Following is my XSLT code to do the transformation & it works. Is it the correct way because in one post I saw the use of "identity template". but I haven't used it.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/array"> <xsl:element name="array"> <xsl:for-each select="value"> <xsl:element name="int"> <xsl:value-of select="." /> </xsl:element> </xsl:for-each> </xsl:element> </xsl:template> </xsl:stylesheet> 

3 Answers 3

1

Your current method works. It is more of a "pull" style stylesheet. The "push" style uses apply-templates.

You could shorten it a bit by using element literals, which makes it a little easier to read:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/array"> <array> <xsl:for-each select="value"> <int> <xsl:value-of select="." /> </int> </xsl:for-each> </array> </xsl:template> </xsl:stylesheet> 

A solution using the identity template and a custom template for the value element:

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes"/> <!--identity template, which copies every attribute and node(element, text, comment, and processing instruction) that it matches and then applies templates to all of it's attributes and child nodes (if there are any) --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!--Specialized template that matches the value element. Because it is more specific than the identity template above it has a higher priority and will match when the value element is encountered. It creates an int element and then applies templates to any attributes and child nodes of the value element --> <xsl:template match="value"> <int> <xsl:apply-templates select="@*|node()"/> </int> </xsl:template> </xsl:stylesheet> 
Sign up to request clarification or add additional context in comments.

2 Comments

what is the use of <xsl:element> tag if we can just put the tag?
I've updated with comments explaining the two templates in the modified identity template stylesheet.
1

You can do:

<xsl:template match="/array"> <array> <xsl:for-each select="value"> <int> <xsl:value-of select="." /> </int> </xsl:for-each> </array> </xsl:template> 

2 Comments

your code is more efficient than mine. right? what is the use of <xsl:element> tag if we can just put the tag?
In the <xsl:element>, you can use variables for the @name and the @namespace. If you know the name of the element and do not need to dynamically construct it, it is often preferred to use an element literal since it is shorter and "reads" like what the output will be.
0

Here is a quote from the accepted answer of your link:

XSL cannot replace anything. The best you can do is to copy the parts you want to keep, then output the parts you want to change instead of the parts you don't want to keep.

That is where the identity template comes into play: it copies everything not targetted by another matching template. The upshot is, that if your base XML contains other content than just the array, then you should also include the identity template in your xslt. But if you are sure that your xml will contain no other content, then you don't need it.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.