u_1958148
u_1958148

Reputation: 383

xslt 1.0 make attribute as parent node

I need to transform the code below:

<test>
 <employee department="HR">john</employee>
 <intern department="HR">Jack</intern>
 <employee  department="HR">Jill</employee>
 <intern department="IT">Joe</intern>
 <employee department="IT">janet</employee>
 <intern department="IT">Jix</intern>
</test>

and make it look like the following

<test>
  <department id="HR">
    <employee department="HR">john</employee>
    <intern department="HR">Jack</intern>
    <employee department="HR">Jill</employee>
  </department>
  <department id="IT">
    <intern department="IT">Joe</intern>
    <employee department="IT">janet</employee>
    <intern department="IT">Jix</intern>
  </department>
</test>

I need to use XSLT 1.0

Upvotes: 0

Views: 55

Answers (1)

hr_117
hr_117

Reputation: 9627

With a valid xml like this:

<test>
 <employee department="HR">john</employee>
 <intern department="HR">Jack</intern>
 <employee  department="HR">Jill</employee>
 <intern department="IT">Joe</intern>
 <employee department="IT">janet</employee>
 <intern department="IT">Jix</intern>
</test>

Then two small templates Muenchian Method and a key will do:

<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key  name="kdepartment" match="test/*[@department]" use="@department"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="test">
        <xsl:copy>
            <xsl:for-each select="*[@department][count(. | key('kdepartment', ./@department)[1]) = 1]">
                <xsl:variable name="this" select="." />
                <department id="{./@department}">
                    <xsl:for-each select="key('kdepartment', $this/@department) ">
                        <xsl:apply-templates select="." />
                    </xsl:for-each>
                </department>
        </xsl:for-each>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

To get this output:

<test>
  <department id="HR">
    <employee department="HR">john</employee>
    <intern department="HR">Jack</intern>
    <employee department="HR">Jill</employee>
  </department>
  <department id="IT">
    <intern department="IT">Joe</intern>
    <employee department="IT">janet</employee>
    <intern department="IT">Jix</intern>
  </department>

Upvotes: 1

Related Questions