I have some XML that looks like this:
<root>
<message name="peter">
<field type="integer" name="pa" />
<group name="foo">
<field type="integer" name="action" />
<field type="integer" name="id" />
<field type="integer" name="value" />
</group>
</message>
<message name="wendy">
<field type="string" name="wa" />
<group name="foo">
<field type="integer" name="action" />
<field type="integer" name="id" />
<field type="integer" name="value" />
</group>
</message>
</root>
I have some XSL that I'm using to generate Java code from this XML. Previously I've been making a key, then generating a Java class for each group.
<xsl:key name="groupsByName" match="//group" use="@name"/>
....
<xsl:for-each select="//group[generate-id(.) = generate-id(key('groupsByName',@name)[1])]">
<xsl:call-template name="class-for-group"/>
</xsl:for-each>
All was well. Now, I've discovered that some messages have groups using the same name as groups present elsewhere, but missing one of the fields. To continue the example XML from above:
<message name="nana">
<field type="string" name="na" />
<group name="foo">
<field type="integer" name="id" />
<field type="integer" name="value" />
</group>
</message>
A group named "foo" is present, but it's missing the field with name "action".
What I'd like to do is to generate a Java class for each unique subtree. Is this possible? I can't work out what the xsl:key for that would look like. The closest idea I've had is
<xsl:key name="groupsKey" match="//group" use="concat(@name,count(*))"/>
which works for the case in the example above, but is hardly elegant. If there were instead two groups named "foo" with the same number (but different types) of fields, it would fail, so it's not actually a solution.
To be clear, the ideal key (or whatever alternative) would end up calling the template only once for the "peter" and "wendy" cases above, once for the "nana" case and again once for this case:
<message name="hook">
<field type="string" name="ha" />
<group name="foo">
<field type="string" name="favourite_breakfast" />
<field type="integer" name="id" />
<field type="integer" name="value" />
</group>
</message>
...because the fields within the group are different to those in the other cases. My key above doesn't cover this case. Is there a way to do so?