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 January 16th, 2011, 05:50 AM
Registered User
 
Join Date: Jan 2011
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Question a weird XSLT namespace transformation problem

Hello

I have quite a strange problem with XSLT transformation, and I have no idea where even to start looking for a solution :

In my input file I have something like:

Code:
<store  xmlns:food="http://www.food-names">

   <element type="food:chocolate">Fazer chocolate</item>

</store>
Let's say I want to transform "element" to "item". In my output file I then have

Code:
<store>

   <item type="food:chocolate">Fazer chocolate</item>

</store>
The "xmlns:food="http://www.food-names"" declaration is missing. Which is quite understandable, because formally this namespace is not referenced in the file at all. But, actually it IS referenced, but from INSIDE the "type" attribute VALUE - but this cannot be noticed by XSLT.. at least this is what I think the reason is.

My question is: How to force the XSLT sheet to include ALL namespace declarations that were there in the input file (even the "unused ones")? Or maybe there is some other solution to my problem?

Or maybe I understood the reason of my problem incorrectly.. ?

(If I add to my input file something like <element food:type="chocolate">Fazer chocolate</item> the namespace IS included correctly. But I am working with already existing files and standards and I cannot adjust them. And without this namespace included, the output file is no longer correct for other tools that use it)

My XSLT part responsible for this transformation looks something like that:

Code:
<xsl:template match="/*"> <!-- matches root node-->
	<xsl:element name="{name(.)}">			
         	  <xsl:apply-templates select="node()|@*"/>	      			
	</xsl:element>    	  
</xsl:template>

<!-- copy all attributes -->
	<xsl:template match="@*">
		<xsl:copy-of select="."/>
	</xsl:template>	
	
<!-- copy all nodes -->
	<xsl:template match="*">
		<xsl:element name="{name()}" >			
			<xsl:apply-templates select="node()|@*"/>
		</xsl:element>				
	</xsl:template>
Please help! Any ideas highly appreciated ;)

Last edited by monami; January 16th, 2011 at 05:53 AM.. Reason: just text formatting
 
Old January 16th, 2011, 06:33 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

> How to force the XSLT sheet to include ALL namespace declarations that were there in the input file

Just use

Code:
<xsl:copy>
in place of

Code:
<xsl:element name="{name()}">
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old January 16th, 2011, 03:12 PM
Registered User
 
Join Date: Jan 2011
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thank you mhkay, after some modifications I came up with this code:

Code:
<!-- copy all attributes -->
<!-- copy all nodes -->
<xsl:template match="*">
      <xsl:copy-of select="."/> 	          			          	                  	  				           				
</xsl:template>
which works fine, replacing this part:

Code:
<!-- copy all attributes -->
	<xsl:template match="@*">
		<xsl:copy-of select="."/>
	</xsl:template>	
	
<!-- copy all nodes -->
	<xsl:template match="*">
		<xsl:element name="{name()}" >			
			<xsl:apply-templates select="node()|@*"/>
		</xsl:element>				
	</xsl:template>
BUT, the thing is, that besides copying the nodes I also need to make few little modifications (as the XSLT purpose would suggest;)), which I didn't mention.. For example I need to add one attribute to the root element. And when I use the "<xsl:copy>" I cannot add attributes afterwards (due to the "Cannot have an attribute node (..) whose parent is a document node" error message). I could use the optional use-attribute-sets attribute for "<xsl:copy>", but this attribute is not available for "<xsl:copy-of>". And if I use "<xsl:copy>" instead of "<xsl:copy-of>" I don't have the children copied, only the attributes (which seems strange to me)...

.. putting <xsl:apply-templates/> after <xsl:copy> does not work either (probably for the same reason as adding the attributes does not work) - I have the element copied twice, first time without children and my additional attribute and second with children and without the attribute..

I'm stuck again..
 
Old January 16th, 2011, 07:57 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

If you need to add attributes to the outermost element node, just add a template rule that does so:

Code:
<xsl:template match="/*">
  <xsl:copy>
     <xsl:apply-templates select="@*"/>
     <xsl:attribute name="extra">value</xsl:attribute>
     <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>
