addisu
addisu

Reputation: 634

How can I sort only some children of an element?

I have a scenario where I want to sort only some of the children of an element. Namely, I want to sort the children that have the attribute Sorted="1" according to the field attribute but not those that have Sorted="0".

Input

<?xml version="1.0" encoding="utf-8"?>
<root>
  <Row field="G" Sorted="1" />
  <Row field="A" Sorted="1" />
  <Row field="B" Sorted="0" />
  <Row field="H" Sorted="1" />
  <Row field="D" Sorted="1" />
  <Row field="M" Sorted="0" />
  <Row field="U" Sorted="1" />
  <Row field="W" Sorted="1" />
  <Row field="Z" Sorted="0" />
  <Row field="L" Sorted="1" />
  <Row field="A" Sorted="0" />
  <Row field="W" Sorted="1" />
</root>

Current XSLT

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:for-each select="/Row[@Sorted='1']">
        <xsl:sort select="@field" order="ascending"/>
        <xsl:copy-of select="."/>
      </xsl:for-each>
    </xsl:copy>
    <xsl:copy>
      <xsl:for-each select="/Row[@Sorted='0']">
        <xsl:copy-of select="."/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Desired Output

<?xml version="1.0" encoding="utf-8"?>
<root>
  <Row field="A" Sorted="1" />
  <Row field="D" Sorted="1" />
  <Row field="G" Sorted="1" />
  <Row field="H" Sorted="1" />
  <Row field="L" Sorted="1" />
  <Row field="U" Sorted="1" />
  <Row field="W" Sorted="1" />
  <Row field="W" Sorted="1" />
  <Row field="B" Sorted="0" />
  <Row field="M" Sorted="0" />
  <Row field="Z" Sorted="0" />
  <Row field="A" Sorted="0" />
</root> 

Upvotes: 0

Views: 91

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117102

In response to your updated question:

Sort Rows with Sorted=1 and copy them at the top and Copy the rest Rows with Sorted=0 at the bottom of the xml unsorted

This can be done quite simply as:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

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

<xsl:template match="root">
    <xsl:copy>
        <xsl:apply-templates select="Row[@Sorted='1']">
            <xsl:sort select="@field" data-type="text" order="ascending"/>
        </xsl:apply-templates>
        <xsl:apply-templates select="Row[@Sorted='0']"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Or, if you prefer:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/root">
    <xsl:copy>
        <xsl:for-each select="Row[@Sorted='1']">
            <xsl:sort select="@field" data-type="text" order="ascending"/>
            <xsl:copy-of select="."/>
        </xsl:for-each>
        <xsl:for-each select="Row[@Sorted='0']">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Upvotes: 1

Related Questions