NMMA
NMMA

Reputation: 173

split different element attribute into multiple duplicate rows

I am trying to transform XML, I have multiple and different input. I tried many solutions like Split specific element attribute into multiple rows based on delimiter but in my case I have different element with different attribute. Any suggestions please?

Input:

<ROOT>
<Data X="1233" Y="1:30:57" Z="abcd"/>
<Info T="1:30:57" F="xyz" H="1234" "/>

Excepted Output:

<ROOT>
    <Data X="1233"/>
    <Data Y="1:30:57"/>
    <Data Z="abcd"/>
    <Info T="1:30:57 />
    <Info F="xyz" />
    <Info H="1234"/>    

Upvotes: 0

Views: 55

Answers (3)

zx485
zx485

Reputation: 29022

A solution to your problem is the following stylesheet:

<?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" version="1.0" encoding="UTF-8" indent="yes"/>

  <xsl:template match="/ROOT">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Data | Info">
    <xsl:variable name="nod" select="local-name()" />
    <xsl:for-each select="@*">
        <xsl:element name="{$nod}">
            <xsl:attribute name="{local-name()}">
                <xsl:value-of select="." />
            </xsl:attribute>
        </xsl:element>
    </xsl:for-each>
  </xsl:template>  

</xsl:stylesheet>

The output is:

<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
    <Data X="1233"/>
    <Data Y="1:30:57"/>
    <Data Z="abcd"/>
    <Info T="1:30:57"/>
    <Info F="xyz"/>
    <Info H="1234"/>
</ROOT>

Upvotes: 2

kalinma
kalinma

Reputation: 527

If you format your input properly

<document>
    <ROOT>
        <Data X="1233" Y="1:30:57" Z="abcd"/>
        <Info T="1:30:57" F="xyz" H="1234"/>
    </ROOT>
</document>

This should do it

<xsl:template match="Data | Info">
    <xsl:for-each select="./@*">
        <xsl:element name="{name(./parent::node())}">
            <xsl:attribute name="{local-name()}">
                <xsl:value-of select="." />                
            </xsl:attribute>
        </xsl:element>
    </xsl:for-each>
</xsl:template>

Upvotes: 0

kalinma
kalinma

Reputation: 527

Your data is not actually well formed, meaning your attributes are not formatted properly.

<ROOT>
    <Data "X=1233,Y=1:30:57,Z=abcd"/>
    <Info " T=1:30:57,F=xyz,H=1234 "/>
</ROOT>

Should really be

<ROOT>
    <Data X="1233" Y="1:30:57" Z="abcd"/>
    <Info T="1:30:57" F="xyz" H="1234"/>
</ROOT>

If you must work with what you've got, you might be able to do something with xsl:analyze-string, but I'm dubious about that because the data is not well-formed XML.I don't think you'll be able to parse the attributes as they are.

Upvotes: 0

Related Questions