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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...