[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
Re: [xsl] converting attributes to nested tags recursively
Subject: Re: [xsl] converting attributes to nested tags recursively From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Thu, 7 Feb 2002 10:49:23 +0000 |
Hi Edward, > I have a file like the following > <tagA attribreq="attribreqvalue1" attrib1="fds" attrib2="hdg"> > <TagB>Text1</TabB> > <tagA attribreq="attribreqvalue1" attrib1="fds" attrib2="hdg"> > </tagA> I'll assume you meant some well-formed XML like: <tagA attribreq="attribreqvalue1" attrib1="fds" attrib2="hdg"> <TagB>Text1</TagB> <tagA attribreq="attribreqvalue1" attrib1="fds" attrib2="hdg" /> </tagA> > And I am trying to convert it to the following > <attribreq attrib="attribreqvalue1"> > <tag name="attrib1" value="fds"> > <tag name="attrib2" value="hdg"> > <tagB>Text1</tagB> > </tag> > </tag> > </attribreq> > <attribreq attrib="attribreqvalue1"> > <tag name="attrib1" value="fds"> > <tag name="attrib2" value="hdg"/> > </tag> > </attribreq> Hmm... OK, one thing that you should be aware of is that attribute order is not retained in an XPath node tree. So the fact that attrib1 comes before attrib2 in the tagA start tag in your example doesn't mean that the attrib1 attribute node comes before the attrib2 attribute node in the XPath node tree. I'll assume that you don't care about the ordering in which the tag elements are nested inside each other, as it makes things simpler. To get the attribreq elements at the top level, you need to apply templates to all the attribreq attributes in the document: <xsl:apply-templates select="//@attribreq" /> and have a template that matches attribreq attributes and generates the equivalent attribreq element: <xsl:template match="@attribreq"> <attribreq attrib="{.}"> ... </attribreq> </xsl:template> Within the attribreq, you to call a recursive template that takes a node set of attributes and works through them one by one to build up the tag element hierarchy. I'll call this template 'createTag'. The attributes that need to be passed are the attributes other than the attribreq attribute on the current attribreq attribute's parent element: <xsl:template match="@attribreq"> <attribreq attrib="{.}"> <xsl:call-template name="createTag"> <xsl:with-param name="attributes" select="../@*[name() != 'attribreq']" /> </xsl:call-template> </attribreq> </xsl:template> The createTag template itself needs to check whether it has received any attributes at all. If it hasn't, then it needs to copy any TagB elements in the content of the current node's parent element (the current node is still an attribreq attribute): <xsl:template name="createTag"> <xsl:param name="attributes" select="/.." /> <xsl:choose> <xsl:when test="$attributes"> ... </xsl:when> <xsl:otherwise> <xsl:copy-of select="../TagB" /> </xsl:otherwise> </xsl:choose> </xsl:template> [Note I'm assuming that you didn't mean to change the case on the name of TagB in the result. If you did, you could apply templates to TagB instead of copying it directly, and have a template that creates a tagB element for it.] If there are attributes in the $attributes parameter, then it needs to take the first of these attributes to create a tag element. The content of the tag element is formed by calling the createTag template again, this time with the $attributes parameter being all the attributes aside from the first one: <xsl:template name="createTag"> <xsl:param name="attributes" select="/.." /> <xsl:choose> <xsl:when test="$attributes"> <xsl:variable name="first" select="$attributes[1]" /> <xsl:variable name="rest" select="$attributes[position() > 1]" /> <tag name="{name($first)}" value="{$first}"> <xsl:call-template name="createTag"> <xsl:with-param name="attributes" select="$rest" /> </xsl:call-template> </tag> </xsl:when> <xsl:otherwise> <xsl:copy-of select="../TagB" /> </xsl:otherwise> </xsl:choose> </xsl:template> Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] converting attributes to nest, Edward . Middleton | Thread | [xsl] In XSL how do you group commo, Su Dh |
RE: [xsl] tag minimisation, Andrew Welch | Date | Re: [xsl] [solved] key with many us, Jeni Tennison |
Month |