I'm trying to transform an XML file into another but I'm having a problem with keeping the same hierarchy of the input file.
Here's the input:
<XMI xmi.version='1.2' xmlns:UML="org.omg.xmi.namespace.UML">
<XMI.content>
<UML:Model xmi.id='eee_1045467100313_135436_1' name='Data'>
<UML:Namespace.ownedElement>
<UML:Package xmi.id='_9_0_bc102e5_1427365805826_580042_23' name='migration_kbir'>
<UML:Namespace.ownedElement>
<UML:Package xmi.id='_9_0_bc102e5_1427365805826_580042_22' name='migration_s8ir'>
<UML:Package xmi.id='_9_0_bc102e5_1427365805826_580042_22' name='migration_s8ir2'>
<UML:Class xmi.id='_9_0_bc102e5_1427367042666_255023_151' name='Employee'>
<UML:Classifier.feature>
<UML:Attribute xmi.id='_9_0_bc102e5_1427367052819_893122_168' name='cin'>
</UML:Attribute>
</UML:Classifier.feature>
</UML:Class>
<UML:Class xmi.id='_9_0_64701d4_1429716452808_363115_43' name='AssoEmpl'>
</UML:Class>
<UML:Generalization xmi.id='_9_0_64701d4_1429719509242_100032_198' child='_9_0_64701d4_1429719498101_197360_182' parent='_9_0_64701d4_1429716437842_892182_26' />
</UML:Package>
</UML:Package>
</UML:Namespace.ownedElement>
</UML:Package>
</UML:Namespace.ownedElement>
</UML:Model>
</XMI.content>
</XMI>
Here's what I get as an output:
<xmi:XMI xmlns:xmi="http://www.omg.org/XMI" xmlns:UML="org.omg.xmi.namespace.UML"
xmi.version="2.1" timestamp="">
<packagedElement xmi:type="uml:package"
xmi.id="_9_0_bc102e5_1427365805826_580042_23" name="migration_kbir" />
<packagedElement xmi:type="uml:package"
xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir" />
<packagedElement xmi:type="uml:package"
xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir2">
<packagedElement xmi:type="uml:Class"
xmi.id="_9_0_bc102e5_1427367042666_255023_151" name="Employee">
<generalization xmi.id="_9_0_bc102e5_1427367042666_255023_151">
<general xmi:type="uml:Class" />
</generalization>
<ownedAttribute xmi.id="_9_0_bc102e5_1427367052819_893122_168"
name="cin" />
</packagedElement>
<packagedElement xmi:type="uml:Class"
xmi.id="_9_0_64701d4_1429716452808_363115_43" name="AssoEmpl">
<generalization xmi.id="_9_0_64701d4_1429716452808_363115_43">
<general xmi:type="uml:Class" />
</generalization>
</packagedElement>
</packagedElement>
</xmi:XMI>
but I'm expecting something like this:
<xmi:XMI xmlns:xmi="http://www.omg.org/XMI" xmlns:UML="org.omg.xmi.namespace.UML" xmi.version="2.1" timestamp="">
<packagedElement xmi:type="uml:package" xmi.id="_9_0_bc102e5_1427365805826_580042_23" name="migration_kbir">
<packagedElement xmi:type="uml:package"xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir">
<packagedElement xmi:type="uml:package"xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir2">
<packagedElement xmi:type="uml:Class"xmi.id="_9_0_bc102e5_1427367042666_255023_151" name="Employee">
<generalization xmi.id="_9_0_bc102e5_1427367042666_255023_151">
<general xmi:type="uml:Class" />
</generalization>
<ownedAttribute xmi.id="_9_0_bc102e5_1427367052819_893122_168"name="cin" />
</packagedElement>
<packagedElement xmi:type="uml:Class" xmi.id="_9_0_64701d4_1429716452808_363115_43" name="AssoEmpl">
<generalization xmi.id="_9_0_64701d4_1429716452808_363115_43">
<general xmi:type="uml:Class" />
</generalization>
</packagedElement>
</packagedElement>
</packagedElement>
</packagedElement>
</xmi:XMI>
and finally here's my transformation file:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:UML="org.omg.xmi.namespace.UML"
xmlns:xmi="http://www.omg.org/XMI"
>
<xsl:output indent="yes" method="xml" />
<xsl:template match="/">
<xmi:XMI>
<xsl:attribute name="xmi.version">2.1</xsl:attribute>
<xsl:attribute name="timestamp">
<xsl:value-of select="@timestamp" />
</xsl:attribute>
<xsl:for-each select="//UML:Package">
<packagedElement>
<xsl:attribute name="xmi:type">uml:package</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
<xsl:choose>
<xsl:when test="UML:Class">
<xsl:for-each select="UML:Class">
<packagedElement>
<xsl:attribute name="xmi:type">uml:Class</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
<generalization>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<general xmi:type="uml:Class" />
</generalization>
<xsl:for-each select="UML:Classifier.feature/UML:Attribute">
<ownedAttribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
</ownedAttribute>
</xsl:for-each>
</packagedElement>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</packagedElement>
</xsl:for-each>
</xmi:XMI>
</xsl:template>
</xsl:stylesheet>
What should I do in the transformation code to keep the hierarchy of my input file?
When you do:
<xsl:for-each select="//UML:Package">
you are selecting all UML:Package
elements, anywhere in the document, and treating them as siblings. Since that's not what you want, you need to change your approach and apply templates recursively instead.
I have made a quick adjustment to your existing styleheet, see if that works for you:
<xsl:stylesheet xmlns:UML="org.omg.xmi.namespace.UML" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xmi:XMI xmi.version="2.1">
<xsl:attribute name="xmi.version">2.1</xsl:attribute>
<xsl:attribute name="timestamp">
<xsl:value-of select="@timestamp"/>
</xsl:attribute>
<xsl:apply-templates/>
</xmi:XMI>
</xsl:template>
<xsl:template match="UML:Package">
<packagedElement>
<xsl:attribute name="xmi:type">uml:package</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="UML:Class">
<xsl:for-each select="UML:Class">
<packagedElement>
<xsl:attribute name="xmi:type">uml:Class</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<generalization>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<general xmi:type="uml:Class"/>
</generalization>
<xsl:for-each select="UML:Classifier.feature/UML:Attribute">
<ownedAttribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
</ownedAttribute>
</xsl:for-each>
</packagedElement>
</xsl:for-each>
</xsl:when>
</xsl:choose>
<xsl:apply-templates/>
</packagedElement>
</xsl:template>
</xsl:stylesheet>
Note:
You should learn how to add attributes directly to literal result elements, and how to use the attribute value template. This could simplify your stylesheet considerably.
This:
<xsl:attribute name="timestamp">
<xsl:value-of select="@timestamp"/>
</xsl:attribute>
makes no sense in the context of the root node that has no attributes.