1 <?xml version="1.0"?> 2 <xsl:stylesheet version="1.0" 3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4 xmlns:template="http://www.boddie.org.uk/ns/xmltools/template"> 5 6 <xsl:output indent="yes"/> 7 8 9 10 <!-- Match the document itself. --> 11 12 <xsl:template match="/"> 13 14 <!-- Process the elements. --> 15 <xsl:apply-templates select="*"/> 16 17 </xsl:template> 18 19 20 21 <!-- Match element references. --> 22 23 <xsl:template match="*[@template:element]"> 24 <xsl:call-template name="enter-element"> 25 <xsl:with-param name="other-elements" select="@template:element"/> 26 </xsl:call-template> 27 </xsl:template> 28 29 <xsl:template name="enter-element"> 30 <xsl:param name="other-elements"/> 31 <xsl:variable name="first-element" select="substring-before($other-elements, ',')"/> 32 <xsl:variable name="remaining-elements" select="substring-after($other-elements, ',')"/> 33 <xsl:choose> 34 <xsl:when test="$first-element = ''"> 35 <xsl:call-template name="next-element"> 36 <xsl:with-param name="first-element" select="$other-elements"/> 37 </xsl:call-template> 38 </xsl:when> 39 <xsl:otherwise> 40 <xsl:call-template name="next-element"> 41 <xsl:with-param name="first-element" select="$first-element"/> 42 <xsl:with-param name="remaining-elements" select="$remaining-elements"/> 43 </xsl:call-template> 44 </xsl:otherwise> 45 </xsl:choose> 46 </xsl:template> 47 48 <xsl:template name="next-element"> 49 <xsl:param name="first-element"/> 50 <xsl:param name="remaining-elements"/> 51 <element> 52 <xsl:attribute name="name"><xsl:value-of select="$first-element"/></xsl:attribute> 53 <xsl:if test="@template:expr"> 54 <xsl:attribute name="expr"><xsl:value-of select="@template:expr"/></xsl:attribute> 55 </xsl:if> 56 <xsl:choose> 57 <xsl:when test="$remaining-elements = ''"> 58 <xsl:call-template name="enter-attribute"/> 59 </xsl:when> 60 <xsl:otherwise> 61 <xsl:call-template name="enter-element"> 62 <xsl:with-param name="other-elements" select="$remaining-elements"/> 63 </xsl:call-template> 64 </xsl:otherwise> 65 </xsl:choose> 66 </element> 67 </xsl:template> 68 69 70 71 <!-- Match attributes. --> 72 73 <xsl:template match="*[not(@template:element) and (@template:attribute or @template:expr-attr)]"> 74 <xsl:call-template name="enter-attribute"/> 75 </xsl:template> 76 77 <xsl:template name="enter-attribute"> 78 <xsl:choose> 79 <xsl:when test="@template:attribute"> 80 <attribute> 81 <xsl:attribute name="name"><xsl:value-of select="@template:attribute"/></xsl:attribute> 82 </attribute> 83 </xsl:when> 84 <xsl:otherwise> 85 <xsl:if test="@template:expr-attr"> 86 <xsl:attribute name="expr-attr"><xsl:value-of select="@template:expr-attr"/></xsl:attribute> 87 </xsl:if> 88 <xsl:if test="@template:expr"> 89 <xsl:attribute name="expr"><xsl:value-of select="@template:expr"/></xsl:attribute> 90 </xsl:if> 91 <xsl:if test="@template:value"> 92 <xsl:attribute name="value"><xsl:value-of select="@template:value"/></xsl:attribute> 93 </xsl:if> 94 <xsl:apply-templates select="*"/> 95 </xsl:otherwise> 96 </xsl:choose> 97 </xsl:template> 98 99 100 101 <!-- Traverse unknown elements. --> 102 103 <xsl:template match="*"> 104 <xsl:apply-templates select="*"/> 105 </xsl:template> 106 107 </xsl:stylesheet>