0

Ok I am trying to build a table, But I'm not doing this correctly, I have no XSL example as nothing I tried came close to what I need. (I have tried using xsl:apply-templates loops, even with modes, and even xsl:for-each and key() but cannot get the right filters.

Here is an example of the XML I would be using. (the real xml I am using is more complex then this one below)

<report>
 <item>
  <vertical>
   <component>
    <partname>Left Side</partname>
    <parttype>Side</parttype>
    <partlocation>Outside</partlocation>
    <material>Wood</material>
    <thickness>20mm</thickness>
    <colour>White</colour>
   </component>
  </vertical>
  <vertical>
   <component>
    <partname>Right Side</partname>
    <parttype>Side</parttype>
    <partlocation>Outside</partlocation>
    <material>Wood</material>
    <thickness>20mm</thickness>
    <colour>White</colour>
   </component>
  </vertical>
  <vertical>
   <component>
    <partname>Back</partname>
    <parttype>Back</parttype>
    <partlocation>Inside</partlocation>
    <material>Plastic</material>
    <thickness>3mm</thickness>
    <colour>Black</colour>
   </component>
  </vertical>
 </item>
</report>

So the task I am wanting to do is, for-each <item> I need to start making a table, and inside that table I need to assess each <component> to find how many have the same <material>, <thickness> and <colour>. Then I need to list the Material name and details. Next I need all the <components> that have the same <parttypes> and <partlocation> that are of the same <material>, <thickness> and <colour>, to show their <partname> in a row for each one. There is no fixed amount of materials I can expect, one time I might get 1, another time I could get 3. And I wont always know what values the nodes will contain. Also in each <item> I can have 1-3 different <parttype> and <partlocation> (althought they work in pairs - and I know what the values of those nodes will be)

Here is a sample of the formatted finish given the really simple above code...

Wood, 20mm, White
Left Side
Right Side

Plastic, 3mm, Black
Back

this question is VERY similar, but not quite... xsl grouping of repetitive nodes by xml element in xslt1

Community
  • 1
  • 1

1 Answers1

1

You may try to use this key based solution as a first idea:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" />
    <!-- Define keys -->
    <xsl:key name="kmaterial" match="component" 
             use="concat (generate-id(../..), '|', material, '|', thickness, '|', colour)"/>
    <xsl:template match="text()" />
    <xsl:template match="item">
        <xsl:for-each 
               select="vertical/component[
                    generate-id(.) = 
                    generate-id(key('kmaterial',   concat (generate-id(../..), '|', material, '|', thickness, '|', colour) )[1])  ]">

            <xsl:variable name="this" select="."/>
            <xsl:value-of select="material"/>, <xsl:value-of select="thickness"/> , <xsl:value-of select="colour"/>
            <xsl:text>&#10;</xsl:text>
            <xsl:for-each
                         select="key('kmaterial',   concat (generate-id(../..), '|', $this/material, '|', $this/thickness, '|', $this/colour) )" >
                <xsl:value-of select="partname"/>
                <xsl:text>&#10;</xsl:text>
            </xsl:for-each>

        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

With the following output:

Wood, 20mm , White
Left Side
Right Side
Plastic, 3mm , Black
Back
hr_117
  • 9,589
  • 1
  • 18
  • 23
  • Thanks for the input hr_117, I have been playing around with this suggestion in my actual file to see if I can make it do what is required, but I fear it might only be half of the task. – Alistair Lindsay-Macfadyen Apr 08 '16 at 06:39
  • To group also (next step) by `parttypes` and `partlocation` you need to have a second key( e.g. kmaterialpart) . This should be same as `kmaterial` extended by `'|', parttypes '|', partlocation` – hr_117 Apr 08 '16 at 10:30
  • I have finally had a very close look at this and after a bit of mixing around to make it work in my actual project, the first stage of this answer has definitely solved my dilemma's, I have always had trouble with Key() and trying to understand it a little better. Thanks @hr_117 – Alistair Lindsay-Macfadyen Jul 11 '16 at 22:58