Improve company productivity with a Business Account.Sign Up

x
?
Solved

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

Posted on 2014-02-12
11
Medium Priority
?
487 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
  • 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
Easily Design & Build Your Next Website

Squarespace’s all-in-one platform gives you everything you need to express yourself creatively online, whether it is with a domain, website, or online store. Get started with your free trial today, and when ready, take 10% off your first purchase with offer code 'EXPERTS'.

 

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

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Styling your websites can become very complex. Here I'll show how SASS can help you better organize, maintain and reuse your CSS code.
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. 
In this tutorial viewers will learn how to position overlapping items using z-index in CSS. They will also learn the restrictions on the z-index property.  Create a new HTML document with an internal stylesheet.: Create a div in CSS and name it Red.…
In this tutorial viewers will learn how to style different bullet points for unordered lists in CSS. Begin with a normal unordered list; the default bullet point is a solid circle: In the CSS, create a defined class of unordered list by typing "ul.S…

595 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