In this thread I refer to my last thread: Convert XML to CSV using XSLT - dynamic columns.
The XSLT script in the refered thread works fine but with a large
See an actual example of an XSLT transformation that produces a stylesheet for another XSLT transformation here:
http://dnovatchev.wordpress.com/2006/10/21/a-stylesheet-to-write-xslt-code/
Rather than a two-external-phase solution (meaning a style-sheet that writes a style-sheet that gets executed), I think you would be better served by a version of Tim's solution that performs better at scale. Please measure the performance of this solution with your 'large XML document' as input.
This XSLT 1.0 style-sheet...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:key name="kTypes" match="Type" use="." />
<xsl:variable name="distinct-types"
select="/*/Person/FamilyMembers/FamilyMember/Type[
generate-id()=generate-id(key('kTypes',.)[1])]" />
<xsl:template match="/">
<xsl:value-of select="'Name;'" />
<xsl:for-each select="$distinct-types">
<xsl:value-of select="." />
<xsl:if test="position() < last()">
<xsl:value-of select="';'" />
</xsl:if>
</xsl:for-each>
<xsl:value-of select="'
'" />
<xsl:apply-templates select="*/Person" />
</xsl:template>
<xsl:template match="Person">
<xsl:value-of select="concat(Name,';')" />
<xsl:variable name="family" select="FamilyMembers/FamilyMember" />
<xsl:for-each select="$distinct-types">
<xsl:variable name="type" select="string(.)" />
<xsl:value-of select="$family/self::*[Type=$type]/Name" />
<xsl:if test="position() < last()">
<xsl:value-of select="';'" />
</xsl:if>
</xsl:for-each>
<xsl:value-of select="'
'" />
</xsl:template>
</xsl:stylesheet>
...will transform this input (or others efficiently at scale) ...
<t>
<Person>
<Name>John</Name>
<FamilyMembers>
<FamilyMember>
<Name>Lisa</Name>
<Type>Sister</Type>
</FamilyMember>
<FamilyMember>
<Name>Tom</Name>
<Type>Brother</Type>
</FamilyMember>
</FamilyMembers>
</Person>
<Person>
<Name>Daniel</Name>
<FamilyMembers>
<FamilyMember>
<Name>Peter</Name>
<Type>Father</Type>
</FamilyMember>
</FamilyMembers>
</Person>
</t>
... and yield text...
Name;Sister;Brother;Father
John;Lisa;Tom;
Daniel;;;Peter
To write one XSLT that outputs another you either need to generate the output elements using <xsl:element>
, e.g.
<xsl:element name="xsl:text">
or use <xsl:namespace-alias>
if you want to use literal result elements. The XSLT spec has an example:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias">
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:template match="/">
<axsl:stylesheet>
<xsl:apply-templates/>
</axsl:stylesheet>
</xsl:template>
Any <axsl:...>
elements in the stylesheet will become <xsl:...>
in the output.