Assuming this input XML
<?xml version="1.0" encoding="UTF-8"?>
<rows>
<row>
<cell>PART_ID</cell>
<cell>TITLE</cell>
<cell>ITEM_NUMBER</cell>
<cell>SUBASSEMBLY_ITEM</cell>
<cell>QUANTITY</cell>
</row>
<row>
<cell>id1</cell>
<cell> some title </cell>
<cell>1</cell>
<cell>y;x,z</cell>
<cell>20</cell>
</row>
<row>
<cell>id2</cell>
<cell> another title </cell>
<cell>2</cell>
<cell>q/r|s</cell>
<cell>10</cell>
</row>
</rows>
here is a somewhat parametrised XPath-based solution to generically generate CSV output:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/">
<xsl:value-of select="
let $escapeChar := '"',
$newLine := '
',
$separator := ','
return //row ! (string-join(* ! string-join($escapeChar||normalize-space(.)||$escapeChar),$separator),$newLine)"
separator=""/>
</xsl:template>
</xsl:stylesheet>
Output:
"PART_ID","TITLE","ITEM_NUMBER","SUBASSEMBLY_ITEM","QUANTITY"
"id1","some title","1","y;x,z","20"
"id2","another title","2","q/r|s","10"
If you want a more XSLT-based solution I’d recommend to make use of templates:
<xsl:variable name="escapeChar" select="'"'" as="xs:string"/>
<xsl:variable name="separator" select="','" as="xs:string"/>
<xsl:variable name="newLine" select="'
'" as="xs:string"/>
<!-- identity template or shallow-skip -->
<xsl:mode on-no-match="shallow-skip"/>
<xsl:template match="//row">
<xsl:apply-templates select="*"/>
<xsl:value-of select="$newLine"/>
</xsl:template>
<xsl:template match="*[parent::row]">
<xsl:value-of select="$escapeChar"/>
<xsl:value-of select="."/>
<xsl:value-of select="$escapeChar"/>
<xsl:if test="not(position()=last())">
<xsl:value-of select="$separator"/>
</xsl:if>
</xsl:template>
CLICK HERE to find out more related problems solutions.