W3C home > Mailing lists > Public > xmlschema-dev@w3.org > September 2000

Re: alpha release of schema rev transform sheet

From: Eric van der Vlist <vdv@dyomedea.com>
Date: Wed, 27 Sep 2000 16:19:36 +0200
Message-ID: <39D201F8.5CABA6F0@dyomedea.com>
To: "Henry S. Thompson" <ht@cogsci.ed.ac.uk>
CC: xmlschema-dev@w3.org
Henry,

Some "theoratical" thoughts about the namespaces handling in the
proposed transformation sheet.

Disclaimer: this is coming out of a reading of the transformation sheet,
not out of existing schemas and the number of schemas which could be
affected by this message is probably very low.

1) Determination of the "april XML schema" prefix.
--------------------------------------------------

This determination is done using a loop:

<xsl:variable name="prefix">
 <xsl:for-each
select="april:schema/namespace::*[.='http://www.w3.org/1999/XMLSchema']">
  <xsl:value-of select="local-name()"/>
 </xsl:for-each>
</xsl:variable>

A schema which would have the funny idea to define 2 prefixes for this
namespace:

<xsd:schema xmlns:xsd="http://www.w3.org/1999/XMLSchema"     
xmlns:xsd2="http://www.w3.org/1999/XMLSchema">

would produce something like:

<xsdxsd2:schema xmlns:xsdxsd2="http://www.w3.org/2000/10/XMLSchema" >

Proposed fixes:

1 a: keep only the first prefix:
----

<xsl:for-each
select="april:schema/namespace::*[.='http://www.w3.org/1999/XMLSchema'][1]">

1 b: Use the prefix used by the schema element:
----

 <xsl:variable name="prefix"
select="substring-before(name(/april:schema), ':')"/>

note:
----

The problem shouldn't occur for the target prefix since I don't see how
an attribute could have more than 1 namespace node.

2) Copy of the namespaces nodes.
-------------------------------

My understanding is that this copy is done only for the root element and
only for the namespaces which URI is not equal to the "april" uri:

<xsl:template match="april:schema">
 <!-- handle specially to get ns nodes copied -->
 <xsl:element name="{$p}schema"
namespace="http://www.w3.org/2000/10/XMLSchema">
   <xsl:for-each
select="namespace::*[not(.='http://www.w3.org/1999/XMLSchema')]">
    <xsl:copy/>
   </xsl:for-each>
   <xsl:apply-templates select="@*"/>
   <xsl:apply-templates select="node()"/>
  </xsl:element>
</xsl:template>

I think it would be far more generic to copy all the namespaces nodes
for all the elements, keeping the one which are not matching the "april"
uri unmodified and changing the uri when matching the april.

The problem is that I haven't found a way to generate a dynamique
namespace node with XSLT...

This would fit (unlikely) schemas such as:

<xsd:schema xmlns:xsd="http://www.w3.org/1999/XMLSchema" >

	<xsd:complexType name="authorType" content="elementOnly"
		xmlns:xsd2="http://www.w3.org/1999/XMLSchema">
		<xsd:element name="name" type="xsd2:string"/>
		<xsd:element name="nickName" type="xsd:string"/>
		<xsd:element name="born" type="xsd:string"/>
		<xsd:element name="dead" type="xsd:string"/>
	</xsd:complexType>

.../...

which is currently generating:

<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" >

	<xsd:complexType name="authorType">
		<xsd:sequence>
   <xsd:element name="name" type="xsd2:string"/>
		<xsd:element name="nickName" type="xsd:string"/>
		<xsd:element name="born" type="xsd:string"/>
		<xsd:element name="dead" type="xsd:string"/>
  </xsd:sequence>
	</xsd:complexType>

3) determination of the prefix per element
------------------------------------------

These 2 suggestions do not fix a still weirder case where a prefix would
be reused:

<xsd:schema xmlns:xsd="http://www.w3.org/1999/XMLSchema" >

	<xsd2:complexType name="authorType" content="elementOnly"
		xmlns:xsd2="http://www.w3.org/1999/XMLSchema"
		xmlns:xsd="my-uri">
		<xsd2:element name="name" type="xsd2:string"/>
		<xsd2:element name="nickName" type="xsd:string"/>
		<xsd2:element name="born" type="xsd:string"/>
		<xsd2:element name="dead" type="xsd:string"/>
	</xsd2:complexType>
	
is currently giving:

<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" >

	<xsd:complexType name="authorType">
		<xsd:sequence>
   <xsd:element name="name" type="xsd2:string"/>
		<xsd:element name="nickName" type="xsd:string"/>
		<xsd:element name="born" type="xsd:string"/>
		<xsd:element name="dead" type="xsd:string"/>
  </xsd:sequence>
	</xsd:complexType>

The generic behavior seems therefore to be for each element:

  - to find its prefix and use it.
  - to copy all the namespaces nodes not matching the april uri
unmodified.
  - to copy all the other nodes changing the uri.

Again, I have no idea of how you can create a dynamic namespace node (to
keep the same prefix).

4) Doing it the other way ?
---------------------------

