AbRe
AbRe

Reputation: 162

Get distinct count of an element using XPath

I have a requirement to get distinct count of some particular element, but I have to only use a single XPath line to fulfil that requirement.

<root>
    <Custom1>
        <ZDPANR>PALLET1</ZDPANR>
    </Custom1>
    <Custom1>

        <ZDPANR>PALLET3</ZDPANR>
    </Custom1>
    <Custom1>

        <ZDPANR>PALLET1</ZDPANR>
    </Custom1>
    <Custom1>

        <ZDPANR>PALLET1</ZDPANR>
    </Custom1>
    <Custom1>

        <ZDPANR>PALLET2</ZDPANR>
    </Custom1>
    <Custom1>

        <ZDPANR>PALLET2</ZDPANR>
    </Custom1>
</root>

The code that I have tried so far is getting currently the distinct values for <ZDPANR> element.

<xsl:for-each select="//ZDPANR[not(.=following::ZDPANR) and .!='']">
  <td>
    <xsl:value-of select="count(//ZDPANR[.=(.)])"/><!--Single Xpath line where the count is not coming proper-->
  </td>
</xsl:for-each>

I'm able to access current distinct ZDPANR using . inside for-each. But count(//ZDPANR[.=(.)]) (.) is not getting the current ZDPANR. If I hardcode count(//ZDPANR[.='PALLET2']) like this it's coming correctly. Therefore I want to get current ZDPANR in that hardcoded place. Can somebody help me to achieve this? Because of a tool limitation I can only use Xpath 1.0.

Upvotes: 1

Views: 81

Answers (1)

kjhughes
kjhughes

Reputation: 111726

Set a variable inside your loop over the distinct ZDPANR elements, and access it in the predicate of your count() XPath predicate.

Your input XML,

<root>
  <Custom1>
    <ZDPANR>PALLET1</ZDPANR>
  </Custom1>
  <Custom1>
    <ZDPANR>PALLET3</ZDPANR>
  </Custom1>
  <Custom1>
    <ZDPANR>PALLET1</ZDPANR>
  </Custom1>
  <Custom1>
    <ZDPANR>PALLET1</ZDPANR>
  </Custom1>
  <Custom1>
    <ZDPANR>PALLET2</ZDPANR>
  </Custom1>
  <Custom1>
    <ZDPANR>PALLET2</ZDPANR>
  </Custom1>
</root>

provided to this updated XSLT,

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:template match="/">
    <table>
      <xsl:for-each select="//ZDPANR[not(.=following::ZDPANR) and .!='']">
        <xsl:variable name="cur" select="."/>
        <tr>
          <td><xsl:value-of select="$cur"/></td>
          <td><xsl:value-of select="count(//ZDPANR[.=$cur])"/></td>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>

will then yield this output XML,

<table>
   <tr>
      <td>PALLET3</td>
      <td>1</td>
   </tr>
   <tr>
      <td>PALLET1</td>
      <td>3</td>
   </tr>
   <tr>
      <td>PALLET2</td>
      <td>2</td>
   </tr>
</table>

as requested.

Upvotes: 1

Related Questions