3

I have a following XML code:

<Group>
    <GElement code="x">
        <Group>
            <GElement code="x">
                <fname>a</fname>
                <lname>b</lname>
            </GElement>
            <GElement code ="f">
                <fname>fa</fname>
            </GElement>
        </Group>
    </GElement>
    <GElement code ="f">
    </GElement>
</Group>

I would like to have the output sorted by "code" like:

<Group>
    <GElement code ="f">
    </GElement>
    <GElement code="x">
        <Group>
            <GElement code ="f">
                <fname>fa</fname>
            </GElement>
            <GElement code="x">
                <fname>a</fname>
                <lname>b</lname>
            </GElement>
        </Group>
    </GElement>
</Group>

The depth of the tree can be endless i.e. the GElement can have another Group and so on.

Any ideas?

3
  • I suspect there's an XSL solution for this but I'm not posting as an answer because I'm not entirely certain. Commented May 6, 2010 at 17:00
  • The minute you start fretting about how your XML looks is the moment you realize you have too much time on your hands. Commented May 6, 2010 at 17:11
  • 2
    @Will: This may be true for indentation, but document order carries meaning in XML, so why not implement something that relies on document order as well? Commented May 6, 2010 at 17:15

1 Answer 1

5

Use XslCompiledTransform (see MSDN) to apply this styleshet to your XML document:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <!-- the identity template copies everything verbatim -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>

  <!-- special template for <Group> that sorts its children -->
  <xsl:template match="Group">
    <xsl:copy>
      <xsl:copy-of select="@*" /> <!-- copy attributes, if any -->
      <xsl:apply-templates select="GElement">
        <xsl:sort select="@code" />
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

XML tree nesting depth can be arbitrary.

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

6 Comments

...yeah, something like this, was what I was thinking.
@tomalak, your first xsl:template has an xsl:apply-templates end tag
also, is <xsl:copy-of select="@*" /> necessary? is there any difference in the output if you remove it?
@DevNull: You're right. Corrected. No, there is no difference in the output with that particular input. But if there are attributes defined in the actual XML, they'll be copied. The <xsl:copy-of select="@*" /> does not hurt or take away performance, but it makes the solution correct.
@DevNull, thinking about it, to be really correct, the solution would also need an <xsl:copy-of select="node()[not(self::GElement])" />, but I estimated that contained elements other than <GElement> were unlikely. This estimate could be wrong, so I add it as a comment. :)
|

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.