I am trying to extract a UML profile definition from a XMI model document and then removing unwanted/illegal attributes using XSLT
Source XMI looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<xmi:XMI xmlns:uml="http://www.omg.org/spec/UML/20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:umldi="http://www.omg.org/spec/UML/20131001/UMLDI" xmlns:dc="http://www.omg.org/spec/UML/20131001/UMLDC" xmlns:thecustomprofile="http://www.sparxsystems.com/profiles/thecustomprofile/1.0" xmlns:Plusprofil="http://www.sparxsystems.com/profiles/Plusprofil/0.9.1">
<uml:Model xmi:type="uml:Model" name="EA_Model">
<...>
</uml:Model>
<xmi:Extension extender="Enterprise Architect" extenderID="6.5">
<...>
<profiles>
<uml:Profile xmlns:uml="http://www.omg.org/spec/UML/20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmi:id="FF44B996-D" nsPrefix="Plusprofil" name="Plusprofil" metamodelReference="mmref01">
<packagedElement xmi:type="uml:Extension" xmi:id="Property_RdfsProperty" name="A_Property_RdfsProperty" memberEnd="extension_RdfsProperty RdfsProperty-base_Property">
<ownedEnd xmi:id="extension_RdfsProperty" name="extension_RdfsProperty" type="RdfsProperty" isComposite="true" lower="0" upper="1" memberEnd="extension_RdfsProperty RdfsProperty-base_Property"/>
</packagedElement>
<...>
</uml:Profile>
</profiles>
</xmi:Extension>
</xmi:XMI>
The intended output looks like this - the profile part of the model, with attributes nsPrefix, lower, upper and isComposite removed:
<?xml version="1.0" encoding="utf-8"?>
<uml:Profile xmlns:uml="http://www.omg.org/spec/UML/20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmi:id="FF44B996-D" name="Plusprofil" metamodelReference="mmref01">
<packagedElement xmi:type="uml:Extension" xmi:id="Property_RdfsProperty" name="A_Property_RdfsProperty" memberEnd="extension_RdfsProperty RdfsProperty-base_Property">
<ownedEnd xmi:id="extension_RdfsProperty" name="extension_RdfsProperty" type="RdfsProperty" memberEnd="extension_RdfsProperty RdfsProperty-base_Property"/>
</packagedElement>
<...>
</uml:Profile>
I can easily extract the profile part using copy-of, like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.omg.org/spec/UML/20131001">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/" >
<xsl:copy-of select="/xmi:XMI/xmi:Extension/profiles/uml:Profile[@name='Plusprofil']" >
</xsl:copy-of>
</xsl:template>
</xsl:stylesheet>
And I can work with the resulting file, using the identity transform pattern in another style sheet to remove attributes:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.omg.org/spec/UML/20131001">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@nsPrefix"/>
<xsl:template match="@memberEnd"/>
<xsl:template match="ownedEnd/@lower[../@lower='0']"/>
<xsl:template match="ownedEnd/@upper[../@upper='1']"/>
<xsl:template match="ownedEnd/@isComposite[../@isComposite='true']"/>
</xsl:stylesheet>
but how do I combine the two efforts in a single file? I would think, this would work, but it doesnt remove the illegal attributes:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.omg.org/spec/UML/20131001">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/" >
<xsl:copy-of select="/xmi:XMI/xmi:Extension/profiles/uml:Profile[@name='Plusprofil']" >
<xsl:call-template name="modify" select="@* | node()"/>
</xsl:copy-of>
</xsl:template>
<xsl:template name="modify" match="@* | node()" >
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@nsPrefix"/>
<xsl:template match="@memberEnd"/>
<xsl:template match="ownedEnd/@lower[../@lower='0']"/>
<xsl:template match="ownedEnd/@upper[../@upper='1']"/>
<xsl:template match="ownedEnd/@isComposite[../@isComposite='true']"/>
</xsl:stylesheet>
Instead if using xsl:copy-of
in the main template matching /
(which won't work as you cannot have any other xslt commands nested in it), use xsl:apply-templates
<xsl:template match="/" >
<xsl:apply-templates select="xmi:XMI/xmi:Extension/profiles/uml:Profile[@name='Plusprofil']" />
</xsl:template>
This way either the identity template can be used, or one of your overriding templates if they match.