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 April 21st, 2010, 02:01 PM
Friend of Wrox
 
Join Date: May 2004
Posts: 109
Thanks: 18
Thanked 0 Times in 0 Posts
Default How to copy namespace delcarations to result

Hi,

I am converting names in a schema to new names in another schema.

I have 3 schemas, one imports the next which imports the last. Each has their own namespace and elementFormDefault is qualified.

Here is head of the source schema:
Code:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
    xmlns="http://../nmitables"
    xmlns:nmiTable="http://../nmitable">
    
    <xs:import namespace="http://../nmitable" schemaLocation="nmi-Table.xsd"></xs:import>
and here is what get's written to the result:
Code:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    
      <xs:import namespace="http://../nmitable"
              schemaLocation="nmi-Table.xsd"/>
It's close, but missing some important namespace declarations, namely xmlns="http://../nmitables" and xmlns:nmiTable="http://../nmitable". The xmlns:xs="http://.../XMLSchema" declaration seems to have copied just fine.

The nmiTable prefix is used in the body of the result schema.

But I cannot figure out how to get the declarations written there as well.

Most of the work is accomplished with a recursive copy template as defined in "XSLT 2.0" 3rd Edition by Mr. Kay, and the liberal use of <apply-templates/> throughout the script.

I am using OxygenXML 11.2 with Saxon-EE 9.2.0.6

What important piece did I forget?
__________________
------------------------
Keep Moving Forward

GnuPG Key fingerprint = 1AD4 726D E359 A31D 05BF ACE5 CA93 7AD5 D8E3 A876

Michael Hare
 
Old April 22nd, 2010, 04:15 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

Nothing you have posted so far looks like an issue - it simply looks like the XSLT processor has removed unused namespace declarations from the output. They are both effectively the same XML document.
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
 
Old April 22nd, 2010, 05:00 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Contrary to what Sam says, "unused" namespace declarations can sometimes be important, especially in a vocabulary like XSD that uses prefixes in content.

But I can't tell what's wrong with your code without seeing your code. A general description of your code isn't enough for me to debug it.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old April 22nd, 2010, 12:00 PM
Friend of Wrox
 
Join Date: May 2004
Posts: 109
Thanks: 18
Thanked 0 Times in 0 Posts
Default

I appreciate the help.
I've tried to distill the script down to a minimum without losing something that might be important.
I only left in the code that processes 'elements' and removed the code for the other entity types (attributes, simpleTypes, complexTypes, etc..)

First, the source schema:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!--
=========================================================================
Test Namespace File
-->
 
<xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
xmlns:nmiTable="http://software.tx.fnc.fujitsu.com/nmitable"
xmlns="http://software.tx.fnc.fujitsu.com/nmitables">
 
<xs:import namespace="http://software.tx.fnc.fujitsu.com/nmitable" schemaLocation="nmi-Table.xsd"></xs:import>
 
<!--
Global Element: tables in the default namespace will be renamed to nms_tables
-->
<xs:element name="tables">
<xs:complexType>
<xs:sequence>
<!--
Nested Element: nmiTable:table references an element in another (known) namespace
This element will be renamed to nmiTable:nmiTable_table
-->
<xs:element ref="nmiTable:table" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
 
 
</xs:schema>
Next the script:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!--
Test Schema Conversion Namespace 
-->
<xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="nmi-Tables.xsd"xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:nmiTable="http://software.tx.fnc.fujitsu.com/nmitable">
 
 
<!--
Capture the default namespace for the file being processed
I work on 3 schemas, each with it's own namespace.
I need to rewrite the entity names with different prefixes
based on the namespace of the file.
-->
<xsl:variable name="defNS">
<xsl:value-of select="namespace-uri-for-prefix('',/*)"/>
</xsl:variable>
 
<!-- Replaces the base namespace -->
 
<!-- The prefix I use when rewriting -->
<xsl:variable name="nmsPrefix">nms_</xsl:variable>
<!-- The namespace -->
<xsl:variable name="nmiTablesNS">http://software.tx.fnc.fujitsu.com/nmitables</xsl:variable>
<!-- The namespace prefix -->
<xsl:variable name="nmiTablesNSprefix"></xsl:variable>
 
