Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

XSLT to group similar elements?

Status
Not open for further replies.

capitano

Programmer
Jul 30, 2001
88
US
I have a pile of XML like the below. What I want to do is group all the <li> elements together under a new parent, call it <ul>. I am trying to find a way to do this with XSLT, but am having problems. It seems like XSLT would be a perfect candidate for such a re-grouping of elements, but I can't figure it out. Thanks for any help!

<root>
<first>
<description>A list of trees follows</description>
<li>Fir</li>
<li>Maple</li>
<li>Pine</li>
</first>
<second>
<description>A list of cars follows</description>
<li>Mazda</li>
<li>Honda</li>
<li>Toyota</li>
</second>
</root>

I have tried using the XSLT Axis notation &quot;following-sibling&quot;, but this doesn't produce the results I'm hoping for. I have tried this:

<?xml version=&quot;1.0&quot;?>
<xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot; <xsl:eek:utput method=&quot;xml&quot; indent=&quot;yes&quot; />

<xsl:template match=&quot;/ | * | @*&quot;>
<xsl:copy>
<xsl:apply-templates select=&quot;* | @* | text()&quot;/>
</xsl:copy>
</xsl:template>

<xsl:template match=&quot;li&quot;>
<ul>
<xsl:for-each match=&quot;./following-sibling::li&quot;>
<li><xsl:value-of select=&quot;.&quot;/>
</xsl:for-each>
</ul>
</xsl:template>

The above XSLT seems to group all the <li> elements throughout the entire XML document indiscriminantly. I'm really struggling with this. Any ideas? Thanks!
 
Code:
<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?>
<xsl:stylesheet
	xmlns:xsl=&quot;[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform&quot;[/URL]
	version=&quot;1.0&quot;>

<xsl:template match=&quot;li&quot;>
<li>
        <xsl:value-of select=&quot;.&quot;/>
</li>
</xsl:template>

<xsl:template match=&quot;/&quot;>
<ul>
	<xsl:apply-templates select=&quot;//li&quot; />
</ul>
</xsl:template>
</xsl:stylesheet>

-pete
 
Thanks. After implementing your suggestion, I get the following:

<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?>
<ul>
<li>Fir</li>
<li>Maple</li>
<li>Pine</li>
<li>Mazda</li>
<li>Honda</li>
<li>Toyota</li>
</ul>

In fact, what I was hoping for was:

<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?>
<root>
<first>
<description>A list of trees follows</description>
<ul>
<li>Fir</li>
<li>Maple</li>
<li>Pine</li>
</ul>
</first>
<second>
<description>A list of cars follows</description>
<ul>
<li>Mazda</li>
<li>Honda</li>
<li>Toyota</li>
</ul>
</second>
</root>

So... any other ideas? Thanks for the help so far. I feel a solution must close by!
 
>> Thanks. After implementing your suggestion, I get the following:

Yep. Sorry i didn't understand what your goal was. [sadeyes]

-pete
 
Code:
<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?>
<xsl:stylesheet
	xmlns:xsl=&quot;[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform&quot;[/URL]
	version=&quot;1.0&quot;>
	
<xsl:output omit-xml-declaration=&quot;no&quot;
             method=&quot;html&quot;
             doctype-public=&quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;
             doctype-system=&quot;[URL unfurl="true"]http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;[/URL]
	     indent=&quot;no&quot; encoding=&quot;UTF-8&quot; />

<xsl:template match=&quot;li&quot;>
	<xsl:copy-of select=&quot;.&quot; />
</xsl:template>

<xsl:template match=&quot;description&quot;>
	<xsl:copy-of select=&quot;.&quot; />
</xsl:template>

<xsl:template match=&quot;*&quot;>
	<xsl:copy>
	<xsl:apply-templates select=&quot;description&quot; />
	<ul>
	<xsl:apply-templates select=&quot;li&quot; />
	</ul>
	</xsl:copy>
</xsl:template>

<xsl:template match=&quot;/&quot;>
	<xsl:apply-templates select=&quot;root/*&quot; />
</xsl:template>
</xsl:stylesheet>

-pete
 
Perfect example and a solution. I have a similar problem - suppose that I have the following xml file and the result should be the second one. Is this possible in xslt (grouping similar elemets if they have the same attribute name value.

<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?>
<body>
<li name='one'>Fir</li>
<li name='one'>Map</li>
<li name='two'>Pine</li>
<li name='two'>Mazda</li>
<li name='one'>Honda</li>
<li name='tree'>Toyota</li>
</body>


output as:

<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?>
<body>
<ul>
<li>Fir</li>
<li>Map</li>
<li>Honda</li>
</ul>
<ul>
<li>Pine</li>
<li>Mazda</li>
</ul>
<ul>
<li>Toyota</li>
</ul>
</body>
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top