Abhi
Abhi

Reputation: 303

Generate comma separated xml using xsl

This seems pretty simple, but I'm missing to generate the required output. Any help would be appreciated.

Input XML:

<?xml version="1.0" encoding="UTF-8"?>
<Event xmlns="urn:sobject.partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Id>00Uc0000001iioEEAQ</Id>
<Subject>TestMeeting2</Subject>
<StartDateTime xsi:nil="true"/>
<Owner>
    <Name>dev0044</Name>
    <Email>[email protected]</Email>
</Owner>
<Notes_Universal_ID__c xsi:nil="true"/>
<Location>San Jose</Location>
<IsPrivate>false</IsPrivate>
<IsDeleted>false</IsDeleted>
<EndDateTime xsi:nil="true"/>
<Description>test description</Description>
<EventRelations>
    <EventRelation>
        <EventId>00Uc0000001iioEEAQ</EventId>
        <RelationId>005c0000000T9YQAA0</RelationId>
        <Relation>
            <Email>[email protected]</Email>
        </Relation>
    </EventRelation>
    <EventRelation>
        <EventId>00Uc0000001iioEEAQ</EventId>
        <RelationId>005c0000000T9YaAAK</RelationId>
        <Relation>
            <Email>[email protected]</Email>
        </Relation>
    </EventRelation>
</EventRelations>

Required Output XML:

<?xml version="1.0" encoding="UTF-8"?>
<CREATEAPPOINTMENT>
<STRUSERNAME>testuser0044</STRUSERNAME>
<STRSTARTDATETIME/>
<STRENDDATETIME/>
<STRSUBJECT>TestMeeting2</STRSUBJECT>
<STRDESCRIPTION>Email : [email protected], [email protected]. Description:    test description</STRDESCRIPTION>
<SRTLOCATION>San Jose</SRTLOCATION>
<STRPRIVATE>0</STRPRIVATE>
<STRAVAILABLE>0</STRAVAILABLE>
</CREATEAPPOINTMENT>

I'm able to get all except for the description field. The STRDESCRIPTION will contain a concatenation of EventRelations/EventRelation/Relation/Email (comma separated email addresses) and the actual Description field.

Here's the xsl that I'm trying with:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" 
xmlns:sf="urn:partner.soap.sforce.com" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/">
<xsl:output indent="yes" method="xml"/>

<xsl:template match="*:Event">
    <xsl:element name="CREATEAPPOINTMENT">
        <xsl:element name="STRUSERNAME"><xsl:value-of select="*:Owner/*:Name"/></xsl:element>
        <xsl:element name="STRSTARTDATETIME"><xsl:value-of select="*:StartDateTime"/></xsl:element>
        <xsl:element name="STRENDDATETIME"><xsl:value-of select="*:EndDateTime"/></xsl:element>
        <xsl:element name="STRSUBJECT"><xsl:value-of select="*:Subject"/></xsl:element>
        <xsl:variable name="description" select="*:Description"/>

        <xsl:element name="SRTDESCRIPTION">
        <xsl:for-each select="*:EventRelations/*:EventRelation">
            <xsl:variable name="email" select="*:Relation/*:Email"/>
                <!-- <xsl:value-of select="concat('Email : ', $email, ' : Description : ')"></xsl:value-of> -->
            <xsl:value-of select="$email"/>
            <xsl:text>, </xsl:text>
            <xsl:value-of select="$description"></xsl:value-of>
            <xsl:text>, </xsl:text>
        </xsl:for-each>
        </xsl:element>

        <xsl:element name="SRTLOCATION"><xsl:value-of select="*:Location"/></xsl:element>

        <xsl:choose>
            <xsl:when test="*:IsPrivate = 'false'">
                <xsl:element name="STRPRIVATE">0</xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:element name="STRPRIVATE">1</xsl:element>
            </xsl:otherwise>
        </xsl:choose>

        <xsl:choose>
            <xsl:when test="*:IsPrivate = 'false'">
                <xsl:element name="STRAVAILABLE">0</xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:element name="STRAVAILABLE">1</xsl:element>
            </xsl:otherwise>
        </xsl:choose>

    </xsl:element>
</xsl:template>

Upvotes: 0

Views: 186

Answers (1)

Daniel Haley
Daniel Haley

Reputation: 52848

Since you're using XSLT 2.0, you can use the separator attribute of xsl:value-of. You can also use xpath-default-namespace so you don't have to use * as the prefix.

Example:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xpath-default-namespace="urn:sobject.partner.soap.sforce.com">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="text()"/>

    <xsl:template match="/*">
        <CREATEAPPOINTMENT>
            <xsl:apply-templates select="(Owner,StartDateTime,EndDateTime,
                Subject,Description,Location,IsPrivate)"/>
        </CREATEAPPOINTMENT>
    </xsl:template>

    <xsl:template match="Owner/Name">
        <STRUSERNAME><xsl:value-of select="."/></STRUSERNAME>
    </xsl:template>

    <xsl:template match="StartDateTime">
        <STRSTARTDATETIME><xsl:value-of select="."/></STRSTARTDATETIME>
    </xsl:template>

    <xsl:template match="EndDateTime">
        <STRENDDATETIME><xsl:value-of select="."/></STRENDDATETIME>
    </xsl:template>

    <xsl:template match="Subject">
        <STRSUBJECT><xsl:value-of select="."/></STRSUBJECT>
    </xsl:template>

    <xsl:template match="Description">
        <STRDESCRIPTION>
            <xsl:text>Email: </xsl:text>
            <xsl:value-of select="../EventRelations/*/Relation/Email" separator=", "/>
            <xsl:text> DESCRIPTION: </xsl:text>
            <xsl:value-of select="."/>
        </STRDESCRIPTION>
    </xsl:template>

    <xsl:template match="Location">
        <SRTLOCATION><xsl:value-of select="."/></SRTLOCATION>
    </xsl:template>

    <xsl:template match="IsPrivate">
        <STRPRIVATE><xsl:apply-templates/></STRPRIVATE>
        <STRAVAILABLE><xsl:apply-templates/></STRAVAILABLE>
    </xsl:template>

    <xsl:template match="IsPrivate/text()">
        <xsl:choose>
            <xsl:when test=".='false'"><xsl:text>0</xsl:text></xsl:when>
            <xsl:otherwise><xsl:text>1</xsl:text></xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

Output

<CREATEAPPOINTMENT>
   <STRUSERNAME>dev0044</STRUSERNAME>
   <STRSTARTDATETIME/>
   <STRENDDATETIME/>
   <STRSUBJECT>TestMeeting2</STRSUBJECT>
   <STRDESCRIPTION>Email: [email protected], [email protected] DESCRIPTION: test description</STRDESCRIPTION>
   <SRTLOCATION>San Jose</SRTLOCATION>
   <STRPRIVATE>0</STRPRIVATE>
   <STRAVAILABLE>0</STRAVAILABLE>
</CREATEAPPOINTMENT>

Note: The order of the elements is different from the output in your question. If the order matters, you can add a select to the xsl:apply-templates in the /* template specifying the order. (I can modify it if it helps.)

Also, if you're creating the new elements by adding "STR" to the beginning, you can replace the templates for StartDateTime, EndDateTime, Subject, and Location with this one:

<xsl:template match="StartDateTime|EndDateTime|Subject|Location">
    <xsl:element name="STR{upper-case(local-name())}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

Upvotes: 1

Related Questions