Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

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

Posted on 2014-02-12
11
Medium Priority
?
481 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 2000 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
The Orion Papers

Are you interested in becoming an AWS Certified Solutions Architect?

Discover a new interactive way of training for the exam.

 

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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

Introduction A frequently asked question goes something like this:  "I am running a long process in the background and I want to alert my client when the process finishes.  How can I send a message to the browser?"  Unfortunately, the short answer…
SASS allows you to treat your CSS code in a more OOP way. Let's have a look on how you can structure your code in order for it to be easily maintained and reused.
In this tutorial viewers will learn how to define a gradient in CSS. Create a new HTML document with an internal stylesheet.: Create a div in CSS and name it Gradient. Define the background as "linear-gradient(to right, #ee3668, black)". Ensure you …
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).
Suggested Courses

704 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