tags:

views:

48

answers:

1

I have an XML file that I want to sort by an attribute. The file is structured as shown below:

<wb xmlns:cf="http://www.macromedia.com/2004/cfform"&gt;

    <a:form name="chart">  

        <a:input FIELDNUMBER="09" INDEX="2" LEFT="200" />
        <a:input FIELDNUMBER="08" INDEX="3" LEFT="200" />

        <a:fieldset FIELD="a" FIELDNAME="FieldSet1">                              
            <a:input FIELDNUMBER="02" INDEX="4" LEFT="200" />
            <a:select1  FIELDNUMBER="01" />
        </a:fieldset>

        <a:fieldset FIELD="b" FIELDNAME="FieldSet1">                              
            <a:input FIELDNUMBER="04" INDEX="7" LEFT="200" />
            <a:select1  FIELDNUMBER="03" />
            <a:fieldset FIELD="c" FIELDNAME="FieldSet1">                              
                <a:input FIELDNUMBER="06" INDEX="8" LEFT="200" />
                <a:input FIELDNUMBER="05" INDEX="6" LEFT="200" />
            </a:fieldset>
       </a:fieldset>

    </a:form>

</wb> 

I would like to sort the above XML all throughout by @fieldnumber, but at the same I want to keep the same structure of the XML. I have managed to sort other XML file but they did not have such nesting levels. Is this possible with XSL alone and if so how can this be done?

The output should be as follows:

<wb xmlns:cf="http://www.macromedia.com/2004/cfform"&gt;

    <a:form name="chart">  

        <a:input FIELDNUMBER="08" INDEX="3" LEFT="200" />
        <a:input FIELDNUMBER="09" INDEX="2" LEFT="200" />

        <a:fieldset FIELD="a" FIELDNAME="FieldSet1">                              
            <a:select1  FIELDNUMBER="01" />
            <a:input FIELDNUMBER="02" INDEX="4" LEFT="200" />
        </a:fieldset>

        <a:fieldset FIELD="b" FIELDNAME="FieldSet1">                              
            <a:select1  FIELDNUMBER="03" />
            <a:input FIELDNUMBER="04" INDEX="7" LEFT="200" />
            <a:fieldset FIELD="c" FIELDNAME="FieldSet1">                              
                <a:input FIELDNUMBER="05" INDEX="6" LEFT="200" />
                <a:input FIELDNUMBER="06" INDEX="8" LEFT="200" />
            </a:fieldset>
       </a:fieldset>

    </a:form>

</wb> 

As another example, should the FIELDNUMBER 04 be changed to a value greater than 7 such as 10 (let's assume 10 in this example) then the output of the fieldset with FIELD value b becomes:

        <a:fieldset FIELD="b" FIELDNAME="FieldSet1">                              
            <a:select1  FIELDNUMBER="03" />
            <a:fieldset FIELD="c" FIELDNAME="FieldSet1">                              
                <a:input FIELDNUMBER="05" INDEX="6" LEFT="200" />
                <a:input FIELDNUMBER="06" INDEX="8" LEFT="200" />
            </a:fieldset>
            <a:input FIELDNUMBER="10" INDEX="7" LEFT="200" />
       </a:fieldset>
+2  A: 

Despite the inconsistency pointed to by Jim Garrison, I tried to come up with something that matches your description:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:output indent="yes"/>
  <xsl:template match="*">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:for-each select="*">
        <xsl:sort select="@FIELDNUMBER|.//@FIELDNUMBER"/>
        <xsl:apply-templates select="." />
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

The sort works first on the element's FIELDNUMBER attribute, or on the first FIELDNUMBER attribute it finds on the element's children if the element doesn't have one itself. Here's the output (xmlns:a was added to the source document, so it got carried to the output):

<?xml version="1.0" encoding="utf-8"?>
<wb xmlns:cf="http://www.macromedia.com/2004/cfform" xmlns:a="urn:dummy">
  <a:form name="chart">
    <a:fieldset FIELD="a" FIELDNAME="FieldSet1">
      <a:select1 FIELDNUMBER="01" />
      <a:input FIELDNUMBER="02" INDEX="4" LEFT="200" />
    </a:fieldset>
    <a:fieldset FIELD="b" FIELDNAME="FieldSet1">
      <a:select1 FIELDNUMBER="03" />
      <a:input FIELDNUMBER="04" INDEX="7" LEFT="200" />
      <a:fieldset FIELD="c" FIELDNAME="FieldSet1">
        <a:input FIELDNUMBER="05" INDEX="6" LEFT="200" />
        <a:input FIELDNUMBER="06" INDEX="8" LEFT="200" />
      </a:fieldset>
    </a:fieldset>
    <a:input FIELDNUMBER="08" INDEX="3" LEFT="200" />
    <a:input FIELDNUMBER="09" INDEX="2" LEFT="200" />
  </a:form>
</wb>
Francis Gagné
Francis, that is just excellent! Not only you managed to understand my query but you also managed to give me an output that does exactly what I expected!
@Francis, bravo
infant programmer