Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old December 6th, 2013, 12:59 AM
Registered User
 
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default How to add namespace to all nodes after root?

Hi experts,


My input XML is :

<?xml version="1.0" encoding="UTF-8"?>

<getResponse xmlns="https://test.com">

<ReturnMessage>

<recordCount/>

<returnCode/>

<returnMessage/>

</ReturnMessage>

</getResponse>

Here if you see that none of the nodes have any namespace prefix nor the child nodes.



What I want is, prefix and namespaces for all nodes. Also the prefix and namespace for root and immediate child node is same ns0 while for other nodes it is ns1.



ns0 and ns1 namespaces are different.



How can I get this in XSLT?

Is there any simple way? Please help!



Desired output XML:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:getResponse xmlns:ns0="https://test.com">
<ns0:ReturnMessage>
<ns1:recordCount xmlns:ns1="https://test.com/schema/"/>
<ns1:returnCode xmlns:ns1="https://test.com/schema/"/>
<ns1:returnMessage xmlns:ns1="https://test.com/schema/"/>
</ns0:ReturnMessage>
</ns0:getResponse>

Thanks
Gopal

Last edited by gopalbaliga; December 6th, 2013 at 05:49 AM..
 
Old December 6th, 2013, 04:37 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Your prose says "all elements except the root" but in your example, that would add the namespace to ReturnMessage. (and perhaps even to getResponse, if you take the XPath 1.0 definition of "root").

If the problem is as shown in your example, rather than as described in your narrative, then I would solve it by adding the new namespace to all elements that are currently in no namespace. That's done with two template rules:

Code:
<xsl:template match="*">
  <xsl:copy><xsl:apply-templates/></xsl:copy>
</xsl:template>

<xsl:template match="*[namespace-uri()='']">
  <xsl:element name="ns1:{local-name()}" namespace="https://test.com/schema">
    <xsl:apply-templates/>
  </xsl:element>
</xsl:template>
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old December 6th, 2013, 04:54 AM
Registered User
 
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi mhkay,

I have corrected the input XML. Here if you see that root node does not have any namespace prefix nor the child nodes.

What I want is, prefix and namespaces for all. Also the prefix and namespace for root and immediate child node is same ns0 while for other nodes it is ns1.

ns0 and ns1 namespaces are different.


How can I get this in XSLT?

Thanks
Gopal
 
Old December 6th, 2013, 06:14 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Oh dear, I made a mistake I don't usually make, I gave you code rather than an explanation. Usually I prefer to give an explanation and leave people to write the code themselves, that way, when they change the requirements, they don't expect you to revise the solution.

The basic model is that you define two template rules that match (a) the elements you don't want to change, and (b) the elements you want to move into a new namespace. The template rule for (a) is the standard identity template, and the template rule for (b) is a modified identity template that uses xsl:element to change the element name to a name in the new namespace. The only thing that leaves is to define match patterns that distinguish the nodes you want to rename from those you want to leave alone.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old December 6th, 2013, 08:28 AM
Registered User
 
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi mhkay,

I actually a novice in XSLT.

I tried your code as well. But it does not work.

I tries with different template rules like below. But I don't see any prefix added to the match nodes.

<!-- Copy Everything -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="getResponse">
<xsl:element name="ns0:{name()}" namespace="https://test.com">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>

<xsl:template match="recordCount">
<xsl:element name="ns1:{name()}" namespace="https://test.com/schema/">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
 
Old December 6th, 2013, 08:35 AM
Registered User
 
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

On further analysis I found that if my root node has a default namespace then the XSLT code does not work.

<getResponse xmlns="https://test.com">
<ReturnMessage>
<recordCount>0</recordCount>
<returnCode>0</returnCode>
<returnMessage>Successfully returned 0 records</returnMessage>
</ReturnMessage>
<AMTRequests/>
</getResponse>

And if I remove the namespace from getResponse root node

