XSLT: Moving node in document

  • Thread starter Claudio Jolowicz
  • Start date
C

Claudio Jolowicz

Suppose you have this document:

<root>
<node id="1">
<node id="4"/>
<node id="5"/>
</node>
<node id="2"/>
<node id="3"/>
</root>

How to write an XSLT stylesheet to make the node with id=5 a child of
the node with id=2?

The resulting document should look as follows:

<root>
<node id="1">
<node id="4"/>
</node>
<node id="2">
<node id="5"/>
</node>
<node id="3"/>
</root>

Thanks,

Claudio
 
D

David Carlisle

mostly you want to copy

<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

but you want to lose id 5

<xsl:template match="node[@id='5']"/>

and you want it to appear again in id 2

<xsl:template match="node[@id='2']">
<xsl:copy>
<xsl:copy-of select="@*|//node[@id='5']"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

David
 
C

Claudio Jolowicz

Thanks, simple and elegant.

Could you give me a hint how to parameterise this?

The following approach doesn't seem to work:

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

<xsl:param name="nodeparent" />
<xsl:param name="nodeid" />

<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<xsl:template match="node[@id='{$nodeid}']"/>

<xsl:template match="node[@id='{$nodeparent}']">
<xsl:copy>
<xsl:copy-of select="@*|//node[@id='{$nodeid}']"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
------------------------------------------------------

Easy enough to put an <xsl:choose> construct inside the identity
transform, and ignore the node satisfying "@id = $nodeid'. But how can
we then add that node to $nodeparent?

Claudio
 
V

Volkm@r

Claudio said:
Suppose you have this document:

<root>
<node id="1">
<node id="4"/>
<node id="5"/>
</node>
<node id="2"/>
<node id="3"/>
</root>
[...]

Not yet tested, but ...

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

<!-- put "id=5" into "id=2" -->
<xsl:template match="*[@id='2']">
<xsl:copy>
<xsl:apply-templates select="*[@id='5']"/>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<!-- match "id=5" and do NOTHING -->
<xsl:template match="*[@id='5']"/>

<!-- copy all other stuff -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
 
D

David Carlisle

Could you give me a hint how to parameterise this?

I knew you were going to ask that:)

<xsl:template match="node[@id='{$nodeid}']"/>


that would never work, { _never_ has any special meaning in an XPath
expression or, as here, in an XSLT pattern. They are used to _surround_
Xpath expressions in XSLT Attribute value templates, but they are not
part of Xpath.

The syntax should be

<xsl:template match="node[@id=$nodeid]"/>

except that in a failed attempt to prevent circular definitions, any use
of variables in match patterns is outlawed in XSLT1 so you can't do
this. (You will be able to do it in XSLT2 as this restriction is
dropped in XSLT2 draft.)

Similarly for

<xsl:copy-of select="@*|//node[@id='{$nodeid}']"/>

except that here of course you can use a variable in XSLT1:

<xsl:copy-of select="@*|//node[@id=$nodeid]"/>

The reason why the restriction on variables in match patterns is
annoying (and will be removed) is that it's easy to circumvent it, in
this case for example you could do:

<xsl:template match="node">
<xsl:choose>
<xsl:when test="@id='$nodeid"/>
<xsl:eek:therwise>
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:if test="@id=$nodeparent">
<xsl:copy-of select="//node[@id='$nodeid']"/>
</xsl:if>
<xsl:apply-templates/>
</xsl:copy>
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>
 
D

David Carlisle

oops sorry I left in two of your quotes

<xsl:copy-of select="//node[@id='$nodeid']"/>
^ ^


<xsl:copy-of select="//node[@id=$nodeid]"/>

David
 
Joined
Aug 29, 2008
Messages
1
Reaction score
0
Hello everyone, i am having an issue with my XSLT.

Here is the XML file i have and what i want it to look like.

<?xml version="1.0"?>
<root>
<Jobs>
<Job>
<JobId>5968</JobId>
<JobInformation>
<JobTitleId>167</JobTitleId>
<SpecialtyId>100070</SpecialtyId>
</JobInformation>
</Job>
<Job>
<JobId>13308</JobId>
<JobInformation>
<JobTitleId>167</JobTitleId>
<SpecialtyId>101821</SpecialtyId>
</JobInformation>
</Job>
</Jobs>
</root>

Desired Result

<?xml version="1.0"?>
<Jobs>
<Job>
<JobId>5968</JobId>
<JobTitleId>167</JobTitleId>
<SpecialtyId>100070</SpecialtyId>
</Job>
<Job>
<JobId>13308</JobId>
<JobTitleId>167</JobTitleId>
<SpecialtyId>101821</SpecialtyId>
</Job>
</Jobs>

What would the XSL be?
 

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

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,740
Latest member
AdolphBig6

Latest Threads

Top