Reputation: 25
I am relatively new to XSLT and i am working on a project involving xml and xslt1.0.
I have a xml code (simplified version) that looks like
<visualChildren>
<object class="com.zerog.ia.installer.InstallSet" >
<installChildren>
<object class="com.zerog.ia.installer.InstallBundle" objectID="33110emc908m">
<property></property>
</object>
<object class="com.zerog.ia.installer.InstallBundle" objectID="43110emc9667m">
<property></property>
</object>
</installChildren>
</object>
</visualChildren>
I would need to collect all the object ids iteratively and store as
<object RefId={ObjectId} />
under visualChildren. Expected result is
<visualChildren>
<object class="com.zerog.ia.installer.InstallSet" >
<installChildren>
<object class="com.zerog.ia.installer.InstallBundle" objectID="33110emc908m">
<property></property>
</object>
<object class="com.zerog.ia.installer.InstallBundle" objectID="43110emc9667m">
<property></property>
</object>
</installChildren>
</object>
<object RefId=33110emc908m />
<object RefId=43110emc9667m />
</visualChildren>
Could anyone help me to achieve this with xslt 1.0
Upvotes: 2
Views: 1385
Reputation: 117140
Try it this way:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/visualChildren">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:for-each select=".//@objectID">
<object RefId="{.}"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note:
If the objects you want to collect are always under installChildren
, then replace:
<xsl:for-each select=".//@objectID">
with the more efficient:
<xsl:for-each select="object/installChildren/object/@objectID">
Upvotes: 0
Reputation: 111726
You can modify the identity transformation to copy over everything exactly except for the visualChildren/object
elements, which can be copied over as-is plus the RefId
attribute you request:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="visualChildren/object">
<xsl:copy>
<xsl:attribute name="RefId">
<xsl:for-each select="//@objectID">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Applying the above XSLT to your input XML:
<visualChildren>
<object class="com.zerog.ia.installer.InstallSet" >
<installChildren>
<object class="com.zerog.ia.installer.InstallBundle" objectID="33110emc908m">
<property></property>
</object>
<object class="com.zerog.ia.installer.InstallBundle" objectID="43110emc9667m">
<property></property>
</object>
</installChildren>
</object>
</visualChildren>
Yields the following output XML:
<?xml version="1.0" encoding="UTF-8"?>
<visualChildren>
<object RefId="33110emc908m 43110emc9667m"
class="com.zerog.ia.installer.InstallSet">
<installChildren>
<object class="com.zerog.ia.installer.InstallBundle" objectID="33110emc908m">
<property/>
</object>
<object class="com.zerog.ia.installer.InstallBundle" objectID="43110emc9667m">
<property/>
</object>
</installChildren>
</object>
</visualChildren>
As requested.
Note: Should you want all of the @objectID
attributes below a given visualChildren/object
element rather than all of the @objectID
attributes in the entire document, then change
<xsl:for-each select="//@objectID">
to
<xsl:for-each select=".//@objectID">
Upvotes: 3