<getResponse>
<ReturnMessage>
<recordCount>0</recordCount>
<returnCode>0</returnCode>
<returnMessage>Successfully returned 0 records</returnMessage>
</ReturnMessage>
<AMTRequests/>
</getResponse>


Then I am getting the result as below:

<?xml version="1.0" encoding="utf-8"?>
<ns0:getResponse xmlns:ns0="https://test.com">
<ReturnMessage>
<ns1:recordCount xmlns:ns1="https://test.com/schema/">0</ns1:recordCount>
<returnCode>0</returnCode>
<returnMessage>Successfully returned 0 records</returnMessage>
</ReturnMessage>
<AMTRequests />
</ns0:getResponse>


So what to change in my XSLT if my root node has namespace like <getResponse xmlns="https://test.com">

to get the result as above? Please help.

My XSLT:

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


<!-- Copy Everything -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="getResponse">
<xsl:element name="ns0:{name()}" namespace="https://test.com">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>

<xsl:template match="recordCount">
<xsl:element name="ns1:{name()}" namespace="https://test.com/schema/">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>

</xsl:stylesheet>

Thanks
Gopal
 
Old December 6th, 2013, 11:38 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

AArghhh! You have edited the question since my first response, which makes a nonsense of my previous advice. Don't do that.

To match an element in a namespace you need to write match="p:local" where p is some prefix bound (in the stylesheet) to the namespace URI of the element, and local is the local name of the element.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old December 6th, 2013, 12:48 PM
Registered User
 
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks mhkay! This solved my problem
 
Old December 8th, 2013, 03:16 AM
Registered User
 
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi mhkay,

One last question.

I am almost able to generate the prefix and namespace except for nodes just after root node.

My input XML:

<getResponse xmlns="https://test.com">
<ReturnMessage>
<recordCount>0</recordCount>
<returnCode>0</returnCode>
<returnMessage>Successfully returned 0 records</returnMessage>
</ReturnMessage>
<AMTRequests/>
</getResponse>


MY XSLT:

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


<!-- Copy Everything -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="p:getResponse">
<xsl:element name="ns0:{name()}" namespace="https://test.com">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>

<xsl:template match="p:ReturnMessage">
<xsl:element name="ns0:{name()}" namespace="https://test.com">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>

<xsl:template match="recordCount">
<xsl:element name="ns1:{name()}" namespace="https://test.com/schema/">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>

</xsl:stylesheet>

This gives below result. Here the node (ReturnMessage) just after root node is not getting the prefix ns0. What could be the mistake in the XSLT code?

<ns0:getResponse xmlns:ns0="http://test.com">
<ReturnMessage xmlns="http://test.com">\
<ns1:recordCount xmlns:ns1="http://test1.com">0</ns1:recordCount><returnCode>0</returnCode>
<returnMessage>Successfully returned 0 records</returnMessage></ReturnMessage>
<AMTRequests xmlns="http://test.com"/>
</ns0:getResponse>




Thanks
Gopal
 
Old December 8th, 2013, 02:14 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

The element is in the right namespace, but not with the desired prefix. XSLT 1.0 says the processor can use any prefix it likes so long as the namespace is right, so you may be out of luck with your choice of XSLT processor. XSLT 2.0 is much more prescriptive: in this scenario, it requires the XSLT processor to use the prefix given.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference





Similar Threads
Thread Thread Starter Forum Replies Last Post
Moving child nodes to previous occurrance of the root node LearnerP XSLT 2 April 9th, 2012 04:24 AM
I used default namespace in my stylesheet but root element is not firing smandeh XSLT 2 June 9th, 2010 09:22 PM
Remove Namespace from root tag using xslt namespce prefix nisargmca XSLT 0 February 24th, 2010 01:08 AM
Need to convert an existing namespace and add new namespace to the SOAP xml Prabeen XSLT 10 April 28th, 2009 10:18 AM
Remove root namespace help? JohnBampton XSLT 2 March 6th, 2009 06:49 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.