Re: [xsl] recursive sorting by element name

Subject: Re: [xsl] recursive sorting by element name
From: "Davis Ford" <davisford@xxxxxxxxx>
Date: Thu, 29 Nov 2007 12:45:08 -0500
Wendell, thank you for the workaround.  This does indeed solve the
issue I'm seeing on Ubuntu.  I no longer get the runtime error from
the xsltproc binary.  Am testing it now with Java.

On Nov 29, 2007 12:21 PM, Wendell Piez <wapiez@xxxxxxxxxxxxxxxx> wrote:
> Davis,
>
> It's difficult to see why you're getting the inconsistent behavior
> without more info, and in particular who (if anyone) is out of
> conformance here. But a workaround shouldn't be too hard in any case. Try this:
>
> <xsl:template match="node()">
>    <xsl:copy>
>      <xsl:copy-of select="@*"/>
>      <!-- copy all the attributes before
>           applying templates to the children only -->
>      <xsl:apply-templates select="node()">
>        <xsl:sort select="@typeName"/>
>        <xsl:sort select="name(.)"/>
>        <xsl:sort/>
>      </xsl:apply-templates>
>    </xsl:copy>
> </xsl:template>
>
> Cheers,
> Wendell
>
>
> At 11:22 AM 11/29/2007, you wrote:
> >Hi, a follow-up question...
> >
> >I am running into some issues / inconsistencies running this
> >transformation on command line vs. within java vs. which platform I
> >run it on.  I'm hoping the list might have some pointers on how to
> >resolve this.
> >
> >Here is the XSLT (slightly modified from what Ken posted):
> >
> ><?xml version="1.0" encoding="UTF-8"?>
> ><xsl:stylesheet version="1.0"
> >         xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> >         xmlns:xalan="http://xml.apache.org/xslt"; >
> >
> >     <!-- The xalan param gets back indentation that seems to be broken
> >in the java api  -->
> >     <xsl:output method="xml" indent="yes" encoding="UTF-8"
> >xalan:indent-amount="4"/>
> >     <xsl:strip-space elements="*" />
> >
> >         <xsl:template match="/">
> >                 <xsl:apply-templates />
> >         </xsl:template>
> >
> >         <xsl:template match="@*|node()">
> >                 <xsl:copy>
> >                         <xsl:apply-templates select="@*|node()">
> >                                 <xsl:sort select="@typeName"/>
> >                                 <xsl:sort select="name(.)"/>
> >                                 <xsl:sort />
> >                         </xsl:apply-templates>
> >                 </xsl:copy>
> >         </xsl:template>
> >
> ></xsl:stylesheet>
> >
> >When I run this on Ubuntu Linux 7.10 (fully updated) using xsltproc, I
> >encounter this bug:
> >
> >https://bugs.launchpad.net/ubuntu/+source/libxml2/+bug/147144
> >
> >Namely, it reports the error:
> >
> >runtime error: file SortCollections.xsl line 40 element copy
> >Attribute nodes must be added before any child nodes to an element.
> >
> >When I run this on Mac OS X 1.5 (Leopard -- fully updated) using
> >xsltproc, it does exactly what I want with no problems.
> >
> >When I run this script from Java 1.6  (using JAXB) with the code
> >below, the identity transform does not copy all the attributes over.
> >I end up with missing attributes, and I have no idea why.
> >
> >This behavior with Java is seen on both Windows XP platform and Ubuntu
> >Linux.  We want to call the script from java -- since it is being used
> >with JAXB to serialize/de-serialize a collection, and then we use the
> >XSLT to sort it and do an XML-diff in unit tests to detect changes.
> >Does anyone have any workaround or solution to getting a consistent
> >solution ??  Thanks in advance!  I have also posted below a sample XML
> >input file that causes this behavior.
> >
> >--JAVA SNIPPET--
> >
> >import javax.xml.bind.Marshaller;
> >import javax.xml.bind.JAXBSource;
> >import javax.xml.bind.JAXBContext;
> >import javax.xml.transform.Transformer;
> >import javax.xml.transform.stream.StreamResult;
> >import javax.xml.transform.stream.StreamSource;
> >
> >Object object; // the object to be marshalled to XML
> >OutputStream output; // the output stream
> >
> >final Marshaller marshaller = getContext().createMarshaller();
> >marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
> >final JAXBSource source = new JAXBSource(marshaller, object);
> >final StreamResult result = new StreamResult(output);
> >// run XSLT script
> >final StreamSource stylesource = new
> >StreamSource(XmlReaderWriter.class.getResourceAsStream(XSLT));
> >final Transformer transformer =
> >TransformFactory.newInstance().newTransformer(stylesource);
> >transformer.transform(source, result);
> >
> >--END JAVA SNIPPET--
> >
> ><?xml version="1.0" encoding="UTF-8"?>
> ><DictionaryModel>
> >     <DictionaryModelDescriptor about="modelName1/modelVersion1">
> >         <modelName>modelName1</modelName>
> >         <modelVersion>modelVersion1</modelVersion>
> >     </DictionaryModelDescriptor>
> >     <DictionaryParts>
> >         <DictionaryPart abstract="false" typeName="part.full1">
> >             <children/>
> >             <parents/>
> >             <DictionaryProperties/>
> >             <feature>feature.empty3</feature>
> >             <maxCardinality>2</maxCardinality>
> >             <minCardinality>1</minCardinality>
> >             <parentComposition>feature.empty2</parentComposition>
> >             <role>role</role>
> >             <sequence>1</sequence>
> >         </DictionaryPart>
> >         <DictionaryPart abstract="false" typeName="part.full5">
> >             <children/>
> >             <parents/>
> >             <DictionaryProperties/>
> >             <feature>feature.empty13</feature>
> >             <maxCardinality>2</maxCardinality>
> >             <minCardinality>1</minCardinality>
> >             <parentComposition>feature.empty12</parentComposition>
> >             <role>role</role>
> >             <sequence>1</sequence>
> >         </DictionaryPart>
> >     </DictionaryParts>
> >     <DictionaryAssociations>
> >         <DictionaryAssociation abstract="false"
> > typeName="association.empty1">
> >             <children/>
> >             <parents/>
> >             <DictionaryProperties/>
> >         </DictionaryAssociation>
> >         <DictionaryAssociation
> >compositionType="BIDIRECTIONAL_ASSOCIATION" abstract="false"
> >typeName="association.full2">
> >             <children/>
> >             <parents/>
> >             <DictionaryProperties>
> >
> ><DictionaryProperty>simple.property.empty4</DictionaryProperty>
> >
> ><DictionaryProperty>composite.property.empty4</DictionaryProperty>
> >             </DictionaryProperties>
> >             <sourcePart>part.full2</sourcePart>
> >             <targetPart>part.full3</targetPart>
> >             <resolverStrategy>resolver.strategy</resolverStrategy>
> >         </DictionaryAssociation>
> >     </DictionaryAssociations>
> >     <DictionaryFeatures>
> >         <DictionaryFeature composite="false" abstract="false"
> >typeName="feature.empty1">
> >             <children/>
> >             <parents/>
> >             <DictionaryProperties/>
> >             <associations/>
> >             <parentComposites/>
> >             <parts/>
> >         </DictionaryFeature>
> >         <DictionaryFeature composite="true" compositionType="SEQUENCE"
> >abstract="true" typeName="feature.full8">
> >             <children>
> >                 <child>feature.empty9</child>
> >             </children>
> >             <parents/>
> >             <DictionaryProperties>
> >
> ><DictionaryProperty>composite.property.empty5</DictionaryProperty>
> >
> ><DictionaryProperty>simple.property.empty5</DictionaryProperty>
> >             </DictionaryProperties>
> >             <associations>
> >                 <association>association.empty3</association>
> >                 <association>association.empty4</association>
> >             </associations>
> >             <parentComposites>
> >                 <parentComposite>feature.empty10</parentComposite>
> >             </parentComposites>
> >             <parts>
> >                 <part>part.empty4</part>
> >             </parts>
> >             <code>code</code>
> >         </DictionaryFeature>
> >     </DictionaryFeatures>
> >     <DictionaryPropertyNodes>
> >         <DictionaryPropertyNode abstract="false"
> >typeName="property.node.empty1">
> >             <children/>
> >             <parents/>
> >             <DictionaryProperties/>
> >         </DictionaryPropertyNode>
> >         <DictionaryPropertyNode abstract="false"
> > typeName="property.node.full3">
> >             <children>
> >                 <child>property.node.empty4</child>
> >             </children>
> >             <parents>
> >                 <parent>property.node.empty5</parent>
> >             </parents>
> >             <DictionaryProperties>
> >
> ><DictionaryProperty>composite.property.empty11</DictionaryProperty>
> >
> ><DictionaryProperty>simple.property.empty8</DictionaryProperty>
> >             </DictionaryProperties>
> >         </DictionaryPropertyNode>
> >     </DictionaryPropertyNodes>
> >     <DictionaryProperties>
> >         <DictionaryProperty
> >xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> >xsi:type="CompositeDictionaryProperty" propertyType="COMPOSITE_ROOT"
> >inherited="false" typeName="composite.property.empty1">
> >             <maxCardinality>2147483647</maxCardinality>
> >             <minCardinality>-2147483648</minCardinality>
> >             <children/>
> >         </DictionaryProperty>
> >         <DictionaryProperty
> >xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> >xsi:type="CompositeDictionaryProperty" propertyType="COMPOSITE_ROOT"
> >inherited="false" typeName="composite.property.empty2">
> >             <maxCardinality>2147483647</maxCardinality>
> >             <minCardinality>-2147483648</minCardinality>
> >             <children/>
> >         </DictionaryProperty>
> >         <DictionaryProperty
> >xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> >xsi:type="CompositeDictionaryProperty" propertyType="COMPOSITE_ROOT"
> >inherited="false" typeName="composite.property.empty3">
> >             <maxCardinality>2147483647</maxCardinality>
> >             <minCardinality>-2147483648</minCardinality>
> >             <children/>
> >         </DictionaryProperty>
> >         <DictionaryProperty
> >xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> >xsi:type="CompositeDictionaryProperty" propertyType="COMPOSITE_CHILD"
> >inherited="true" typeName="composite.property.full6">
> >             <code>code</code>
> >             <maxCardinality>3</maxCardinality>
> >             <minCardinality>2</minCardinality>
> >             <parentObject>feature.empty14</parentObject>
> >             <parentProperty>composite.property.empty8</parentProperty>
> >             <rootProperty>composite.property.empty7</rootProperty>
> >             <children>
> >                 <child>simple.property.empty6</child>
> >             </children>
> >             <propertyNode>property.node.empty2</propertyNode>
> >         </DictionaryProperty>
> >         <DictionaryProperty
> >xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> >xsi:type="SimpleDictionaryProperty" propertyType="SIMPLE_ROOT"
> >inherited="false" typeName="simple.property.empty1">
> >             <maxCardinality>2147483647</maxCardinality>
> >             <minCardinality>-2147483648</minCardinality>
> >         </DictionaryProperty>
> >         <DictionaryProperty
> >xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> >xsi:type="SimpleDictionaryProperty" propertyType="SIMPLE_ROOT"
> >inherited="false" typeName="simple.property.empty2">
> >             <maxCardinality>2147483647</maxCardinality>
> >             <minCardinality>-2147483648</minCardinality>
> >         </DictionaryProperty>
> >         <DictionaryProperty
> >xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> >xsi:type="SimpleDictionaryProperty" propertyType="SIMPLE_ROOT"
> >inherited="false" typeName="simple.property.empty3">
> >             <maxCardinality>2147483647</maxCardinality>
> >             <minCardinality>-2147483648</minCardinality>
> >         </DictionaryProperty>
> >         <DictionaryProperty
> >xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> >xsi:type="SimpleDictionaryProperty" propertyType="SIMPLE_CHILD"
> >inherited="true" typeName="simple.property.full7">
> >             <code>code</code>
> >             <maxCardinality>2</maxCardinality>
> >             <minCardinality>1</minCardinality>
> >             <parentObject>feature.empty16</parentObject>
> >             <parentProperty>composite.property.empty9</parentProperty>
> >             <rootProperty>composite.property.empty10</rootProperty>
> >             <defaultValue>default-value</defaultValue>
> >             <dictionaryFeatureRange>feature.range2</dictionaryFeatureRange>
> >             <referentFeature>feature.empty17</referentFeature>
> >             <dictionaryValueRange>value.range1</dictionaryValueRange>
> >             <valueTypeName>value-type-name</valueTypeName>
> >         </DictionaryProperty>
> >     </DictionaryProperties>
> >     <DictionaryFeatureRanges>
> >         <DictionaryFeatureRange typeName="feature.range1">
> >             <DictionaryFeatures>
> >                 <DictionaryFeature>feature.empty11</DictionaryFeature>
> >             </DictionaryFeatures>
> >         </DictionaryFeatureRange>
> >     </DictionaryFeatureRanges>
> >     <DictionaryValueRanges>
> >         <DictionaryValueRange typeName="value.range2">
> >             <DictionaryRangeItems>
> >                 <DictionaryRangeItem>range.item3</DictionaryRangeItem>
> >             </DictionaryRangeItems>
> >             <valueTypeName>value-type-name</valueTypeName>
> >         </DictionaryValueRange>
> >     </DictionaryValueRanges>
> >     <DictionaryRangeItems>
> >         <DictionaryRangeItem typeName="range.item2">
> >             <value>4</value>
> >         </DictionaryRangeItem>
> >     </DictionaryRangeItems>
> >     <DictionaryValueTypeNames>
> >         <DictionaryValueTypeName>a value type name</DictionaryValueTypeName>
> >         <DictionaryValueTypeName>value-type-name</DictionaryValueTypeName>
> >     </DictionaryValueTypeNames>
> ></DictionaryModel>
> >
> >On Nov 28, 2007 5:46 PM, G. Ken Holman <gkholman@xxxxxxxxxxxxxxxxxxxx> wrote:
> > > At 2007-11-28 17:04 -0500, Davis Ford wrote:
> > > >Hi, consider the following example:
> > > >...
> > > >I want to sort it as such
> > > >...
> > > >I am trying to come up with a generic XSLT solution that does not use
> > > >explicit element names, but only uses the sort select="name()", and it
> > > >should be recursive such that if say, element <A1> contained further
> > > >elements, then they would also be sorted by element name.
> > > >
> > > >Finally, if the element names are the same, then it should sort them
> > > >by an attribute called "typeName".
> > > >
> > > >Can anyone provide some help?  Thank you in advance!
> > >
> > > Am I missing something?  This is a variant of a one-template identity
> > > transform.
> > >
> > > I hope the example below helps.
> > >
> > > . . . . . . . . . . Ken
> > >
> > > t:\ftemp>type davis.xml
> > > <Collection>
> > >    <CollectionB>
> > >       <B2></B2>
> > >       <A2></A2>
> > >       <A1></A1>
> > >       <B1 typeName="2"></B1>
> > >       <B1 typeName="1"></B1>
> > >    </CollectionB>
> > >    <CollectionA>
> > >       <B2></B2>
> > >       <A2></A2>
> > >       <A1></A1>
> > >       <B1></B1>
> > >    </CollectionA>
> > > </Collection>
> > >
> > > t:\ftemp>type davis.xsl
> > > <?xml version="1.0" encoding="US-ASCII"?>
> > > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> > >                  version="1.0">
> > >
> > > <xsl:output indent="yes"/>
> > > <xsl:strip-space elements="*"/>
> > >
> > > <xsl:template match="@*|node()">
> > >    <xsl:copy>
> > >      <xsl:apply-templates select="@*|node()">
> > >        <xsl:sort select="name(.)"/>
> > >        <xsl:sort select="@typeName"/>
> > >      </xsl:apply-templates>
> > >    </xsl:copy>
> > > </xsl:template>
> > >
> > > </xsl:stylesheet>
> > > t:\ftemp>xslt davis.xml davis.xsl con
> > > <?xml version="1.0" encoding="utf-8"?>
> > > <Collection>
> > >     <CollectionA>
> > >        <A1/>
> > >        <A2/>
> > >        <B1/>
> > >        <B2/>
> > >     </CollectionA>
> > >     <CollectionB>
> > >        <A1/>
> > >        <A2/>
> > >        <B1 typeName="1"/>
> > >        <B1 typeName="2"/>
> > >        <B2/>
> > >     </CollectionB>
> > > </Collection>
> > > t:\ftemp>
> > >
> > >
> > >
> > >
> > > --
> > > Comprehensive in-depth XSLT2/XSL-FO1.1 classes: Austin TX,Jan-2008
> > > World-wide corporate, govt. & user group XML, XSL and UBL training
> > > RSS feeds:     publicly-available developer resources and training
> > > G. Ken Holman                 mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
> > > Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
> > > Box 266, Kars, Ontario CANADA K0A-2E0    +1(613)489-0999 (F:-0995)
> > > Male Cancer Awareness Nov'07  http://www.CraneSoftwrights.com/s/bc
> > > Legal business disclaimers:  http://www.CraneSoftwrights.com/legal
>
>
> ======================================================================
> Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
> Mulberry Technologies, Inc.                http://www.mulberrytech.com
> 17 West Jefferson Street                    Direct Phone: 301/315-9635
> Suite 207                                          Phone: 301/315-9631
> Rockville, MD  20850                                 Fax: 301/315-8285
> ----------------------------------------------------------------------
>    Mulberry Technologies: A Consultancy Specializing in SGML and XML
> ======================================================================
>
>



-- 
Zeno Consulting, Inc.
http://www.zenoconsulting.biz
248.894.4922 phone
313.884.2977 fax

Current Thread