1

I'm trying to sort some XML (using XSLT) based on a few child elements and return the result as XML. I know it's probably not that difficult but this is my first experience using XSLT and it's giving me some troubles. Here's the XML:

<root>
  <subject>
    <courseSubjectHeader>
        <subjectCode>B</subjectCode>
        <subjectName>text</subjectName>
        <unit>text</unit>
        <faculty>text</faculty>
    </courseSubjectHeader>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>B 200</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>B 100</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
  </subject>
  <subject>
    <courseSubjectHeader>
        <subjectCode>C</subjectCode>
        <subjectName>text</subjectName>
        <unit>text</unit>
        <faculty>text</faculty>
    </courseSubjectHeader>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>C 300</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>C 100</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
  </subject>
  <subject>
    <courseSubjectHeader>
        <subjectCode>A</subjectCode>
        <subjectName>text</subjectName>
        <unit>text</unit>
        <faculty>text</faculty>
    </courseSubjectHeader>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>A 300</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>A 200</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
  </subject>
</root>

I'd like to sort the 'subjects' by their 'subjectCode' child element, and all the courses within each subject by their 'subjectAndNumber' child element. So the resulting XML would be...

<root>
  <subject>
    <courseSubjectHeader>
        <subjectCode>A</subjectCode>
        <subjectName>text</subjectName>
        <unit>text</unit>
        <faculty>text</faculty>
    </courseSubjectHeader>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>A 200</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>A 300</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
  </subject>
  <subject>
    <courseSubjectHeader>
        <subjectCode>B</subjectCode>
        <subjectName>text</subjectName>
        <unit>text</unit>
        <faculty>text</faculty>
    </courseSubjectHeader>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>B 100</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>B 200</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
  </subject>
  <subject>
    <courseSubjectHeader>
        <subjectCode>C</subjectCode>
        <subjectName>text</subjectName>
        <unit>text</unit>
        <faculty>text</faculty>
    </courseSubjectHeader>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>C 100</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
    <course>
      <crsLevel>text</crsLevel>
      <subjectAndNumber>C 300</subjectAndNumber>
      <units>3.0</units>
      <hours>3-0</hours>
    </course>
  </subject>
</root>

And finally, here's my (pretty awful) attempt at the XSLT:

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

    <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="/">
        <xsl:copy>
            <xsl:apply-templates select="subject">
                <xsl:sort select="subjectCode"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="subject">
        <xsl:copy>
            <xsl:apply-templates select="course">
                <xsl:sort select="subjectAndNumber"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Any help would be much appreciated, thanks!

1 Answer 1

2

You only have a few minor mistakes - compare:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<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="/*">
    <xsl:copy>
        <xsl:apply-templates select="subject">
            <xsl:sort select="courseSubjectHeader/subjectCode"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="subject">
    <xsl:copy>
        <xsl:copy-of select="courseSubjectHeader"/>
        <xsl:apply-templates select="course">
            <xsl:sort select="subjectAndNumber"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Note: your most serious mistake is this: xmlns:xsl="http://www.w3.org/1999/ /Transform". If you don't declare the XSLT namespace properly, then your document is not a stylesheet at all.

Sign up to request clarification or add additional context in comments.

1 Comment

Ah that's my mistake, I must have added that space while editing it within stack's editor. Thanks a ton, this looks like it's working perfectly!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.