If we can't preserve the prefixes (at least not in all the cases), why
couldn't we fix them and transform the references to these prefixes in
the attributes using them ?

The solution could be the 2 first line of 3) :

For each element:

  - to find its prefix and use it.
  - to copy all the namespaces nodes not matching the april uri
unmodified.

plus a transformation of the attributes which need to be transformed.

It could be done in a generic template, for instance:

<xsl:template match="@type" .../

in which you could check if the value starts with a prefix corresponding
to the april URI and replace it with the prefix which has been selected.

There might be simpler solutions, but, as far as namespaces is concerned
(there is no modification of structure), the following style sheet seems
to handle all the cases mentioned above:

--------------------
<?xml version='1.0'?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
 
 <xsl:output method="xml" indent="no"
doctype-system="http://www.w3.org/2000/10/XMLSchema.dtd"
doctype-public="-//W3C//DTD XMLSCHEMA 200010//EN"/>

<xsl:template match="*">
 	<xsl:variable name="prefix" select="substring-before(name(), ':')"/>
	<xsl:variable name="p">
		<xsl:choose>
			<xsl:when test="$prefix=''"><xsl:text></xsl:text></xsl:when>
		<xsl:otherwise><xsl:value-of select="$prefix"/>:</xsl:otherwise>
	</xsl:choose>
 	</xsl:variable>
	<xsl:element name="{$p}{local-name()}"
namespace="http://www.w3.org/2000/10/XMLSchema">
		<xsl:for-each select="namespace::*[. !=
'http://www.w3.org/1999/XMLSchema']">
			<xsl:copy/>
		</xsl:for-each>
		<xsl:apply-templates select="@*|*|text()">
			<xsl:with-param name="p" select="$p"/>
		</xsl:apply-templates>
	</xsl:element>
</xsl:template>

<xsl:template match="@*|text()">
	<xsl:copy/>
</xsl:template>


<xsl:template match="@type">
	<xsl:param name="p"/>
	<xsl:variable name="prefix" select="substring-before(., ':')"/>
	<xsl:variable name="prefix2">
		<xsl:choose>
			<xsl:when test="contains(., ':')">
				<xsl:value-of select="concat($prefix, ':')"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="''"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>
	<xsl:variable name="name">
		<xsl:choose>
			<xsl:when test="contains(., ':')">
				<xsl:value-of select="substring-after(., ':')"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="."/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>
	<xsl:variable name="uri"
select="../namespace::*[local-name()=$prefix]"/>
	<xsl:variable name="translated-prefix">
		<xsl:choose>
			<xsl:when test="$uri='http://www.w3.org/1999/XMLSchema'">
				<xsl:value-of select="$p"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$prefix2"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>
	<xsl:attribute name="type">
		<xsl:value-of select="concat($translated-prefix, $name)"/>
	</xsl:attribute>

</xsl:template>
</xsl:transform>
------------------------ 

Hope this helps.

Eric

"Henry S. Thompson" wrote:
> 
> I'd like to release this more widely tomorrow, but consider it _very_
> alpha.
> 
> Known _not_ to work with XT, uses features XT doesn't support.
> 
> Known to work with saxon, invoke as follows:
> 
> CLASSPATH=.../saxon.jar
> java com.icl.saxon.StyleSheet SCHEMADOC schemaRev.xsl [copyDefaults=yes]
> 
> I recommend against using copyDefaults, especially if you use have a
> <!DOCTYPE...> statement -- without it attributes with the default
> values will _not_ be copied.
> 
> I urgently need to know
> 
> 1) If it breaks with your input;
> 2) If it works with other XSLT interpreters;
> 3) If it takes schemas which were valid (per [1]) and produces ones
> which aren't (per [2]).
> 
> I'm prepared to listen to complaints about linebreaks.
> 
> I can't do much if anything about indentation.
> 
> I've worked pretty hard to preserve comments and PIs, let me know if
> anything's missing.
> 
> ht
> 
> [1] http://www.w3.org/2000/06/webdata/xsv
> [2] http://www.w3.org/2000/09/webdata/xsv
> 
>   ------------------------------------------------------------------------
>                        Name: schemaRev.xsl
>    schemaRev.xsl       Type: Iexplore File (text/xml)
>                 Description: XSLT Transform Sheet to rev XML Schema documents
> 
>   ------------------------------------------------------------------------
> 
> --
>   Henry S. Thompson, HCRC Language Technology Group, University of Edinburgh
>           W3C Fellow 1999--2001, part-time member of W3C Team
>      2 Buccleuch Place, Edinburgh EH8 9LW, SCOTLAND -- (44) 131 650-4440
>             Fax: (44) 131 650-4587, e-mail: ht@cogsci.ed.ac.uk
>                      URL: http://www.ltg.ed.ac.uk/~ht/

-- 
------------------------------------------------------------------------
Eric van der Vlist       Dyomedea                    http://dyomedea.com
http://xmlfr.org         http://4xt.org              http://ducotede.com
------------------------------------------------------------------------
Received on Wednesday, 27 September 2000 10:18:41 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Tuesday, 11 January 2011 00:14:18 GMT