lonelymo
lonelymo

Reputation: 4192

Convert an xml array to another type of xml array using xslt

I've two xml files. Both are arrays of

person (having a lot of nodes underneath)

I need to convert this one

    <result>
        <sfobject>
            <id></id>
            <type>CompoundEmployee</type>
            <person>
                <lot of nodes/>
            </person>
        </sfobject>
        <sfobject>
            <id></id>
            <type>CompoundEmployee</type>
            <person>
                 <lot of nodes/>
            </person>
        </sfobject>
    </result>

to

    <queryCompoundEmployeeResponse>
        <CompoundEmployee>
            <id></id>
            <person>
                <lot of nodes/>
            </person>
        </CompoundEmployee>
        <CompoundEmployee>
            <id></id>
            <person>
              <lot of nodes/>
            </person>
        </CompoundEmployee>
    </queryCompoundEmployeeResponse>

using xslt. I've this xslt for it.

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output omit-xml-declaration="yes" indent="yes" />
        <xsl:strip-space elements="*" />
        <xsl:template match="node()|@*" name="identity">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*" />
            </xsl:copy>
        </xsl:template>
        <xsl:template match="sfobject/*[1]">
            <queryCompoundEmployeeResponse>
                <CompoundEmployee>
                    <id>
                        <xsl:value-of select="@id" />
                    </id>
                    <xsl:copy-of select="/*/person[1]" />
                    <xsl:call-template name="identity" />
                    </id>
                </CompoundEmployee>
            </queryCompoundEmployeeResponse>
        </xsl:template>
        <xsl:template match="/*/sfobject[1]" />
        <xsl:param name="removeElementsNamed" select="'type'"/>
    </xsl:stylesheet>

This doesn't check out well. I've done this before in groovy, but now this has to be converted to xslt as the system changed. I'm new to xslt and I'm sure I am to use an advanced level of xslt here. Any pointers are highly appreciated.

Is xslt the right tool at all here? Or should I stick to groovy?

Upvotes: 0

Views: 503

Answers (1)

Tim C
Tim C

Reputation: 70638

You have three rules you need to implement, it seems

  1. Rename result to queryCompoundEmployeeResponse
  2. Rename sfobject to whatever is held in type
  3. Remove type from under sfobject

Happuly, each rule here can actually be implemented as a separate template.

So, for rule 1, you do this...

<xsl:template match="result">
    <queryCompoundEmployeeResponse>
        <xsl:apply-templates />
    </queryCompoundEmployeeResponse>
</xsl:template>

For rule 2, do this...

<xsl:template match="sfobject">
    <xsl:element name="{type}">
        <xsl:apply-templates select="node()|@*" />
    </xsl:element>
</xsl:template>

And for rule 3, do this...

<xsl:template match="sfobject/type" />

You then use the identity template to handle all other nodes and attributes.

Try this XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes" />
    <xsl:strip-space elements="*" />

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

    <xsl:template match="result">
        <queryCompoundEmployeeResponse>
            <xsl:apply-templates />
        </queryCompoundEmployeeResponse>
    </xsl:template>

    <xsl:template match="sfobject">
        <xsl:element name="{type}">
            <xsl:apply-templates select="node()|@*" />
        </xsl:element>
    </xsl:template>

    <xsl:template match="sfobject/type" />
</xsl:stylesheet>

Upvotes: 1

Related Questions