1

Here is an xml I want to transform to below result using xsl. Any help please.This is some thing like windows directory structure.here the depth of the directory is dynamic.

<?xml version="1.0" encoding="UTF-8"?>
<root>
<qc name="accounting" level="1">
    <qc name="fund" level="2">
        <qc name="v1_0" level="3"/>
    </qc>
</qc>
<qc name="asset_allocation" level="1">
    <qc name="fund" level="2">
        <qc name="v1_0" level="3"/>
    </qc>
</qc>
<qc name="asset_allocation" level="1">
    <qc name="fund" level="2">
        <qc name="v1_1" level="3"/>
    </qc>
</qc>
<qc name="credit_quality" level="1">
    <qc name="account" level="2">
        <qc name="v1_0" level="3"/>
    </qc>
</qc>
<qc name="credit_quality" level="1">
    <qc name="fund" level="2">
        <qc name="v1_0" level="3"/>
    </qc>
</qc>
<qc name="credit_quality" level="1">
    <qc name="v1_0" level="2"/>
</qc>
<qc name="credit_quality" level="1">
    <qc name="v2_0" level="2"/>
</qc>
<qc name="portfolio" level="1">
    <qc name="credit_quality" level="2">
        <qc name="v1_0" level="3"/>
    </qc>
</qc>
</root>

In above xml I have with each level name. I want to group the same names at the same level.

Result:

<root>
<qc name="accounting" level="1">
    <qc name="fund" level="2">
        <qc name="v1_0" level="3"/>
    </qc>
</qc>
<qc name="asset_allocation" level="1">
    <qc name="fund" level="2">
        <qc name="v1_0" level="3"/>
        <qc name="v1_1" level="3"/>
    </qc>
</qc>
<qc name="credit_quality" level="1">
    <qc name="account" level="2">
        <qc name="v1_0" level="3"/>
    </qc>
    <qc name="fund" level="2">
        <qc name="v1_0" level="3"/>
    </qc>
    <qc name="v1_0" level="2"/>
    <qc name="v2_0" level="2"/>
</qc>
<qc name="portfolio" level="1">
    <qc name="credit_quality" level="2">
        <qc name="v1_0" level="3"/>
    </qc>
</qc>
 </root>
1
  • So where's the XSL you have so far? Commented Apr 20, 2012 at 21:58

2 Answers 2

2

If you can use XSLT 2.0, do, and use the xsl:for-each-group instruction.

If you are stuck with XSLT 1.0, read up about Muenchian grouping.

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

Comments

1

A quick hack using XSLT 1.0 and EXSLT functions could look like this. It's probably not the most elegant solution but it should work.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:func="http://exslt.org/functions"
  xmlns:my="my-namespace"
  extension-element-prefixes="func"
  exclude-result-prefixes="my">

  <xsl:key name="qc-by-path" match="qc" use="my:path(.)"/>

  <xsl:template match="root">
    <root>
      <xsl:apply-templates/>
    </root>
  </xsl:template>

  <xsl:template match="qc">
    <xsl:variable name="peers" select="key('qc-by-path', my:path(.))"/>
    <xsl:if test="generate-id(.)=generate-id($peers[1])">
      <qc name="{@name}" level="{@level}">
        <xsl:apply-templates select="$peers/qc"/>
      </qc>
    </xsl:if>
  </xsl:template>

  <func:function name="my:path">
    <xsl:param name="qc"/>
    <xsl:choose>
      <xsl:when test="$qc/parent::qc">
        <func:result select="concat(my:path($qc/parent::qc),'/',$qc/@name)"/>
      </xsl:when>
      <xsl:otherwise>
        <func:result select="$qc/@name"/>
      </xsl:otherwise>
    </xsl:choose>  
  </func:function>
</xsl:stylesheet>

Comments

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.