0

Here is the current XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd>
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Dolly Parton</artist>
        <country>USA</country>
        <company>RCA</company>
        <price>9.90</price>
        <year>1982</year>
    </cd>
    <cd>
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
    </cd>
</catalog>

Current XSL:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/">
    <html>
      <body>
        <table border="1">
          <xsl:variable name="a" select="count(catalog/cd[contains(title,'Empire Burlesque')])"/>
          <xsl:for-each select="catalog/cd">
            <tr>
              <td>
                <xsl:choose>
                  <xsl:when test="$a = '2' and contains(title,'Empire Burlesque') ">
                    <xsl:text>pass</xsl:text>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:value-of select="title"/>
                  </xsl:otherwise>
                </xsl:choose>
              </td>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Out from this is:

pass
Hide your heart
pass
Still got the blues

Expected output:

Empire Burlesque
Hide your heart
pass
Still got the blues

I don't want 'Empire Burlesque' to be repeated instead it should be replaced with 'pass' on the second time. Can some one please help me where I must have went wrong?

Eero Helenius
  • 2,584
  • 21
  • 22
Vamsee
  • 1

2 Answers2

0

Here's one option:

Stylesheet

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

  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates select="catalog"/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="catalog">
    <table border="1">
      <xsl:apply-templates select="cd"/>
    </table>
  </xsl:template>

  <xsl:template match="cd">
    <tr>
      <xsl:apply-templates select="title"/>
    </tr>
  </xsl:template>

  <xsl:template match="title">
    <td>
      <xsl:value-of select="."/>
    </td>
  </xsl:template>

  <!--
  Match <title> elements that contain the string "Empire Burlesque" with a
  preceding element like it. This template will be applied rather than the
  one above because it has a higher specificity (as in, it is more specific
  about what kind of node it's looking for).
  -->
  <xsl:template match="title[contains(., 'Empire Burlesque') and
                       preceding::title[contains(., 'Empire Burlesque')]]">
    <td>pass</td>
  </xsl:template>
</xsl:stylesheet>

Input

<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd>
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Dolly Parton</artist>
        <country>USA</country>
        <company>RCA</company>
        <price>9.90</price>
        <year>1982</year>
    </cd>
    <cd>
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
    </cd>
</catalog>

Output

<html>
  <body>
    <table border="1">
      <tr>
        <td>Empire Burlesque</td>
      </tr>
      <tr>
        <td>Hide your heart</td>
      </tr>
      <tr>
        <td>pass</td>
      </tr>
      <tr>
        <td>Still got the blues</td>
      </tr>
    </table>
  </body>
</html>

Also, you'll want to avoid <xsl:for-each> if you can and use <xsl:apply-templates> instead, splitting your code into neat, readable chunks.

Community
  • 1
  • 1
Eero Helenius
  • 2,584
  • 21
  • 22
0

If doing grouping or duplicate removal in XSLT 1 then you want to look out for the "Muenchian Grouping" technique using keys:

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

<xsl:key name="t" match="title" use="."/>

  <xsl:template match="/">
    <html>
      <body>
        <table border="1">
          <xsl:for-each select="catalog/cd">
            <tr>
              <td>
                <xsl:choose>
                  <xsl:when test="generate-id(title)=generate-id(key('t',title))[1]">
                    <xsl:value-of select="title"/>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:text>pass</xsl:text>
                  </xsl:otherwise>
                </xsl:choose>
              </td>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Produces

<html>
   <body>
      <table border="1">
         <tr>
            <td>Empire Burlesque</td>
         </tr>
         <tr>
            <td>Hide your heart</td>
         </tr>
         <tr>
            <td>pass</td>
         </tr>
         <tr>
            <td>Still got the blues</td>
         </tr>
      </table>
   </body>
</html>
David Carlisle
  • 5,582
  • 1
  • 19
  • 23