0

Im now to XSLT and I need to do some grouping with the value of a child. I have objects, that can have multiple properties and one of them (with id=11) is on I need to use as a grouping element. The amount of properties each object can have varies, but they all have the common prop.

Input:

<object id=1>
 <properties>
    <prop id=10>Name of object 1</prop>
    <prop id=11>Group 1</prop>
    <prop id=xy>Whatever properties this object has</prop>
 </properties>
</object>
<object id=2>
 <properties>
    <prop id=10>Name of object 2</prop>
    <prop id=11>Group 2</prop>
 </properties>
</object>
<object id=3>
 <properties>
    <prop id=10>Name of object 3</prop>
    <prop id=11>Group 1</prop>
 </properties>
</object>
<object id=4>
 <properties>
    <prop id=10>Name of object 4</prop>
    <prop id=11>Group 3</prop>
 </properties>
</object>

Desired output:

<group name='Group 1'>
  <object id=1>
    <prop id=10>Name of object 1</prop>
    <prop id=11>Group 1</prop>
    <prop id=xy>Whatever properties this object has</prop>
  </object>
<object id=3>
 <properties>
    <prop id=10>Name of object 3</prop>
    <prop id=11>Group 1</prop>
 </properties>
</object>
</group>
<group name='Group 2'>
  <object id=2>
   <properties>
    <prop id=10>Name of object 2</prop>
    <prop id=11>Group 2</prop>
   </properties>
  </object>
</group>
<group name='Group 3'>
  <object id=4>
   <properties>
    <prop id=10>Name of object 4</prop>
    <prop id=11>Group 3</prop>
   </properties>
  </object>
</group>

The idea is to have the items grouped by the value of the prop with id 11.

Ive found multiple different code samples, but none of them have had this specific case, and I havent been able to modify them to suit my need.

2
  • How about showing us what you have tried so far? Commented Jul 6, 2016 at 12:27
  • By the way, this is pretty much the same question as stackoverflow.com/questions/2291567/…. Commented Jul 6, 2016 at 13:22

2 Answers 2

2

My version of the xsl that is essentially that same as Michael Vehrs in that it is also using the Muenchian Method but thought I may as well post it to show a subtle alternative. Here I'm using an apply-templates instead of the for-each/call-template. In terms of performance there is probably nothing between them but personally, I prefer to use apply-templates wherever possible as it typically allows for more flexibility.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="no" encoding="utf-8"/>
<xsl:key name="groups" match="prop[@id='11']" use="text()"/>

<xsl:template match="/">
    <xsl:apply-templates select="//prop[generate-id()=generate-id(key('groups', text())[1])]"/>
</xsl:template>

<xsl:template match="prop">
    <group name="{text()}">
        <xsl:copy-of select="//object[properties/prop[@id='11']=current()/text()]"/>
    </group>
</xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

1 Comment

Apply-templates seems like the more straightforward option and this worked perfectly.
1

This is a basic application of the Muenchian Method (which is explained here, for example):

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

<xsl:key name="prop" match="//prop[@id='11']/text()" use="." />

<xsl:template match="/">
  <xsl:for-each select="//prop[@id='11']/text()[generate-id()
                        = generate-id(key('prop',.)[1])]">
    <xsl:call-template name="group">
      <xsl:with-param name="groupname" select="." />
    </xsl:call-template>
  </xsl:for-each>
</xsl:template>

<xsl:template name="group">
  <xsl:param name="groupname" />
  <group><xsl:attribute name="name"><xsl:value-of select='$groupname'/></xsl:attribute>
  <xsl:for-each select="//object[.//prop[@id='11'][text()=$groupname]]" >
    <xsl:copy-of select="." />
  </xsl:for-each>
  </group>
</xsl:template>

</xsl:stylesheet>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.