Re: [xsl] Modifying namespace definitions in xs:schema elements

Subject: Re: [xsl] Modifying namespace definitions in xs:schema elements
From: Wolfgang Laun <wolfgang.laun@xxxxxxxxx>
Date: Sun, 11 Oct 2009 10:59:34 +0200
Ken,

first, thank you for the quick reply. It wasn't smooth sailing, but I
think I've reached home port. Below is the complete stylesheet, with
comments to tell y'all the tacks and turns I made. (This is only my
third day of XSLT programming, so I'll admit that I was using the W3C
document for version 1.0 as a reference :-\ )

Best,
Wolfgang

The XSLT processors I'm using (on Linux/Ubuntu)

$ xsltproc --version
Using libxml 20632, libxslt 10124 and libexslt 813
xsltproc was compiled against libxml 20632, libxslt 10124 and libexslt 813
libxslt 10124 was compiled against libxml 20632
libexslt 813 was compiled against libxml 20632

xalan-j_2_7_1

The XSLT:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema";
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns:com="a.b.com">
<!--XXX Up here I had to add the namespace prefix definition for the
one to be added to xs:schema,
 otherwise the XSLT processors would refuse the use of 'com', below. -->

<xsl:template match="xs:schema">
 <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">

<!--XXX Without the com prefix, <xsl:namespace> has no effect on
<xs:schema>. But
the introduced namespace is propagated to child nodes, as can be seen when
not
not using a prefix and not reconstructing descendants. -->
   <xsl:namespace name="com">a.b.com</xsl:namespace>
   <xsl:attribute name="targetNamespace">a.b.com</xsl:attribute>

 <!--XXX This, too, appears to be required to make xmlns:com="..."
appear in <xs:schema>. -->
   <xsl:attribute name="com:blech">42</xsl:attribute>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates/>
 </xsl:element>
</xsl:template>

<!--XXX Reconstructing elements below <xs:schema> to avoid the introduction
of
xmlns:com="..." all over the place doesn't appear to be necessary now. -->
<xsl:template match="*" >
  <xsl:copy>
    <xsl:apply-templates select="* | @* | text()"/>
  </xsl:copy>
</xsl:template>

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

<xsl:template match="xs:element">
  <xsl:copy>
    <xsl:for-each select="node() | @*">
      <xsl:choose>
        <xsl:when test="node()">
          <xsl:copy-of select="."/>
        </xsl:when>

<!--XXX The whole point of the exercise: targetNamespace is used in
attribute values only.
There is a note in
http://www.w3.org/TR/xslt20/#creating-namespace-nodes which addresses
exactly this issue: "It is rarely necessary... needed is a situation
where the required namespace is used only within attribute values in
the result document..." Is it possible that implementations overlook
this rare occasion? -->
        <xsl:when test="name(.)='type' and not(contains(.,':')) ">
          <xsl:attribute name="type">
            <xsl:value-of select="concat('com:',.)"/>
          </xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
          <xsl:copy/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Input:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
           version="0.107">

  <xs:complexType name="FooType">
    <xs:sequence>
      <xs:element name="el1" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="BarType">
    <xs:sequence>
      <xs:element name="el2" type="FooType"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>

Result of XSLT:
<?xml version="1.0" encoding="UTF-8"?><xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"; targetNamespace="a.b.com"
xmlns:com="a.b.com" com:blech="42" version="0.107">

  <xs:complexType name="FooType">
    <xs:sequence>
      <xs:element name="el1" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="BarType">
    <xs:sequence>
      <xs:element name="el2" type="com:FooType"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>


On Sat, Oct 10, 2009 at 9:22 PM, G. Ken Holman
<gkholman@xxxxxxxxxxxxxxxxxxxx> wrote:
>
> At 2009-10-10 21:09 +0200, Wolfgang Laun wrote:
>>
>> given an XML Schema, I should split this schema into two parts,
>> according to properties of elements and complex/simpleTypes.
>> Basically, I've succeeded to do this, using a couple of XSLT
>> transformations. But...
>>
>> The original schema contains <xs:schema ... xmlns="a.b"
>> targetNamespace="a.b" ...>. I would like to modify this for one of the
>> results of the filtering, to become, e.g., xmlns="a.b.c"
>> targetNamespace="a.b.c". (The ultimate goal is to separate the
>> definitions made by the splt schemas into two different namespaces.)
>
> Fine.
>
>> Exploring the set of attributes in xs:schema (by <xsl:choose>
>> <xsl:when test="true()"> <xsl:value-of
>> select="concat(namespace-uri(),local-name())"/>...) has shown me that
>> the namespace definitions (xmlns="...") are not passed to template
>> processing.
>
> False.
>
> Namespace definitions are not passed to template processing as attribute
nodes, but they are passed to template processing as namespace nodes.
>
>> Does this mean that what I want to be done cannot be achieved at all,
>> using XSLT techniques?
>
> No, what you want can be done.  I hope the example below helps.
>
> . . . . . . Ken
>
> T:\ftemp>type wolfgang.xml
> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
>           xmlns="a.b"
>           targetNamespace="a.b">
>
> <xs:element name="doc">
>  <xs:complexType>
>    ...
>  </xs:complexType>
> </xs:element>
>
> </xs:schema>
>
> T:\ftemp>xslt2 wolfgang.xml wolfgang.xsl
> <?xml version="1.0" encoding="UTF-8"?><xs:schema xmlns="a.b.c"
xmlns:xs="http://www.w3.org/2001/XMLSchema"; targetNamespace="a.b.c">
>
> <xs:element name="doc">
>  <xs:complexType>
>    ...
>  </xs:complexType>
> </xs:element>
>
> </xs:schema>
> T:\ftemp>type wolfgang.xsl
> <?xml version="1.0" encoding="US-ASCII"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>                xmlns:xsd="http://www.w3.org/2001/XMLSchema";
>                version="2.0">
>
> <!--recreate the document element when encountered-->
> <xsl:template match="xsd:schema">
>  <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
>    <xsl:copy-of select="@*"/>
>    <!--replacing the target namespace information-->
>    <xsl:namespace name="">a.b.c</xsl:namespace>
>    <xsl:attribute name="targetNamespace">a.b.c</xsl:attribute>
>    <!--rest of the document-->
>    <xsl:apply-templates/>
>  </xsl:element>
> </xsl:template>
>
> <!--recostitute all other elements to avoid copying namespaces-->
> <xsl:template match="*">
>  <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
>    <xsl:apply-templates select="@*,node()"/>
>  </xsl:element>
> </xsl:template>
>
> <xsl:template match="@* | comment() | processing-instruction">
>  <xsl:copy/>
> </xsl:template>
>
> </xsl:stylesheet>
>
> T:\ftemp>
>
> --
> Upcoming: hands-on code list, UBL, XSLT, XQuery and XSL-FO classes
> in Copenhagen Denmark and Washington DC USA, October/November 2009
> Interested in other classes?  http://www.CraneSoftwrights.com/s/i/
> Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
> Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
> Video lesson:    http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18
> Video overview:  http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18
> G. Ken Holman                 mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
> Male Cancer Awareness Nov'07  http://www.CraneSoftwrights.com/s/bc
> Legal business disclaimers:  http://www.CraneSoftwrights.com/legal

Current Thread