Solved

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

Posted on 2014-02-12
11
475 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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Replace value 2 55
CSS Formatting Getting Stripped 1 35
Page link not showing on Mobile Device 3 52
In wordpress, how did they do that? 3 14
This article describes how to create custom column layout styles for Bootstrap. The article uses 5 columns to illustrate the concept, but the principle can be extended to any number of columns.
This article discusses four methods for overlaying images in a container on a web page
In this Micro Tutorial viewers will learn how to create navigation buttons that change on rollover, using CSS (Continuation of the CSS Image Sprite tutorial) Create a parent ID for all the list items       - Specify position: absolute and display: block…
In this tutorial viewers will learn how to style a corner ribbon overlay for an image using CSS Create a new class by typing ".Ribbon":  Define the class' "display:" as "inline-block": Define its "position:" as "relative": Define its "overflow:" as …

734 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