<!-- Replaces the namespace for 'nmi' (http://software.tx.fnc.fujitsu.com/nmiforms) -->
<xsl:variable name="nmiPrefix">nmi_</xsl:variable>
<xsl:variable name="nmiNS">http://software.tx.fnc.fujitsu.com/nmiforms</xsl:variable>
<xsl:variable name="nmiNSprefix">nmi</xsl:variable>
 
<!-- Replaces the namespace for 'nmiTable' (http://software.tx.fnc.fujitsu.com/nmitable) -->
<xsl:variable name="nmiTablePrefix">nmiTable_</xsl:variable>
<xsl:variable name="nmiTableNS">http://software.tx.fnc.fujitsu.com/nmitable</xsl:variable>
<xsl:variable name="nmiTableNSprefix">nmiTable</xsl:variable>
 
 
 
 
<xsl:output indent="yes" method="xml" version="1.0"/>
 
<!--
========================================================================================== 
-->
 
<xsl:template match="/">
 
<!-- GO! -->
<xsl:apply-templates/>
 
 
</xsl:template>
 
 
 
<!--
========================================================================================== 
Find global element definitions
-->
<xsl:template match="/xs:schema/xs:element">
 
<xsl:apply-templates select="." mode="global"/>
 
</xsl:template>
 
<!--
========================================================================================== 
Find all other element definitions.
-->
<xsl:template match="xs:element">
 
<xsl:apply-templates select="." mode="not-global"/>
 
</xsl:template>
 
 
<!--
========================================================================================== 
Write out the global element definition and it's contents
-->
<xsl:template match="xs:element" mode="global">
 
<xsl:element name="xs:element">
 
<xsl:apply-templates select="@name" mode="global"/>
 
<!-- Process the nested nodes -->
<xsl:apply-templates/>
 
</xsl:element>
 
</xsl:template>
 
<!--
========================================================================================== 
Write out the nested element
Determine if it is locally defined (uses @name) or a reference (uses @ref)
-->
<xsl:template match="xs:element" mode="not-global">
 
<xsl:element name="xs:element">
<xsl:if test="exists(@name)">
<xsl:apply-templates select="@name" mode="not-global"/>
</xsl:if>
 
<xsl:if test="exists(@ref)">
<xsl:apply-templates select="@ref" mode="not-global"/>
</xsl:if>
 
<!-- Process the nested nodes -->
<xsl:apply-templates/>
 
</xsl:element>
 
</xsl:template>
 
 
<!--
========================================================================================== 
Global element definitions need to have their name adjusted with a prefix
-->
<xsl:template match="xs:element/@name" mode="global">
 
<xsl:attribute name="name">
<xsl:call-template name="NSprefix">
<xsl:with-param name="value">
<xsl:value-of select="."/>
</xsl:with-param>
</xsl:call-template>
<xsl:apply-templates/>
</xsl:attribute>
 
<!-- Process the remaining attributes -->
<xsl:apply-templates select=".." mode="attrs"/>
 
</xsl:template>
 
<!--
========================================================================================== 
Locally defined elements do not need to have their name rewritten
-->
<xsl:template match="xs:element/@name" mode="not-global">
 
<xsl:attribute name="name">
<xsl:value-of select="."/>
<xsl:apply-templates/>
</xsl:attribute>
 
<!-- Process the remaining attributes -->
<xsl:apply-templates select=".." mode="attrs"/>
 
</xsl:template>
 
<!--
========================================================================================== 
Nested elements that reference global element definitions will need to 
have the ref value rewritten depending on what namespace the reference 
target exists
-->
<xsl:template match="xs:element/@ref" mode="not-global">
 
<xsl:attribute name="ref">
<xsl:call-template name="NSprefix">
<xsl:with-param name="value">
<xsl:value-of select="."/>
</xsl:with-param>
</xsl:call-template>
</xsl:attribute>
 
<xsl:apply-templates select=".." mode="attrs"/>
 
<xsl:apply-templates/>
 
</xsl:template>
 
<!--
==========================================================================================
This is the ReWrite engine. Inspect the input value and determine if it needs
to be rewritten and if so, how to rewrite it.
-->
<xsl:template name="NSprefix">
<xsl:param name="value"/>
 
<xsl:choose>
<!--
First, convert the entities with known namespace prefixes
-->
<!-- value has namespace: nmi -->
<xsl:when test="substring-before($value,':') eq $nmiNSprefix">
<xsl:value-of select="$nmiNSprefix"></xsl:value-of>
<xsl:text>:</xsl:text>
<xsl:value-of select="$nmiPrefix"/>
<xsl:value-of select="substring-after($value,':')"/>
</xsl:when>
 
<!-- value has namespace: nmiTable -->
<xsl:when test="substring-before($value,':') eq $nmiTableNSprefix">
<xsl:value-of select="$nmiTableNSprefix"></xsl:value-of>
<xsl:text>:</xsl:text>
<xsl:value-of select="$nmiTablePrefix"/>
<xsl:value-of select="substring-after($value,':')"/>
</xsl:when>
 
<!--
Next, convert the entities that do not have a namespace prefix
-->
<!-- nmiTable http://software.tx.fnc.fujitsu.com/nmitable -->
<xsl:when test="($defNS eq $nmiTableNS) and (not(contains($value,':')))">
<xsl:value-of select="$nmiTablePrefix"/>
<xsl:value-of select="$value"/>
</xsl:when>
 
<!-- nmiTables http://software.tx.fnc.fujitsu.com/nmitables -->
<xsl:when test="($defNS eq $nmiTablesNS) and (not(contains($value,':')))">
<xsl:value-of select="$nmsPrefix"/>
<xsl:value-of select="$value"/>
</xsl:when>
 
<!-- nmi http://software.tx.fnc.fujitsu.com/nmiforms -->
<xsl:when test="($defNS eq $nmiNS) and (not(contains($value,':')))">
<xsl:value-of select="$nmiPrefix"/>
<xsl:value-of select="$value"/>
</xsl:when>
 
<!--
All unknown namespace prefixes (such as 'xs:') will not be converted
-->
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
 
</xsl:template>
 
<!--
========================================================================================== 
I've written the element node with the name or ref attribute, now I need
to copy the remaining attributes to the result.
Couldn't think of a better way than to just march through all the possibilities
and write them out. This does give me the opportunity to intercept any specific 
attribute and do a rewrite on the value if I need to, such as type might
point to a simpleType defined in another namespace.
-->
<xsl:template match="xs:element" mode="attrs">
<xsl:if test="exists(@final)">
<xsl:attribute name="final">
<xsl:apply-templates select="@final"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@abstract)">
<xsl:attribute name="abstract">
<xsl:apply-templates select="@abstract"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@block)">
<xsl:attribute name="block">
<xsl:apply-templates select="@block"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@fixed)">
<xsl:attribute name="fixed">
<xsl:apply-templates select="@fixed"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@id)">
<xsl:attribute name="id">
<xsl:apply-templates select="@id"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@form)">
<xsl:attribute name="form">
<xsl:apply-templates select="@form"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@minOccurs)">
<xsl:attribute name="minOccurs">
<xsl:apply-templates select="@minOccurs"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@maxOccurs)">
<xsl:attribute name="maxOccurs">
<xsl:apply-templates select="@maxOccurs"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@nillable)">
<xsl:attribute name="nillable">
<xsl:apply-templates select="@nillable"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@substitutionGroup)">
<xsl:attribute name="substitutionGroup">
<xsl:apply-templates select="@substitutionGroup"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@type)">
<xsl:attribute name="type">
<xsl:apply-templates select="@type"/>
</xsl:attribute>
</xsl:if>
</xsl:template>
 
 
 
