Search code examples
xmlxsltgroupingunique-values

Ignore repeating values xml 1.0


<?xml version="1.0" encoding="utf-8"?>
<order>
<press_mow>
  <mow_section_id>1</mow_section_id>
    <mow_webs>
        <mow_web>
            <web_number>1</web_number>
        </mow_web>
    </mow_webs>
</press_mow>
<press_mow>
  <mow_section_id>1</mow_section_id>
    <mow_webs>
        <mow_web>
            <web_number>1</web_number>
        </mow_web>
    </mow_webs>
</press_mow>
<press_mow>
  <mow_section_id>2</mow_section_id>
    <mow_webs>
        <mow_web>
            <web_number>1</web_number>
        </mow_web>
       <mow_web>
            <web_number>2</web_number>
        </mow_web>
       <mow_web>
            <web_number>2</web_number>
        </mow_web>
        <mow_web>
            <web_number>3</web_number>
        </mow_web>
        <mow_web>
            <web_number>3</web_number>
        </mow_web>
    </mow_webs>
</press_mow>
<press_mow>
  <mow_section_id>2</mow_section_id>
    <mow_webs>
        <mow_web>
            <web_number>1</web_number>
        </mow_web>
       <mow_web>
            <web_number>2</web_number>
        </mow_web>
       <mow_web>
            <web_number>2</web_number>
        </mow_web>
        <mow_web>
            <web_number>3</web_number>
        </mow_web>
        <mow_web>
            <web_number>3</web_number>
        </mow_web>
    </mow_webs>
</press_mow>
<press_mow>
  <mow_section_id>2</mow_section_id>
    <mow_webs>
        <mow_web>
            <web_number>1</web_number>
        </mow_web>
       <mow_web>
            <web_number>2</web_number>
        </mow_web>
       <mow_web>
            <web_number>2</web_number>
        </mow_web>
        <mow_web>
            <web_number>3</web_number>
        </mow_web>
        <mow_web>
            <web_number>3</web_number>
        </mow_web>
    </mow_webs>
</press_mow>

</order>

Trying to create a list of unique mow_webs/mow_web/web_number using menchian grouping however within each press_mow I either get only get 123 once or all numbers within each press_mow unable to see what Im doing wrong any help greatly appreciated.

Desired output

1 = 1
1 = 1
2 = 1,2,3
2 = 1,2,3
2 = 1,2,3

Have spent hours looking at all the explanations of this method and have previously used to good effect but cannot see what my error is on this occasion. Have tried two different methods below. Can only use xml 1.0. This is my first post apologies in advance if I have made an error.

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

<xsl:output method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>

<xsl:key name="webnoB" match="mow_web" use="web_number" />
<xsl:key name="webnoC" match="mow_webs" use="mow_web/web_number" />
<xsl:template match="order">

******TESTING HERE********

<xsl:for-each select="press_mow">
    SecIdA:<xsl:value-of select="mow_section_id"/>/
    <xsl:for-each select="mow_webs">
        <xsl:for-each select="mow_web[count(. | key('webnoB', web_number)           [1]) = 1]">
            WebNoA:<xsl:value-of select="web_number"/>
        </xsl:for-each>
    </xsl:for-each>
</xsl:for-each>
**************
<xsl:for-each select="press_mow[count(. | key('webnoC', web_number)[1]) = 1]">
    secidB:<xsl:value-of select="mow_section_id"/>/
    <xsl:for-each select="mow_webs">
        <xsl:for-each select="mow_web">
            WebNo.B:<xsl:value-of select="web_number"/>
        </xsl:for-each>
    </xsl:for-each>
</xsl:for-each>
******TESTING HERE********

</xsl:template>

Solution

  • If - as it seems - you want to list the distinct web_number values within each press_mow, you must include a press_mow identifier in the key definition and usage.

    And since your input has no unique values identifying the press_mow nodes, you will need to use the generate-id() function for this.

    Consider the following stylesheet:

    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="wn" match="mow_web" use="concat(web_number, '|', generate-id(ancestor::press_mow))" />
    
    <xsl:template match="/order">
        <root>
            <xsl:for-each select="press_mow">
                <section id="{mow_section_id}">
                    <xsl:for-each select="mow_webs/mow_web[count(. | key('wn', concat(web_number, '|', generate-id(ancestor::press_mow)))[1]) = 1]">
                        <number>
                            <xsl:value-of select="web_number"/>
                        </number>
                    </xsl:for-each>
                </section>
            </xsl:for-each>
        </root>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Applied to your input example, the result will be:

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
       <section id="1">
          <number>1</number>
       </section>
       <section id="1">
          <number>1</number>
       </section>
       <section id="2">
          <number>1</number>
          <number>2</number>
          <number>3</number>
       </section>
       <section id="2">
          <number>1</number>
          <number>2</number>
          <number>3</number>
       </section>
       <section id="2">
          <number>1</number>
          <number>2</number>
          <number>3</number>
       </section>
    </root>