XML sorting

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • pisicuta
    New Member
    • Oct 2009
    • 8

    XML sorting

    People must get sick of answering questions on sorting, but I haven't found an example on the web that matches my situation (Maybe I am asking the wrong question). My XML file has this sort of structure
    Code:
    <?xml version="1.0"?>
    <Building>
    	<Block>
    		<Id>Ba2150</Id>
    		<Elevation>140</Elevation>
    		<Piece>
    			<Description>Rustic</Description>
    			<Elevation>180</Elevation>
    			<Qty>1</Qty>
    		</Piece>
    		<Piece>
    			<Description>Rustic</Description>
    			<Elevation>1870</Elevation>
    			<Qty>1</Qty>
    		</Piece>
    		<Piece>
    			<Description>Red</Description>
    			<Elevation>500</Elevation>
    			<Qty>1</Qty>
    		</Piece>
    		<Piece>
    			<Description>Blue</Description>
    			<Elevation>1430</Elevation>
    			<Qty>1</Qty>
    		</Piece>
    		<Piece>
    			<Description>Side</Description>
    			<Elevation>140</Elevation>
    			<Qty>2</Qty>
    		</Piece>
    		<Piece>
    			<Description>Bottom</Description>
    			<Elevation>140</Elevation>
    			<Qty>1</Qty>
    		</Piece>
    		<Piece>
    			<Description>Back</Description>
    			<Elevation>140</Elevation>
    			<Qty>1</Qty>
    		</Piece>
    		<Piece>
    			<Description>Top</Description>
    			<Elevation>2190</Elevation>
    			<Qty>1</Qty>
    		</Piece>
    	</Block>
    </Building>
    All I want to do is sort the pieces within the blocks and output the whole lot. I can sort the blocks, I can sort the pieces and lose the blocks and I can sort the pieces and keep the block tags, but not the block data. My current xsl is

    Code:
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes"/>
    
     <xsl:template match="Building">
     <xsl:copy>
          <xsl:apply-templates select="Block">
    	<xsl:sort select="Elevation" data-type="number"/> <!-- not really necessary, already sorted -->
         </xsl:apply-templates>
    </xsl:copy>
    </xsl:template>
    
      <xsl:template match="Block">
        <xsl:copy>
    	<xsl:apply-templates select="Piece">
    		<xsl:sort select="Elevation" data-type="number"/>
    	</xsl:apply-templates>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    Any help would be greatly appreciated
    Last edited by Dormilich; Feb 19 '10, 05:15 AM. Reason: Please use [code] tags when posting code
  • Dormilich
    Recognized Expert Expert
    • Aug 2008
    • 8694

    #2
    just for a better understanding, what shall it look like afterwards?

    Comment

    • pisicuta
      New Member
      • Oct 2009
      • 8

      #3
      Sorry, I didn't it clear what the output should be. The output should look like this, so the Piece elements are in ascending elevation order:

      Code:
      <?xml version="1.0"?>
      <Building>
      	<Block>
      		<Id>Ba2150</Id>
      		<Elevation>140</Elevation>
      		<Piece>
      			<Description>Side</Description>
      			<Elevation>140</Elevation>
      			<Qty>2</Qty>
      		</Piece>
      		<Piece>
      			<Description>Bottom</Description>
      			<Elevation>140</Elevation>
      			<Qty>1</Qty>
      		</Piece>
      		<Piece>
      			<Description>Back</Description>
      			<Elevation>140</Elevation>
      			<Qty>1</Qty>
      		</Piece>
      		<Piece>
      			<Description>Rustic</Description>
      			<Elevation>180</Elevation>
      			<Qty>1</Qty>
      		</Piece>
      		<Piece>
      			<Description>Red</Description>
      			<Elevation>500</Elevation>
      			<Qty>1</Qty>
      		</Piece>
      		<Piece>
      			<Description>Blue</Description>
      			<Elevation>1430</Elevation>
      			<Qty>1</Qty>
      		</Piece>		
      		<Piece>
      			<Description>Rustic</Description>
      			<Elevation>1870</Elevation>
      			<Qty>1</Qty>
      		</Piece>
      		<Piece>
      			<Description>Top</Description>
      			<Elevation>2190</Elevation>
      			<Qty>1</Qty>
      		</Piece>
      	</Block>
      </Building>
      Last edited by Dormilich; Feb 19 '10, 08:02 AM. Reason: Please use [code] tags when posting code

      Comment

      • Dormilich
        Recognized Expert Expert
        • Aug 2008
        • 8694

        #4
        maybe Munchian sorting can help.

        Comment

        • pisicuta
          New Member
          • Oct 2009
          • 8

          #5
          Spent all day with Munchian sorting and am no further forward. In fact I've probably got a bigger headache. I just can't get any elements copied from the <Piece>..</Piece> nodes and have the Block details as well. I end up with:

          Code:
          <Building>
          	<Block>
          		<Id>Ba2150</Id>
          		<Elevation>140</Elevation>
                          <Piece />
          		<Piece />
                          <Piece />
          		<Piece />
                          <Piece />
          		<Piece />
                          <Piece />
          		<Piece />
          	<Block>
          <Building>
          Last edited by Dormilich; Feb 19 '10, 10:49 PM. Reason: Please use [code] tags when posting code

          Comment

          • Dormilich
            Recognized Expert Expert
            • Aug 2008
            • 8694

            #6
            I wish jkmyoung were here, he’s the sort & copy expert …

            I’ll try if I can shed some light on it, but it will take some time.

            Comment

            • pisicuta
              New Member
              • Oct 2009
              • 8

              #7
              Solution

              I managed to get the answer from somewhere else. For all those interested, here it is.

              Code:
              <xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
                <xsl:template match="Building">
                  <xsl:copy>
                    <xsl:copy-of select="@*" /> <!-- copy attributes-->
                    <xsl:apply-templates />
                  </xsl:copy>
                </xsl:template>
                
                <xsl:template match="Block">
                  <xsl:copy>
                    <xsl:copy-of select="@*" /> <!-- copy attributes-->
                    <xsl:copy-of select="*[local-name()!='Piece']" />
                    <xsl:for-each select="Piece">
                      <!-- [url]http://www.w3.org/TR/xslt#sorting[/url] -->
                      <xsl:sort select="Elevation" data-type="number" order="ascending" />
                      <xsl:copy-of select="." />
                    </xsl:for-each>
                  </xsl:copy>
                </xsl:template>
                
                  <xsl:template match="Panel">
                      <xsl:copy-of select="." />
                </xsl:template>
              </xsl:stylesheet>
              Last edited by Dormilich; Feb 23 '10, 06:29 AM. Reason: Please use [code] tags when posting code

              Comment

              Working...