0

I want to find distinct values across each node. but when i use muenchian method it will select distinct values only at top level.

Currently i am getting output as:

Bag 20
Tray 30

But i want to group type and quantity for each item

<!--for 1st item-->
Bag 20
Tray 30
<!--for 2nd item-->
Bag 20
Box 20
Tray 30

I am doing some research to make it work but did not succeed.

XML:

<?xml version="1.0" encoding="UTF-8"?>
<Test>
<Items>
    <Item>
        <name>A</name>
        <type>Bag</type>
        <input quantity="20"/>
       
    </Item>
    <Item>
        <name>A</name>
        <type>Bag</type>
        <input quantity="20"/>
     
    </Item>
    <Item>
        <name>B</name>
        <type>Metal</type>
        <input quantity="20"/>
       
    </Item>
    <Item>
        <name>A</name>
        <type>Tray</type>
        <input quantity="30"/>
     
    </Item>
    
</Items>
<Items>
    <Item>
        <name>A</name>
        <type>Bag</type>
        <input quantity="20"/>
       
    </Item>
    <Item>
        <name>A</name>
        <type>Box</type>
        <input quantity="20"/>
     
    </Item>
    <Item>
        <name>B</name>
        <type>Metal</type>
        <input quantity="20"/>
       
    </Item>
    <Item>
        <name>A</name>
        <type>Tray</type>
        <input quantity="30"/>
     
    </Item>
    
</Items>
</Test>

Code:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:fo="http://www.w3.org/1999/XSL/Format"
   xmlns:date="http://exslt.org/dates-and-times"
    xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl"
    extension-element-prefixes="date"
    
    >
    
    <xsl:key name="item-key" match="Items/Item[name='A']" use="input/@quantity" /> 
    
    <xsl:template match="/" name="Barcode">
        
        <fo:root>
            <fo:layout-master-set>
                <fo:simple-page-master master-name="ManufacturLabelSize-first" page-height="297mm" page-width="210mm"  margin-top="25.4mm" margin-right="25.4mm" margin-left="25.4mm" margin-bottom="25.4mm">
                    <fo:region-body margin-top="15mm" />
                    <fo:region-before />
                    <fo:region-after />
                </fo:simple-page-master>
                <fo:simple-page-master master-name="ManufacturLabelSize-rest" page-height="297mm" page-width="210mm"   margin-top="25.4mm" margin-right="25.4mm" margin-left="25.4mm" margin-bottom="25.4mm">
                    <fo:region-body margin-top="15mm"/>
                    <fo:region-before />
                    <fo:region-after />
                </fo:simple-page-master>
                <fo:page-sequence-master master-name="ManufacturLabelSize-portrait">
                    <fo:repeatable-page-master-alternatives>
                        <fo:conditional-page-master-reference master-reference="ManufacturLabelSize-first" 
                            page-position="first"/>
                        <fo:conditional-page-master-reference master-reference="ManufacturLabelSize-rest" 
                            page-position="rest"/>
                    </fo:repeatable-page-master-alternatives>
                </fo:page-sequence-master>
            </fo:layout-master-set>
            
            <fo:page-sequence master-reference="ManufacturLabelSize-portrait" id="pSeqID">
                
                <fo:flow flow-name="xsl-region-body">
                    
                    <fo:table  >
                        
                        <fo:table-body border="solid" border-width="0.5pt">
                            <fo:table-row>
                                <fo:table-cell>
                                    
                                    <fo:block>
                                        
                                        <xsl:for-each select="Test">
                                            <xsl:for-each select="Items">
                                               
                                                <xsl:for-each select="Item[name='A'][count(. | key('item-key',input/@quantity)[1])=1]">
                                               
                                                <fo:block>
                                                    <xsl:value-of select="type"/> <fo:inline color="white">XXX</fo:inline><xsl:value-of select="input/@quantity"/>
                                                    
                                                </fo:block>
                                             </xsl:for-each> 
                                         </xsl:for-each> 
                                         
                                        </xsl:for-each>
                                    </fo:block>
                                    
                                </fo:table-cell>
                            </fo:table-row>
                        </fo:table-body>          
                    </fo:table> 
                </fo:flow>
            </fo:page-sequence>
        </fo:root>
        
    </xsl:template> 
    
</xsl:stylesheet>

Appreciate your help!

Akash
  • 33
  • 5

1 Answers1

0

If - as it seems - you want to find distinct Items whose name is A by their type separately for each Items, then you need to include the parent Items' id in the key. Here's a simplified example:

XSLT 1.0

<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 name="k" match="Item[name='A']" use="concat(type, '|', generate-id(..))"/>

<xsl:template match="/Test">
    <root>
        <xsl:for-each select="Items">
            <xsl:comment>
                <xsl:value-of select="position()" />
            </xsl:comment>
            <xsl:for-each select="Item[name='A'][count(. | key('k', concat(type, '|', generate-id(..)))[1]) = 1]">
                <item>
                    <type>
                        <xsl:value-of select="type"/>
                    </type>
                    <quantity>
                        <xsl:value-of select="input/@quantity"/>
                    </quantity>
                </item>
            </xsl:for-each>
        </xsl:for-each>
    </root>
</xsl:template>

</xsl:stylesheet>

Applied to your input example, the result will be:

Result

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <!--1-->
  <item>
    <type>Bag</type>
    <quantity>20</quantity>
  </item>
  <item>
    <type>Tray</type>
    <quantity>30</quantity>
  </item>
  <!--2-->
  <item>
    <type>Bag</type>
    <quantity>20</quantity>
  </item>
  <item>
    <type>Box</type>
    <quantity>20</quantity>
  </item>
  <item>
    <type>Tray</type>
    <quantity>30</quantity>
  </item>
</root>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Hi, i used same key within my code. But i am still getting old output. – Akash Nov 07 '21 at 16:44
  • I need to group wrt to quantity and type for name='A'. In second line quantity is 20 for both box and bag. So when i group with quantity it is 20 and it has two different type. So that also needs to get split – Akash Nov 07 '21 at 16:58
  • Sorry, I do not understand your requirement. If you want to group by both type AND quantity, then add quantity to the key. If you want something else, then clarify. Your example is ambiguous because it does not have two items with the same type but different quantity. – michael.hor257k Nov 07 '21 at 17:07
  • My bad i did not provide the correct XML. But I'm glad it helped me solve my issue by grouping quantity wise. Grouping was taking for only one line item but now it runs for all the nodes. Thank you very much for your time and help!! – Akash Nov 10 '21 at 11:15