Subject: Re: [xsl] recursive sorting by element name From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx> Date: Thu, 29 Nov 2007 12:21:58 -0500 |
<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
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 ======================================================================
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] recursive sorting by elem, Davis Ford | Thread | Re: [xsl] recursive sorting by elem, Davis Ford |
Re: [xsl] sorting (again), Davis Ford | Date | Re: [xsl] Help with staregies for o, James A. Robinson |
Month |