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