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 September 3rd, 2010, 10:36 AM
Registered User
 
Join Date: Sep 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Default 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>
 
Old September 3rd, 2010, 10:55 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

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:
ebaerwald (September 3rd, 2010)
 
Old September 3rd, 2010, 11:18 AM
Registered User
 
Join Date: Sep 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Default

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!
 
Old September 3rd, 2010, 11:29 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

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.
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
The Following User Says Thank You to samjudson For This Useful Post:
ebaerwald (September 3rd, 2010)
 
Old September 3rd, 2010, 11:38 AM
Registered User
 
Join Date: Sep 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Default

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!
 
Old September 3rd, 2010, 12:16 PM
Registered User
 
Join Date: Sep 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Default 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?????
 
Old September 3rd, 2010, 12:25 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

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
 
Old September 3rd, 2010, 12:31 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

>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
 
Old September 7th, 2010, 09:53 AM
Registered User
 
Join Date: Sep 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Default 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
 
Old September 7th, 2010, 10:35 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

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





Similar Threads
Thread Thread Starter Forum Replies Last Post
Copy command not working nayaz VBScript 1 July 5th, 2007 05:24 AM
template to copy namespaces matrixman XSLT 0 May 4th, 2007 08:21 AM
XML to EXCEL ATTRIBUTE NOT WORKING pallone XSLT 4 September 7th, 2006 02:17 AM
Need to copy all nodes, attributes, and namespaces juaniux XSLT 4 October 22nd, 2004 04:39 PM
Get Working Copy... not working Enkiel Classic ASP Basics 0 April 21st, 2004 01:41 PM





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