Search code examples
xslt-1.0xslt-grouping

Sorting Specific node in nested XML


I am trying to sort specific nodes in a nested XML. I can sort them fine but the output does not contain the other XML fields that are supposed to be copied.

Input:

<!-- language: lang-xml -->
<PerPerson>
  <PerPerson>
    <personalInfoNav>
      <PerPersonal>
        <lastName></lastName>
        <firstName></firstName>
        <personIdExternal></personIdExternal>
        <startDate></startDate>
      </PerPersonal>
    </personalInfoNav>
    <personIdExternal></personIdExternal>
    <employmentNav>
      <EmpEmployment>
        <personIdExternal></personIdExternal>
        <assignmentClass></assignmentClass>
        <compInfoNav/>
        <jobInfoNav>
          <EmpJob>
            <employeeClass></employeeClass>
            <seqNumber>2</seqNumber>
            <startDate>2020-06-01T00:00:00.000</startDate>
          </EmpJob>
          <EmpJob>
            <employeeClass></employeeClass>
            <seqNumber>3</seqNumber>
            <startDate>2020-01-01T00:00:00.000</startDate>
          </EmpJob>
          <EmpJob>
            <seqNumber>1</seqNumber>
            <startDate>2019-06-01T00:00:00.000</startDate>
          </EmpJob>
        </jobInfoNav>
        <userId></userId>
      </EmpEmployment>
    </employmentNav>
  </PerPerson>
</PerPerson>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="PerPerson/PerPerson">
        <xsl:apply-templates select="employmentNav/EmpEmployment/jobInfoNav/EmpJob">
            <xsl:sort select="startDate" order="descending"/>
            <xsl:sort select="seqNumber" order="descending"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

How can I make sure that everything else is copied?


Solution

  • I think you want to do:

    <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="jobInfoNav">
        <xsl:apply-templates select="EmpJob">
            <xsl:sort select="startDate" order="descending"/>
            <xsl:sort select="seqNumber" order="descending"/>
        </xsl:apply-templates>
    </xsl:template>
    
    </xsl:stylesheet>
    

    For explanation, see: https://www.w3.org/TR/1999/REC-xslt-19991116/#section-Processing-Model