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

September 3rd, 2010, 10:36 AM
|
|
Registered User
|
|
Join Date: Sep 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
copy-namespaces attribute not working?
I'm trying to translate an input .xml that validates against a standard (say v1.xsd) to one that validates against a new standard (say v2.xsd).
When I tried to update my identity transform from a straight copy to using the XSLT v2.0 attribute: copy-namespaces="no" - it simply doens't work. Apparently it only suppresses namespaces not 'in use' (documentation confusing on this point...).
How do I ensure that elements of one namespace on an input all end up with the new namespace on the output (regardless of how I transformed them)?
I have other elements that have references to yet another namespace as well - and those need to remain 'untouched' (i.e., still referring to their original namespace). How do I do the above, while ensuring these other elements maintain their namespaces?
I tried swapping out the usual copy command in the identity transform with code that intercepts the elements - and creates a new element of the same name - (with the namespace= etc.) - but then the recursive nature of the identity transform stopped working. I tried explicitly adding an apply-templates with the text() command to force retrieving the text - and that seemed to help marginally but didn't solve it.
Current state of the so-called identity transform I'm experimenting with is below:
Code:
<xsl:template match="node()|@*">
<xsl:choose>
<xsl:when test="self::*">
<xsl:element name="{local-name(.)}" namespace="blah:blah:2.0">
<xsl:apply-templates select="text()"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="text()"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
|
|

September 3rd, 2010, 10:55 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
xsl:copy and xsl:copy-of will never change the name of an element (that is, move it into a different namespace). Your approach of using a recursive tree walk using templates that call xsl:element is fundamentally the correct one. However you have made it much more difficult than it needs to be. The following should do the trick:
Code:
<xsl:template match="*">
<xsl:element name="{local-name(.)}" namespace="blah:blah:2.0">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|
The Following User Says Thank You to mhkay For This Useful Post:
|
|
|

September 3rd, 2010, 11:18 AM
|
|
Registered User
|
|
Join Date: Sep 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Wow - thanks for the quick response!
Assuming what you provided is intended to replace the 'identity' transform --- I don't understand how that outermost template (with just the *) will match on all nodes - I thought that it had to have the node()|@* to ensure it would catch every node (type). Perhaps my assumption is wrong and I still need the identity template as well?
I tried placing that code in - Interstingly my processor is complaining now about a completely different location in my XSLT that it has not complained about before... Will be trying to figure out if it relates to this change or not.
thanks again!
|
|

September 3rd, 2010, 11:29 AM
|
 |
Friend of Wrox
|
|
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
|
|
The attributes don't need a template of their own as you are handling them inside that template. No attribute ever isn't the child of an element, so this is fine.
Not the above template also doesn't handle text nodes, only element nodes. text nodes are handled by the built in template which copies their contents.
|
|
The Following User Says Thank You to samjudson For This Useful Post:
|
|
|

September 3rd, 2010, 11:38 AM
|
|
Registered User
|
|
Join Date: Sep 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
So I guess the 'identity transform' samples I found and based my code on were essentially 'overkill' in that regard.... interesting...
Turns out that placing that new code has indeed caused (or revealed) a problem somewhere else --- It worked fine with the previous standard approach using the template matching on node()|@* (and with the apply-templates inside selecting on that same criteria) --- but with this new code swapped in - I'm now getting an error from the processor... not sure why that would happen...
...yet another mystery to solve... :o)
thanks!
|
|

September 3rd, 2010, 12:16 PM
|
|
Registered User
|
|
Join Date: Sep 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
So I can't use copy or copy-of then?
So,
If I understand correctly (and I hope I don't here... :o) - If I want my output to have a new namespace different than my input, I can't use copy or copy-of?
That can't be right.
Can it?????
|
|

September 3rd, 2010, 12:25 PM
|
|
Friend of Wrox
|
|
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
|
|
You are right, copy copies a node to the output, both its name and its namespace are copied, thus if you want to change the namespace then you need to use a template as already suggested, that changes the namespace with an xsl:element.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
|
|

September 3rd, 2010, 12:31 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
>If I understand correctly (and I hope I don't here... :o) - If I want my output to have a new namespace different than my input, I can't use copy or copy-of?
>That can't be right.
Yes, it is right. copy and copy-of make an exact copy - they don't allow you to make a copy whose name is different from the original. The namespace, of course, is part of the name.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|

September 7th, 2010, 09:53 AM
|
|
Registered User
|
|
Join Date: Sep 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Wow...
OK - well - that does seem odd to a newbie like me...
With the goal of XSLT to be transformation, and to not be able to use such a 'core' command as copy or copy-of is severely limiting.
I'll now need to go back through all of my code and replace all such commands with manual creation of elements (and children - for copy-of).
...weird...
(...it would be nice if the copy-namespaces command actually did as the name implies... and gave us control over the output namespace.)
thanks for the help/clarification!
e
|
|

September 7th, 2010, 10:35 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
The reason you think it's weird is that you think you are copying the XML unchanged; you haven't realised that you are changing it in a fundamental way, and that the operation you are performing is therefore a transformation rather than a copy. This is because you haven't fully understood the XML data model. Understanding the data model is key to fluency in XSLT, and makes the difference between loving XSLT and hating it.
If you were renaming all the elements to upper case, rather than renaming them to put them in a different namespace, I don't think you would find it weird that xsl:copy doesn't do the job.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|
 |