didierCH
didierCH

Reputation: 428

How to re-order a xml-file with xslt while keeping structure

I know it is a basic problem but I'm very new to XSL and I don't get it to work. I have a XML-File with a given structure and I want to rearrange the XML in alphabetical order based on one node while keeping the structure. I need that XSLT-Stylesheet to reorder a XML when importing it in Adobe InDesign.

My File:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Employee>
        <First_Name>Andrew</First_Name>
        <Last_Name>Miller</Last_Name>
        <Salary>100000</Salary>
        <Performance>8</Performance>
    </Employee>
    <Employee>
        <First_Name>Betsy</First_Name>
        <Last_Name>Clarke</Last_Name>
        <Salary>105000</Salary>
        <Performance>10</Performance>
    </Employee>
    <Employee>
        <First_Name>Donald</First_Name>
        <Last_Name>Abernathey</Last_Name>
        <Salary>95000</Salary>
        <Performance>7</Performance>
    </Employee>
</Root>

I want to rearange the document in the way that it is sorted alphabetically based on the tag <Last_name>. My desired output is:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Employee>
        <First_Name>Donald</First_Name>
        <Last_Name>Abernathey</Last_Name>
        <Salary>95000</Salary>
        <Performance>7</Performance>
    </Employee>
    <Employee>
        <First_Name>Betsy</First_Name>
        <Last_Name>Clarke</Last_Name>
        <Salary>105000</Salary>
        <Performance>10</Performance>
    </Employee>
    <Employee>
        <First_Name>Andrew</First_Name>
        <Last_Name>Miller</Last_Name>
        <Salary>100000</Salary>
        <Performance>8</Performance>
    </Employee>
</Root>

I found some solutions to re-arange my output but it's always in respect to output HTML and not XML.

Update: As requested here is my atempt to solve the problem. I stuck because it copyies now all in one tag <Employee>.

<?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" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
  <Root>
  <Employee>
      <xsl:for-each select="Root/Employee">
      <xsl:sort select="Last_Name"/>
        <First_Name><xsl:value-of select="First_Name"/></First_Name>
        <Last_Name><xsl:value-of select="Last_Name"/></Last_Name>
        <Salary><xsl:value-of select="Salary"/></Salary>
        <Performance><xsl:value-of select="Performance"/></Performance>
      </xsl:for-each>
  </Employee>
  </Root>
</xsl:template>

</xsl:stylesheet>

Upvotes: 1

Views: 976

Answers (3)

michael.hor257k
michael.hor257k

Reputation: 116992

Or simply:

<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="Employee">
            <xsl:sort select="Last_Name"/>
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Upvotes: 3

Martin Honnen
Martin Honnen

Reputation: 167516

If you transform XML to XML where you want to preserve some or even most of the content I would suggest to start with the identity transformation template and then add the templates that are necessary to perform the change you want to make, e.g. in your case to sort:

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

  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="Root">
    <xsl:copy>
        <xsl:apply-templates>
            <xsl:sort select="Last_Name"/>
        </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/6rexjig

Upvotes: 2

malarres
malarres

Reputation: 2946

You were really close to the solution:

<?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" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
  <Root>
      <xsl:for-each select="Root/Employee">

      <xsl:sort select="Last_Name"/>
      <Employee>
        <First_Name><xsl:value-of select="First_Name"/></First_Name>
        <Last_Name><xsl:value-of select="Last_Name"/></Last_Name>
        <Salary><xsl:value-of select="Salary"/></Salary>
        <Performance><xsl:value-of select="Performance"/></Performance>
       </Employee>
      </xsl:for-each>
  </Root>
</xsl:template>

</xsl:stylesheet>

Upvotes: 1

Related Questions