[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] for-each(-group) - flattening a set of strings hierarchy


Subject: Re: [xsl] for-each(-group) - flattening a set of strings hierarchy
From: Andrew Welch <andrew.j.welch@xxxxxxxxx>
Date: Fri, 23 Jan 2009 10:04:08 +0000

2009/1/23 Robert Koberg <rob@xxxxxxxxxx>:
> Hi, (didn't really know how to phrase the subject... :) )
>
> Given an XML instance like:
>
> <q>
>  <a>
>    <mapping resource="a/b/A.xml"/>
>    <mapping resource="a/b/B.xml"/>
>    <mapping resource="a/b/c/A.xml"/>
>    <mapping resource="a/b/c/B.xml"/>
>    <mapping resource="d/e/A.xml"/>
>    <mapping resource="d/e/B.xml"/>
>  </a>
> </q>
>
> I want to get output as (javascript namespaces):
>
> var a = {};
> a.b = {};
> a.b.c = {};
>
> var d = {};
> d.e = {};
>
> I am clumsily getting about half of the way there, but I feel like I am
> approaching it wrong. I am imagining a bunch of for loops.
>

Hi Rob,

I'd be tempted to converted

   <mapping resource="a/b/A.xml"/>
   <mapping resource="a/b/B.xml"/>
   <mapping resource="a/b/c/A.xml"/>
   <mapping resource="a/b/c/B.xml"/>

into (something like)

<a>
  <b>
    <c/>
  </b>
</a>

...and then it's straight forward to work out

a
a.b
a.b.c

Easier to debug and maintain etc

To do the grouping part you could use:


<xsl:call-template name="grouper">
  <xsl:with-param name="seq" select="//@resource"/>	
  <xsl:with-param name="pos" select="1"/>
</xsl:call-template>


<xsl:template name="grouper">
	<xsl:param name="seq"/>
	<xsl:param name="pos"/>
	<xsl:for-each-group select="for $x in $seq return tokenize($x,
'/')[$pos][not(contains(., '.xml'))]" group-by=".">
		<xsl:element name="{.}">
			<xsl:call-template name="grouper">
			  <xsl:with-param name="seq" select="$seq"/>	
			  <xsl:with-param name="pos" select="$pos + 1"/>				
			</xsl:call-template>
		</xsl:element>	
	</xsl:for-each-group>	
</xsl:template>


cheers
-- 
Andrew Welch
http://andrewjwelch.com
Kernow: http://kernowforsaxon.sf.net/


Current Thread
Keywords
xml