How to add an element using XSL.

P

ppl

I'm very new to XSL and have come across a stumbling block with a
recent assignment at work. I need to translate from XML to XML using
an XSL style sheet. Here is the input XML:
<?xml version="1.0" encoding="GB2312"?>
<?xml-stylesheet type="text/xsl" href="untitled9.xsl"?>
<booklist>
<book>
<title>bookname1</title>
<price>80</price>
<amount>3</amount>
</book>
<book>
<title>bookname2</title>
<price>60</price>
<amount>2</amount>
</book>
</booklist>

which needs to be transformed to:

<?xml version="1.0" encoding="GB2312"?>
<?xml-stylesheet type="text/xsl" href="untitled9.xsl"?>
<booklist>
<book>
<title>bookname1</title>
<price>80</price>
<amount>3</amount>
<total>240</total>
</book>
<book>
<title>bookname2</title>
<price>60</price>
<amount>2</amount>
<total>120</total>
</book>
</booklist>

I want to copy all content from source XML and insert an element on
specificall node, can anyone konw?
 
D

Dimitre Novatchev

Use the identity template and override it for "book" nodes like this:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:eek:utput omit-xml-declaration="yes"/>

<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="book">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<total>
<xsl:value-of select="price * amount"/>
</total>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

When this transformation is applied on your source.xml:


<?xml version="1.0" encoding="GB2312"?>
<booklist>
<book>
<title>bookname1</title>
<price>80</price>
<amount>3</amount>
</book>
<book>
<title>bookname2</title>
<price>60</price>
<amount>2</amount>
</book>
</booklist>

the wanted result is produced:

<booklist>
<book>
<title>bookname1</title>
<price>80</price>
<amount>3</amount>
<total>240</total></book>
<book>
<title>bookname2</title>
<price>60</price>
<amount>2</amount>
<total>120</total></book>
</booklist>

=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 
P

Patrick TJ McPhee

% <xsl:template match="@* | node()">
% <xsl:copy>
% <xsl:apply-templates select="@* | node()"/>
% </xsl:copy>
% </xsl:template>

I would write this one as

<xsl:template match="@* | node()">
<xsl:copy-of select='.'/>
</xsl:template>

Is there a difference in the result?
 
D

Dimitre Novatchev

Patrick TJ McPhee said:
% <xsl:template match="@* | node()">
% <xsl:copy>
% <xsl:apply-templates select="@* | node()"/>
% </xsl:copy>
% </xsl:template>

I would write this one as

<xsl:template match="@* | node()">
<xsl:copy-of select='.'/>
</xsl:template>

Is there a difference in the result?


Very big difference if you need to do something additional to just copying
the whole document. In this last and trivial case one would simply have:

<xsl:copy-of select="/" />

The identity template (the first above), is instantiated for every attribute
and node(). This makes it possible to override this generic template just
for some nodes in order to modify or delete them when copying to the output.


The "copy at once template precludes any possibility of overriding, if it is
instantiated at all. To use it for such "copy all with the exception of ..."
tasks would be extremely awkward -- you'll have to process all ancestor
nodes of the nodes that must be treated differently, then process these "to
be treated differently" nodes, and only then use xsl:apply-templates, in
order to copy the rest of the tree.



=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,813
Latest member
lawrwtwinkle111

Latest Threads

Top