Search code examples
xmlxsltxml-spreadsheet

Sorting cells as per ss:Index


Server generated XML-spreadsheet has random sequence of <Cell>s in each <Row>. Which is required to be sorted.

I want to go with XSLT implementation for sorting <Cell>s in each <Row> based on ss:Index. I tried but failed to get sorted result.(XSLT code is given below)

XML-Spreadsheet

<?xml version="1.0" encoding="UTF-8" standalone="no"?><?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" 
    xmlns:html="http://www.w3.org/TR/REC-html40" 
    xmlns:o="urn:schemas-microsoft-com:office:office" 
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
    xmlns:x="urn:schemas-microsoft-com:office:excel">
    <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
        <Version>16.00</Version>
    </DocumentProperties>
    <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
        <AllowPNG/>
    </OfficeDocumentSettings>
    <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
        <WindowHeight>10185</WindowHeight>
        <WindowWidth>20610</WindowWidth>
        <WindowTopX>0</WindowTopX>
        <WindowTopY>0</WindowTopY>
        <RefModeR1C1/>
        <ProtectStructure>False</ProtectStructure>
        <ProtectWindows>False</ProtectWindows>
    </ExcelWorkbook>
    <Styles>
        <Style ss:ID="Default" ss:Name="Normal">
            <Alignment ss:Vertical="Bottom"/>
            <Borders/>
            <Font ss:Color="#000000" ss:FontName="Calibri" ss:Size="11" x:Family="Swiss"/>
            <Interior/>
            <NumberFormat/>
            <Protection/>
        </Style>
        <Style ss:ID="header">
            <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
            <Borders>
                <Border ss:Color="#000000" ss:LineStyle="Continuous" ss:Position="Left" ss:Weight="1"/>
                <Border ss:Color="#000000" ss:LineStyle="Continuous" ss:Position="Right" ss:Weight="1"/>
                <Border ss:Color="#000000" ss:LineStyle="Continuous" ss:Position="Top" ss:Weight="1"/>
            </Borders>
            <Font ss:Bold="1" ss:Color="#000000" ss:FontName="Arial" ss:Size="11" x:Family="Swiss"/>
            <Interior ss:Color="#E2EFDA" ss:Pattern="Solid"/>
        </Style>
        <Style ss:ID="record">
            <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
            <Borders>
                <Border ss:Color="#000000" ss:LineStyle="Continuous" ss:Position="Bottom" ss:Weight="1"/>
                <Border ss:Color="#000000" ss:LineStyle="Continuous" ss:Position="Left" ss:Weight="1"/>
                <Border ss:Color="#000000" ss:LineStyle="Continuous" ss:Position="Right" ss:Weight="1"/>
                <Border ss:Color="#000000" ss:LineStyle="Continuous" ss:Position="Top" ss:Weight="1"/>
            </Borders>
            <Font ss:Color="#000000" ss:FontName="Arial" ss:Size="11" x:Family="Swiss"/>
        </Style>
    </Styles>
    <Worksheet ss:Name="Report">
        <Names>
            <NamedRange ss:Hidden="1" ss:Name="_FilterDatabase" ss:RefersTo="=Report!R1C1:R1C19"/>
        </Names>
        <Table>
            <Column ss:AutoFitWidth="0" ss:Width="87"/>
            <Column ss:AutoFitWidth="0" ss:Width="135"/>
            <Column ss:AutoFitWidth="0" ss:Width="249.75"/>
            <Column ss:AutoFitWidth="0" ss:Width="97.5"/>
            <Column ss:AutoFitWidth="0" ss:Width="97.5"/>
            <Column ss:AutoFitWidth="0" ss:Span="1" ss:Width="97.5"/>
            <Column ss:AutoFitWidth="0" ss:Index="8" ss:Width="105.75"/>
            <Column ss:AutoFitWidth="0" ss:Width="90"/>
            <Column ss:AutoFitWidth="0" ss:Span="9" ss:Width="97.5"/>
            <Row ss:AutoFitHeight="0" ss:Height="31.5">
                <Cell ss:Index="8" ss:StyleID="header">
                    <Data ss:Type="String">c8</Data>
                </Cell>
                <Cell ss:Index="9" ss:StyleID="header">
                    <Data ss:Type="String">c9</Data>
                </Cell>
                <Cell ss:Index="10" ss:StyleID="header">
                    <Data ss:Type="String">c10</Data>
                </Cell>
                <Cell ss:Index="11" ss:StyleID="header">
                    <Data ss:Type="String">c11</Data>
                </Cell>
                <Cell ss:Index="7" ss:StyleID="header">
                    <Data ss:Type="String">c7</Data>
                </Cell>
                <Cell ss:Index="12" ss:StyleID="header">
                    <Data ss:Type="String">c12</Data>
                </Cell>
                <Cell ss:Index="13" ss:StyleID="header">
                    <Data ss:Type="String">c13</Data>
                </Cell>
                <Cell ss:Index="14" ss:StyleID="header">
                    <Data ss:Type="String">c14</Data>
                </Cell>
                <Cell ss:Index="15" ss:StyleID="header">
                    <Data ss:Type="String">c15</Data>
                </Cell>
                <Cell ss:Index="16" ss:StyleID="header">
                    <Data ss:Type="String">c16</Data>
                </Cell>
                <Cell ss:Index="1" ss:StyleID="header">
                    <Data ss:Type="String">c1</Data>
                </Cell>
                <Cell ss:Index="2" ss:StyleID="header">
                    <Data ss:Type="String">c2</Data>
                </Cell>
                <Cell ss:Index="3" ss:StyleID="header">
                    <Data ss:Type="String">c3</Data>
                </Cell>
                <Cell ss:Index="4" ss:StyleID="header">
                    <Data ss:Type="String">c4</Data>
                </Cell>
                <Cell ss:Index="5" ss:StyleID="header">
                    <Data ss:Type="String">c5</Data>
                </Cell>
                <Cell ss:Index="6" ss:StyleID="header">
                    <Data ss:Type="String">c6</Data>
                </Cell>
                <Cell ss:Index="17" ss:StyleID="header">
                    <Data ss:Type="String">c17</Data>
                </Cell>
                <Cell ss:Index="18" ss:StyleID="header">
                    <Data ss:Type="String">c18</Data>
                </Cell>
                <Cell ss:Index="19" ss:StyleID="header">
                    <Data ss:Type="String">c19</Data>
                </Cell>
            </Row>          
        </Table>
        <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
            <Unsynced/>
            <Print>
                <ValidPrinterInfo/>
                <PaperSizeIndex>9</PaperSizeIndex>
                <HorizontalResolution>600</HorizontalResolution>
                <VerticalResolution>600</VerticalResolution>
            </Print>
        </WorksheetOptions>
        <AutoFilter xmlns="urn:schemas-microsoft-com:office:excel" x:Range="R1C1:R1C19">
        </AutoFilter>
    </Worksheet>
</Workbook>

XLST

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">

  <xsl:output method="xml" encoding="utf-8" indent="yes"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Row">
    <xsl:copy>
      <xsl:apply-templates select="*">
        <xsl:sort select="@ss:Index" order="ascending" data-type="number"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Solution

  •  <xsl:template match="Row">
    

    does not match anything in your input XML, because your input XML has a default namespace:

    <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" 
    

    You have already declared this namespace in your stylesheet and assigned it a prefix - now all you have to do is use it:

    <xsl:template match="ss:Row">