xmlfor-loopxsltxslt-1.0delimiter

xslt 1.0 - need a delimiter between each node value under for-each select


i have ran out of ideas on my XSLT 1.0 below. Could you guys guide me on how to insert a delimiter between every node values?

My source XML:

<NtryDtls>
        <TxDtls>
            <RmtInf>
                <Strd>
                    <CdtrRefInf>
                        <Tp>
                            <CdOrPrtry>
                                <Cd>SCOR</Cd>
                            </CdOrPrtry>
                        </Tp>
                        <Ref>VIER000627054</Ref>
                    </CdtrRefInf>
                </Strd>
            </RmtInf>
        </TxDtls>
</NtryDtls>

and i have this XSLT 1.0 code:

<?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" indent="yes"/>
    <xsl:template match="/">
        <xsl:for-each select="NtryDtls/TxDtls/RmtInf">
            <xsl:for-each select="*">
                <xsl:for-each select="node() | @*">
                    <xsl:value-of select="."/>
                    <xsl:if test="not(position()=last())  ">,</xsl:if>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

the result that i get is

,SCORVIER000627054,

instead of expected result where ',' should appear in between every node values:

SCOR, VIER000627054

Solution

  • First thing, if you want to get a text result then change your output method to text.

    Now, the main problem with your stylesheet is that your two instructions:

            <xsl:for-each select="*">
                <xsl:for-each select="node() | @*">
    

    end up selecting all child nodes of Strd which apart from some whitespace-only text nodes includes only the CdtrRefInf element. Then your instruction:

                     <xsl:value-of select="."/>
    

    will return a concatenation of all text node descendants of CdtrRefInf with no separator between them.

    The best thing would be to select each element with a text node explicitly. If you cannot do that and need to select all text nodes that are descendants of Strd (except whitespace-only nodes) you could do:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="/">
        <xsl:for-each select="NtryDtls/TxDtls/RmtInf">
            <xsl:for-each select="*/descendant::text()">
                <xsl:value-of select="."/>
                <xsl:if test="not(position()=last())  ">,</xsl:if>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
        
    </xsl:stylesheet>