<!--
========================================================================================== 
All Purpose Recursive Copy
Catches everything
-->
<xsl:template match="@*|node()" mode="#all">
<xsl:copy copy-namespaces="no">
<xsl:copy-of select="@*" copy-namespaces="yes"/>
<xsl:apply-templates mode="#current"/>
</xsl:copy>
</xsl:template>
 
</xsl:stylesheet>
and finally, the result:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!--
=========================================================================
Test Namespace File
--><xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
 
<xs:import namespace="http://software.tx.fnc.fujitsu.com/nmitable"
schemaLocation="nmi-Table.xsd"/>
 
<!--
Global Element: tables in the default namespace will be renamed to nms_tables
-->
<xs:element name="nms_tables">
<xs:complexType>
<xs:sequence>
<!--
Nested Element: nmiTable:table references an element in another (known) namespace
This element will be renamed to nmiTable:nmiTable_table
-->
<xs:element ref="nmiTable:nmiTable_table" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
 
 
</xs:schema>
As you can see, both the default namespace and the nmiTable namespace have lost their declarations in the result schema. Everything else looks fine (to me).

Thanks,
__________________
------------------------
Keep Moving Forward

GnuPG Key fingerprint = 1AD4 726D E359 A31D 05BF ACE5 CA93 7AD5 D8E3 A876

Michael Hare
 
Old April 22nd, 2010, 12:16 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

You have said <xsl:copy copy-namespaces="no">, so it is not copying namespaces.

copy-namespaces only has any effect when you are copying an element (it means copy the element with/without its namespaces. So in <xsl:copy-of select="@*" copy-namespaces="yes"/> the copy-namespaces attribute is ignored, because you are not copying an element.

Also, in general, use <xsl:copy> rather than <xsl:element> if you want namespaces preserved.
__________________
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:
mphare (April 22nd, 2010)
 
Old April 22nd, 2010, 02:12 PM
Friend of Wrox
 
Join Date: May 2004
Posts: 109
Thanks: 18
Thanked 0 Times in 0 Posts
Default

As I was walking to lunch, the statement copy-namespaces="no" popped into my head. I just returned, set it to 'yes' and .. there are the namespaces..

Thanks again!
__________________
------------------------
Keep Moving Forward

GnuPG Key fingerprint = 1AD4 726D E359 A31D 05BF ACE5 CA93 7AD5 D8E3 A876

Michael Hare





Similar Threads
Thread Thread Starter Forum Replies Last Post
error CS0234: The type or namespace name 'Xml' does not exist in the namespace 'Syste shailesh_kumar C# 2008 aka C# 3.0 8 August 20th, 2009 03:11 AM
xsl:copy exclude namespace bonekrusher XSLT 2 April 22nd, 2009 07:10 AM
Changing namespace on copy rushman XSLT 2 November 12th, 2007 02:35 PM
Namespace copy problem francislang XSLT 3 February 20th, 2006 01:07 PM
copy-of xsi namespace chris_strub XSLT 2 October 2nd, 2004 10:32 PM





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