Re: [xsl] This could be simple, but not for me!

Subject: Re: [xsl] This could be simple, but not for me!
From: "Kenny Bogoe (BogoeMD)" <kenny@xxxxxxxxx>
Date: Tue, 25 May 2004 20:05:54 +0200
Andrew, thanks again. You are right, there is just one <City> per
<Community> but I did not manage to get the right result with the modified
stylesheet. 

Here is the source again, now with two identical <Detail no> for City1:

<Root>
    <Community>
        <City>City1</City>
        <A>
            <B>
                <Name>Name1</Name>
                <Info>
                    <Detail no="100">Red</Detail>
                </Info>
            </B>
            <B>
                <Name>Name2</Name>
                <Info>
                    <Detail no="200">Blue</Detail>
                </Info>
            </B>
            <B>
                <Name>Name3</Name>
                <Info>
                    <Detail no="300">Green</Detail>
                </Info>
            </B>
             <B>
                <Name>Name7</Name>  <-----one more no="300" for City1
                <Info>
                    <Detail no="300">Green</Detail>
                </Info>
            </B>
        </A>
    </Community>
    <Community>
        <City>City2</City>
        <A>
            <B>
                <Name>Name4</Name>
                <Info>
                    <Detail no="100">Red</Detail>
                </Info>
            </B>
            <B>
                <Name>Name5</Name>
                <Info>
                    <Detail no="200">Blue</Detail>
                </Info>
            </B>
            <B>
                <Name>Name6</Name>
                <Info>
                    <Detail no="400">Yellow</Detail>
                </Info>
            </B>
        </A>
    </Community>
</Root>


...and this is the stylesheet:

<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:key name="details" match="Detail" use="concat(@no,'/',.)"/>
<xsl:key name="cities" match="City" use="."/>


<xsl:output method='html' version='1.0' encoding='iso-8859-1' indent='no'/>


<xsl:template match="/">
  <root>
    <xsl:apply-templates select="//Detail[generate-id() =
generate-id(key('details',concat(@no,'/',.))[1])]"/>
  </root>
</xsl:template>

<xsl:template match="Detail">
  <div detail="{concat(@no,', ',.)}">
    <xsl:for-each select="key('details',concat(@no,'/',.))">
      <span>

<xsl:if test="generate-id(ancestor::Community/City) =
generate-id(key('cities',ancestor::Community/City)[1])">
        <xsl:value-of select="ancestor::Community/City"/>,<xsl:text/>
</xsl:if>
        <xsl:value-of select="parent::Info/preceding-sibling::Name"/>
      </span>
  </xsl:for-each>
  </div>
</xsl:template>


</xsl:stylesheet>


...and this is the result I get:

<root>
    <div detail="100, Red">
        <span>City1,Name1</span>
        <span>City2,Name4</span>
    </div>
    <div detail="200, Blue">
        <span>City1,Name2</span>
        <span>City2,Name5</span>
    </div>
    <div detail="300, Green">
        <span>City1,Name3</span>
        <span>City1,Name7</span>
    </div>
    <div detail="400, Yellow">
        <span>City2,Name6</span>
    </div>
</root>


...and finally this is the result I need:

<root>
    <div detail="100, Red">
        <span>City1</span>
        <span>Name1</span>
        <span>City2</span>
        <span>Name4</span>
    </div>
    <div detail="200, Blue">
        <span>City1</span>
        <span>Name2</span>
        <span>City2</span>
        <span>Name5</span>
    </div>
    <div detail="300, Green">
        <span>City1</span>      <----- only one City
        <span>Name3</span>
        <span>Name7</span>
    </div>
    <div detail="400, Yellow">
        <span>City2</span>
        <span>Name6</span>
    </div>
</root>


Is there still hope?
Kenny



> 
>> Thanks, Andrew
>> 
>> This is very very close to what I need. But the city name has
>> to be there only once for all names like:
>> 
>> 
>> 100, Red
>>     City1
>>         Name1
>>         Name10
>>         Name100
>>         ...etc
>> 
>>     City2
>>         Name4
>>         Name40
>>         ...
>> 
>> 200, Blue
>>     City1
>>         Name2
>>         Name20
>>         ...
>> 
>>     City2
>>         Name5
>>         ...
>> 
>> 300, Green
>>     City1
>>         Name3
>>         Name30
>>         Name300
>>         Name3000
>>         ...
>> 
>> 400, Yellow
>>     City2
>>         Name6
>>         ...
>> 
>> Is that possible as well?
> 
> 
> Sure, just add an extra key and an if test around the value-of to check
> if it's the first occurance of that value:
> 
> <xsl:key name="cities" match="City" use="."/>
> 
> and the if test:
> 
> <xsl:if test="generate-id(ancestor::Community/City) =
> generate-id(key('cities',ancestor::Community/City)[1])">
> <span><xsl:value-of select="ancestor::Community/City"/></span>
> </xsl:if>
> 
> Now, this might fail at the moment because I'm guessing at the structure
> of your xml, if its anything other that one <City> per <Community> then
> you will need to adjust it.
> 
> cheers
> andrew

Current Thread