Jump to content
Sign in to follow this  
kkalaany

split XML element into new elements

Recommended Posts

I'm trying to split the elements into new elements, from this format :

    <CTP>
        <name>ABSA bank</name>
        <BAs.BA>bank|sector|issuer</BAs.BA>
        <altIDs.altID.label_altSystem>ABSB_BBG|ASB_Reuters</altIDs.altID.label_altSystem>
    </CTP>



to this format:

    <CTP>
        <name>ABSA bank</name>
        <BAs>
            <BA>bank</BA>
            <BA>sector</BA>
            <BA>issuer</BA>
        </BAs>
        <altIDs>
            <aldID>
                <label>ABSB</label>
                <altSystem>BBG</altSystem>
            </aldID>
            <aldID>
                <label>ASB</label>
                <altSystem>Reuters</altSystem>
            </aldID>
        </altIDs>
    </CTP>


What I did so far is to transform this format:

    <CTP>
        <name>ABSA bank</name>
        <BAs.BA>bank|sector|issuer</BAs.BA>
        <FAs.FA.F>dep|sec|issue</FAs.FA.F>
    </CTP>

to this formmat :

    <?xml version="1.0" encoding="UTF-8"?>
    <CTP>
        <name>ABSA bank</name>
        <BAs>
            <BA>bank</BA>
            <BA>sector</BA>
            <BA>issuer</BA>
        </BAs>
        <FAs>
            <FA>
                <F>dep</F>
                <F>sec</F>
                <F>issue</F>
            </FA>
        </FAs>
    </CTP>


Using this Code with the help of @michael.hor257k



<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="*[contains(name(), '.')]" name="nest">
        <xsl:param name="name" select="name()"/>
        <xsl:param name="delimiter" select="'.'"/>
        <xsl:choose>
            <xsl:when test="contains($name, $delimiter)">
                <xsl:element name="{substring-before($name, $delimiter)}" >
                    <!-- recursive call -->
                    <xsl:call-template name="nest">
                        <xsl:with-param name="name" select="substring-after($name, $delimiter)"/>
                    </xsl:call-template>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:call-template name="tokenize">
                    <xsl:with-param name="name" select="$name"/>
                    <xsl:with-param name="text" select="."/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    
    <xsl:template name="tokenize">
        <xsl:param name="name"/>
        <xsl:param name="text"/>
        <xsl:param name="delimiter" select="'|'"/>
        <xsl:variable name="token" select="substring-before(concat($text, $delimiter), $delimiter)" />
        <xsl:if test="$token">
            <xsl:element name="{$name}" >
                <xsl:value-of select="$token"/>
            </xsl:element>
        </xsl:if>
        <xsl:if test="contains($text, $delimiter)">
            <!-- recursive call -->
            <xsl:call-template name="tokenize">
                <xsl:with-param name="name" select="$name"/>
                <xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
    
    </xsl:stylesheet>

The tricky step that I need is how to use many delimiters and access layers and levels to write the needed XML format.

Share this post


Link to post
Share on other sites


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<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="*[contains(name(), '_')]" name="nest">

<xsl:param name="name" select="name()" />

<xsl:param name="delimiter" select="'_'" />

<xsl:param name="text" select="." />

<xsl:variable name="token" select="substring-before(concat($text, $delimiter), $delimiter)" />

<xsl:choose>

<xsl:when test="contains($name, $delimiter)">

<xsl:element name="{substring-before($name, $delimiter)}">

<xsl:value-of select="$token" />

</xsl:element>

<xsl:element name="{substring-after($name, $delimiter)}">

<xsl:variable name="token" select="substring-after($text, $delimiter)" />

<xsl:value-of select="$token" />

<!-- recursive call -->

<xsl:call-template name="nest">

<xsl:with-param name="name" select="substring-after($name, $delimiter)" />

<xsl:with-param name="text" select="substring-after($text, $delimiter)" />

</xsl:call-template>

</xsl:element>

</xsl:when>

</xsl:choose>

</xsl:template>

</xsl:stylesheet>

 

Edited by kkalaany

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×