Solved

XSL: add new element inside a node i want to copy over

Posted on 2014-02-12
11
480 Views
Last Modified: 2014-02-13
I want to copy over an entire node and it's contents BUT i want to also append a new element as well.

So for instance, I have
<Response>
      <Group Price="100" Num="1">      
       ... (many other nodes within)
      </Group>
</Response>

I want to copy <Group> and inside this node create a new element
<Sequence>1</Sequence>

//where value of Sequence number will be something I'll calculate later  (there could be more than 1 sequence) But for testing purposes just place a "1".


So the output would be
      <Group Price="42800" Num="1">      
       ... (many other nodes within)
      
      <Sequence>1</Sequence>
      
      </Group>



Is this even plausible?
Right now I'm only copying the Group
<xsl:copy-of select="/test/Response/Group"/>
0
Comment
Question by:badtz7229
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
11 Comments
 
LVL 60

Accepted Solution

by:
Geert Bormans earned 500 total points
ID: 39854530
You need to build an identity copy
which controls the copy at every level

and have a second more specific template for group
that copies at that level, but adds the Sequence

copy-of for subtrees only works well if you don't need influence on a deeper level

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:template match="node()">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="Group">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()"/>
            <Sequence>1</Sequence>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

Open in new window

0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 39854542
zc2 suggested in your previous question to move away from for-each in favour of apply-templates. This question is a good example of the power that brings
0
 

Author Comment

by:badtz7229
ID: 39854552
i have a template which i'm using to call this <xsl:copy-of select="/test/Response/Group"/>
(which i know is wrong).
so how then would i incorporate your suggestion within a template?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:badtz7229
ID: 39854590
i think i just answered my own question . i have the following

    <xsl:template match="node()">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
   
    <xsl:template match="/test/Response/Group">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()"/>
            <Sequence>1</Sequence>
        </xsl:copy>
    </xsl:template>


and the following call inside another template.
      <xsl:apply-templates select="/test/Response/Group"/>

and it worked.
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 39854612
yes indeed
replace
<xsl:copy-of select="/test/Response/Group"/>
with
<xsl:apply-templates select="/test/Response/Group"/>

if the identity copy is bothering other nodes, put a mode="inner-copy" or so on each apply-templates and the two templates I posted

like this

<xsl:apply-templates select="/test/Response/Group" mode="inner-copy"/>

and

<xsl:template match="node()" mode="inner-copy">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()" mode="inner-copy"/>
        </xsl:copy>
    </xsl:template>
   
    <xsl:template match="Group" mode="inner-copy">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()" mode="inner-copy"/>
            <Sequence>1</Sequence>
        </xsl:copy>
    </xsl:template>

being specific in the template match
<xsl:template match="/test/Response/Group">

is only necessary if there are Group elements at other levels too
otherwise this is enough
<xsl:template match="Group">
(with or without the mode, depending)
0
 

Author Comment

by:badtz7229
ID: 39854661
if i add  mode="inner-copy"/>
i see lots of free text (outputs contents of the input without building it into proper xml).

also, in the <xsl:apply-templates select="/test/Response/Group"/> call, can i pass parameters?
to  <xsl:template match="/test/Response/Group"> so that i can manipulate what the value of <sequence> would be?
0
 

Author Comment

by:badtz7229
ID: 39854664
i ask, bc i've only seen parameters used in call templates and not apply templates
0
 

Author Comment

by:badtz7229
ID: 39854677
sorry, disrgard that last comment about params. yes you can.
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 39854700
you can pass parameters, but only in XSLT2 you can "tunnel" them
in XSLT1 they will only be picked up by the next level down

about the mode ... aparently the identity copy is used by other nodes as well,
so drop the modes then
0
 

Author Closing Comment

by:badtz7229
ID: 39857280
thank u. this worked.
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 39857801
welcome
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many times as a report developer I've been asked to display normalized data such as three rows with values Jack, Joe, and Bob as a single comma-separated string such as 'Jack, Joe, Bob', and vice versa.  Here's how to do it. 
Today, the web development industry is booming, and many people consider it to be their vocation. The question you may be asking yourself is – how do I become a web developer?
In this tutorial viewers will learn how to customize the background color and font color of highlighted text using the ::selection element in CSS Begin by defining the selected text as an element in CSS by typing "::selection": Style the ::selection…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.
Suggested Courses

635 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question