1

I have the following simplified XML data and I want to group it by the Category ID and see if there's any similar records in the payload, if so I want to join the condition with the found element.

<Items>
   <result>
      <id>11</id>
      <name>ABC</name>
      <condition>new</condition>
   </result>
   <result>
      <id>22</id>
      <name>XYZ</name>
      <condition>new</condition>
   </result>
   <result>
      <id>11</id>
      <name>ABC</name>
      <condition>used</condition>
   </result>
   <result>
      <id>33</id>
      <name>PQR</name>
      <condition>used</condition>
   </result>
</Items>

Expected Result After Grouping:

<Items>
   <result>
      <id>11</id>
      <name>ABC</name>
      <condition>new,used</condition>
   </result>
   <result>
      <id>22</id>
      <name>XYZ</name>
      <condition>new</condition>
   </result>
   <result>
      <id>11</id>
      <name>ABC</name>
      <condition>new,used</condition>
   </result>
   <result>
      <id>33</id>
      <name>PQR</name>
      <condition>used</condition>
   </result>
</Items>

How can I do this in XSLT 1.0 for a large payload where multiple similar records are exists? Is it doable using grouping method?

Current Logic:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sdml="http://selfhtml.org/sdml">
 <xsl:template match="/Items">
    <xsl:copy>
        <xsl:for-each-group select="result" group-by="id"> 
            <records type="{current-grouping-key()}" >
                <xsl:apply-templates select="current-group()" />
            </records>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
        <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet>

Current Response:

"@type": "11",
"$": "11ABC<itemdescription>.new11ABC<itemdescription>.used"

Edit1: Response added
Edit2: Typo Edited

Rooster
  • 157
  • 2
  • 9
  • 1
    So you have managed to use the tag for XSLT 1.0's grouping technique Muenchian grouping but you can't apply any tutorial like http://www.jenitennison.com/xslt/grouping/muenchian.html to your own data? – Martin Honnen May 19 '20 at 13:31
  • I did my research on Muenchian grouping, and followed other similar questions, which i figured out this could be done using Muenchian grouping, however i was unable to successfully implement it. Thus I post for some help. Thank you for the reference. :) – Rooster May 19 '20 at 13:53
  • So which key did you try to define if you tried to use Muechian grouping? How does your XSLT 1 attempt look? Which wrong result or which error do you get? – Martin Honnen May 19 '20 at 13:55
  • Thanks for writing back. I'm getting the following output, I've edited it to be smaller. `"@type": "11", "$": "11ABC.new66711ABC.used824"` It groups the items, but everything as a chunk. – Rooster May 19 '20 at 14:03
  • Please edit your question with the results you get. And your XSLT snippet uses the XSLT 2/3 only `xsl:for-each-group` instruction, thus, if you really need to use an XSLT 1.0 processor and Muenchian grouping, the first step is not to use XSLT 2 but rather Muenchian grouping. – Martin Honnen May 19 '20 at 14:13
  • ohh, thank you for pointing into the right direction, I started using XSLT recently as you can see. I just find my way through reading contents. Appreciate your time on this. I will post – Rooster May 19 '20 at 14:18
  • Please post your current attempt so that we can fix it, instead of having to write your code for you from scratch. -- Note also that your expected output is identical to the input. – michael.hor257k May 19 '20 at 14:28
  • 1
    I can't make sense of your sample data, the input has two `result` elements with `22`, the wanted output only one, without any grouping or merging of the conditions from the input. And where does the `33` in the result come from? – Martin Honnen May 19 '20 at 14:29
  • @michael.hor257k - That's what I thought originally, but a couple of the `condition` values are different. Also, the last `result` element is different, but I think it might be because of a typo in the input example. – Daniel Haley May 19 '20 at 14:30
  • @DanielHaley Kudos for your sharp eye. So it's even worse than that. – michael.hor257k May 19 '20 at 14:33
  • Oh no no, let me. I want to get the elements with same id `11`, and contact their `new`, thus in the response, it should be `new,used`, for the id's with `11` only. – Rooster May 19 '20 at 14:36

1 Answers1

0

As you only want to merge the condition data but keep the separate result elements and also only want to identify the group for a certain id you could use

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

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:key name="result-group" match="result[id = 11]/condition" use="../id"/>

  <xsl:template match="result[id = 11]/condition">
      <xsl:copy>
          <xsl:for-each select="key('result-group', ../id)">
              <xsl:if test="position() > 1">,</xsl:if>
              <xsl:value-of select="."/>
          </xsl:for-each>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/3MvmXj1

In XSLT 2 or 3 you can use a variable in the key and template match pattern: https://xsltfiddle.liberty-development.net/a9GPfY

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • Thank you for your time @Martin, really appreciate it. I tried your solution, but it still not append the `new,used`. "Items": { "result": [ { "id": 11, "name": "ABC", "description": ".", "condition": [ "new" ] } I have changed the `match="result[id = '11']/condition" ` to get whatever the id in result/id. – Rooster May 19 '20 at 15:21
  • Thank you very much. I finally able to manipulate it to my use-case, and it worked beautifully. Thanks for the guidance as well. Appreciate it. – Rooster May 19 '20 at 15:41