My xml looks something like this:

<Staff>
     <Row alphakey="doejohn" building="abc" class="Algebra" />
     <Row alphakey="doejohn" building="abc" class="Geometry" />
     <Row alphakey="personbob" building="abc" class="Calculus" />
     <Row alphakey="personbob" building="abc" class="Precalc" />
...
</Staff>

And basically I need it to output like this:

Alphakey       Classes
doejohn        Algebra, Geometry
personbob      Calculus, Precalc

I've searched for how to do this with a merge, but I can't quite figure it out, and most examples look different from what I am trying to do. Can someone help me with this?

Dani AI

Generated

Brief recap: wants each unique alphakey to show the list of class values from the Row elements. asked about XSLT versions and correctly pointed out grouping (Muenchian grouping is the common XSLT 1.0 approach). If you prefer doing this in Python (often simpler when you just want a small transformation), the snippet below reads the XML, preserves the original order of the keys, and deduplicates class names while keeping their document order.

from __future__ import print_function
import xml.etree.ElementTree as ET
from collections import OrderedDict

tree = ET.parse('staff.xml')
root = tree.getroot()

groups = OrderedDict()
for row in root.findall('.//Row'):
    key = row.get('alphakey')
    cls = row.get('class')
    if not key or not cls:
        continue
    if key not in groups:
        groups[key] = []
    if cls not in groups[key]:
        groups[key].append(cls)

for key, classes in groups.items():
    print("{}\t{}".format(key, ", ".join(classes)))

Notes and troubleshooting: use iterparse() if the file is very large to avoid loading everything into memory; if class names may contain commas, emit CSV using the csv module instead of naive joining so values are quoted correctly; if you need deterministic sorting rather than original document order, iterate sorted(groups.items()). For pure XSLT: stick with Muenchian grouping in XSLT 1.0 as suggested; in XSLT 2.0 xsl:for-each-group makes the same job much simpler.

Recommended Answers

All 3 Replies

Are you using XSLT 1.0 or XSLT 2.0 ?

1.0

It's a gouping problem.
In XSLT 1.0 we have to use muench method

First step : eliminate double
second step : call all element with same "key" value

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
	<xsl:key match="Row" use="@alphakey" name="row"></xsl:key>
	<xsl:template match="/">
	<table>
		<tbody>
			<xsl:for-each select="/*/Row[generate-id(.)=generate-id(key('row',@alphakey)[1])]"><tr>
				<td><xsl:value-of select="@alphakey"></xsl:value-of></td><td><xsl:apply-templates select="key('row',@alphakey)"></xsl:apply-templates></td>
			</tr></xsl:for-each>
		</tbody>
	</table>
	</xsl:template>
	<xsl:template match="Row">
	<xsl:value-of select="@class"></xsl:value-of>;
	</xsl:template>
</xsl:stylesheet>
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.