All the problems you describe are caused by writing incorrect code. If you show us the actual code you wrote, we can explain why it's behaving the way it is and what you should do to fix it. Be specific; it's hard to help you debug your code if you only describe it in general terms.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old January 17th, 2011, 06:29 PM
Registered User
 
Join Date: Jan 2011
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thank you for helping:) Okay, you're right about being specific. I thought being more general will make it more clear.

However, this is the part of my actual code I am struggling with now:

Input file:
Code:
<?xml version="1.0" encoding="UTF-8"?>

<RuleML
xmlns="http://www.ruleml.org/0.9/xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xsi:schemaLocation="http://www.ruleml.org/0.9/xsd http://www.ruleml.org/0.9/xsd/hornlogeq.xsd">


  <aaa xmlns:mmm="http://www.w3.org/2001/XMLSchema" o="mmm:aa">
    <w>
      <ras s="assss"/>
    </w>
  </aaa>
  
  <bbb ob="xs:bb">
  </bbb>

</RuleML>
Desired output file:
Code:
<?xml version="1.0" encoding="UTF-8"?>

<RuleML
xmlns="http://www.ruleml.org/0.91/xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xsi:schemaLocation="http://www.ruleml.org/0.91/xsd http://www.ruleml.org/0.91/xsd/hornlogeq.xsd">


  <aaa xmlns:mmm="http://www.w3.org/2001/XMLSchema" o="mmm:aa">
    <w>
      <ras s="assss"/>
    </w>
  </aaa>
  
  <bbb ob="xs:bb">
  </bbb>

</RuleML>
My current xslt:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.ruleml.org/0.91/xsd"
xmlns:ruleml="http://www.ruleml.org/0.9/xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="ruleml">
		
	<xsl:output method="xml" version="1.0"/>
  
<xsl:template match="/*">
    <xsl:copy>
        
       <xsl:attribute name="xsi:schemaLocation">
				  <xsl:variable name="url">http://www.ruleml.org/0.91/xsd</xsl:variable>				  
				  <xsl:variable name="file" select="substring-after(@xsi:schemaLocation, 'http://www.ruleml.org/0.9/xsd/')" />
				  <xsl:value-of select="concat($url, ' ', $url, '/', $file)" />		
			  </xsl:attribute>    	
        
      <xsl:copy-of select="@*[name() != 'xsi:schemaLocation']"/>
                        
      <xsl:apply-templates/>
      
    </xsl:copy>        
        
	</xsl:template>  

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

</xsl:stylesheet>
My current output file:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<RuleML xmlns="http://www.ruleml.org/0.9/xsd" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xsi:schemaLocation="http://www.ruleml.org/0.91/xsd http://www.ruleml.org/0.91/xsd/hornlogeq.xsd"> 
 
 
  <aaa xmlns:mmm="http://www.w3.org/2001/XMLSchema" o="mmm:aa"> 
    <w> 
      <ras s="assss"/> 
    </w> 
  </aaa> 
  
  <bbb ob="xs:bb"> 
  </bbb> 
 
</RuleML>
The red line is wrong - it should be 0.91 instead of 0.9. I suppose this is because I am using "copy", not creating a new element with the same name. But without using copy, the "xmlns:xs="http://www.w3.org/2001/XMLSchema" and xmlns:mmm="http://www.w3.org/2001/XMLSchema" lines are omitted... How to preserve both all the namespace definitions and updating the xmlns=.... ?





Similar Threads
Thread Thread Starter Forum Replies Last Post
problem with xslt transformation Enthrall XSLT 9 July 28th, 2010 03:14 AM
XSLT apply-templates namespace problem mariokofler XSLT 4 March 11th, 2010 10:27 AM
Problem in replacing XML namespace using XSLT kris13 XSLT 16 December 23rd, 2009 05:43 AM
weird namespace thing happening Martijn XSLT 6 January 26th, 2007 01:00 PM
dynamic xslt -> xslt creation namespace problem jkmyoung XSLT 2 July 15th, 2006 12:42 AM





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