[xsl] Partial sort of a schema-valid xml into a schema-valid xml

Subject: [xsl] Partial sort of a schema-valid xml into a schema-valid xml
From: "Gierschner, Frank" <Frank.Gierschner@xxxxxxxxxxxx>
Date: Tue, 2 May 2006 14:54:03 +0200
Hello xsl(t) experts and users.

I am new to XSLT and tried to find an answer to my topic in the book
"Essential XML" (Box/Skonnard/Lam) as well as in the corresponding "Quick
Reference" and in the FAQs and lists mentioned in the mulberrytech posting
guidelines for a while but I didn't find a real match or I was unable to use
the correct keywords or to read between the lines.

My task is as described in the subject to transform a given schema-valid xml
into a new schema-valid xml (refering to the same schema) but with a distinct
part of it to appear sorted. The simplified schema specifies the following:

	<!-- other definitions omitted -->
	<xs:complexType name="A_TYPE">
		<xs:sequence>
			<!--  other child elements omitted  -->
			<xs:element ref="A" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute name="NAME" type="xs:string" use="required"/>
		<!-- other attributes omitted -->
	</xs:complexType>

	<xs:element name="A" type="A_TYPE"/>

	<!-- definitions for a container -->
	<xs:element name="container">
		<xs:complexType>
			<xs:sequence>
				<xs:element ref="A" minOccurs="0" maxOccurs="unbounded"/>
				<xs:element ref="B" minOccurs="0" maxOccurs="unbounded"/>
				<xs:element ref="C" minOccurs="0"/>
			</xs:sequence>
			<xs:attribute name="NAME" type="xs:string" use="required"/>
			<!-- other attributes omitted -->
		</xs:complexType>
	</xs:element>

	<!-- the document type -->
	<xs:element name="mydoctype">
		<xs:complexType>
			<xs:sequence>
				<xs:element ref="container" minOccurs="0" maxOccurs="unbounded"/>
			</xs:sequence>
			<!-- other attributes omitted -->
		</xs:complexType>
	</xs:element>

The elements A shall be sorted by their attribute 'NAME' recursively, i.e. as
the A elements itself form a tree all sibling A's shall appear sorted by
NAME.

I use this XSL stylesheet with Xalan 1.9(Xerces 2.6) [XSLT 1.0] via the
distributions test program Xalan.exe (until now I haven't applied Xalan to my
project because I want to test before I start coding):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
	<xsl:output method="xml" version="1.0" encoding="UTF-16" indent="yes"/>

	<xsl:template match="node()">
		<xsl:choose>
			<xsl:when test='local-name(current())="A"'>
				<xsl:copy>
					<xsl:apply-templates select="* | @*">
						<xsl:sort select="@NAME" data-type="text" order="ascending"/>
					</xsl:apply-templates>
				</xsl:copy>
			</xsl:when>
			<xsl:otherwise>
				<xsl:copy>
					<xsl:apply-templates select="node()|@*" />
				</xsl:copy>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

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

</xsl:stylesheet>

When I apply this XSL stylesheet to an XML file which only contains A's within
the 'container' of 'mydoctype' everything is fine (and sorted). When I use an
XML file which contains all the specified element types (i.e. also elements B
and C), the stylesheet appliance distorts the required sequence ordering
within the 'container' elements as follows:

<?xml version="1.0" encoding="UTF-16" ?>
<mydoctype ... some attributes ...>
  <container NAME="cont1" ... some more attributes ...>
    <C>
      <!-- C's children -->
    </C>
    <B ... attributes ...>
      <B ... attributes ... />
    </B>
    <A ... attributes ...>
      <A ... attributes ...>
        <A ... attributes ...>
          . . .
        </A>
      </A>
    </A>
    <B ... attributes ...>
      <B ... attributes ... />
    </B>
    <A ... attributes ...>
      <A ... attributes ...>
        . . .
      </A>
    </A>
    . . .
  </container>
</mydoctype>

During debugging with XMLSpy I encounter the elements to be evaluated in the
same way as they are written to the target file but initially I expected an
output behaviour like SAX, i.e. elements are processed as they appear, sorted
and then written back to the target file (well of course this might be more
memory- and time-consuming).

So, can you please tell me how I should proceed?! (I really would like NOT to
start deep in the implementation specific details of XSLT processors if
possible)

I read something about schema-aware XSL and tried to bind my xsl to the schema
which the xml data is bound to but failed apparently due to namespace issues.
Could this be a solution?


Regards
 Frank

Current Thread