 |
| 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
|
|
|
|

December 6th, 2013, 12:59 AM
|
|
Registered User
|
|
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
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..
|
|

December 6th, 2013, 04:37 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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
|
|

December 6th, 2013, 04:54 AM
|
|
Registered User
|
|
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
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
|
|

December 6th, 2013, 06:14 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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
|
|

December 6th, 2013, 08:28 AM
|
|
Registered User
|
|
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
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>
|
|

December 6th, 2013, 08:35 AM
|
|
Registered User
|
|
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
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
|
|

December 6th, 2013, 11:38 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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
|
|

December 6th, 2013, 12:48 PM
|
|
Registered User
|
|
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Thanks mhkay! This solved my problem
|
|

December 8th, 2013, 03:16 AM
|
|
Registered User
|
|
Join Date: May 2011
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
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
|
|

December 8th, 2013, 02:14 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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
|
|
 |