p2p.wrox.com Forums

p2p.wrox.com Forums (http://p2p.wrox.com/index.php)
-   XSLT (http://p2p.wrox.com/forumdisplay.php?f=86)
-   -   if test=???? (http://p2p.wrox.com/showthread.php?t=46908)

jmirickhai August 24th, 2006 08:08 AM

if test=????
 
I have a field to search and a search string. I need all the records whose field starts with the search string. Something like.

For example given the following xml file I would like to be a able to do something like:
return all cd elements whose artist's name starts with "Bo"


<?xml version="1.0" encoding="ISO-8859-1"?>

<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>Greatest Hits</title>
        <artist>Dolly Parton</artist>
        <country>USA</country>
        <company>RCA</company>
        <price>9.90</price>
        <year>1982</year>
    </cd>
</catalog>



Im not quite sure how to write the test for that

<xsl:for-each select="cd">
  <xsl:if test="???????? what goes here ??????">

Thanks


joefawcett August 24th, 2006 08:27 AM

You need to use the starts-with function:
Code:

<?xml version="1.0" encoding="utf-8"?>

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

<xsl:param name="artistSearch" select="'Bo'"/>
<xsl:template match="/">
    <html>
     <head>
        <title>CD Collection</title>
     </head>
     <body>
        <table>
         <caption>
            Artists starting with#xa0;<xsl:value-of select="$artistSearch"/>
         </caption>
         <thead>
            <tr>
             <th>Title</th>
             <th>Artist</th>
             <th>Country</th>
             <th>Company</th>
             <th>Price</th>
             <th>Year</th>
            </tr>
         </thead>
         <tbody>
            <xsl:apply-templates select="catalog/cd[starts-with(artist, $artistSearch)]" />
         </tbody>
        </table>
     </body>
    </html>
</xsl:template>
<xsl:template match="cd">
    <tr>
     <td>
        <xsl:value-of select="title"/>
     </td>
     <td>
        <xsl:value-of select="artist"/>
     </td>
     <td>
        <xsl:value-of select="country"/>
     </td>
     <td>
        <xsl:value-of select="company"/>
     </td>
     <td>
        <xsl:value-of select="price"/>
     </td>
     <td>
        <xsl:value-of select="year"/>
     </td>
    </tr>
</xsl:template>
</xsl:stylesheet>

--

Joe (Microsoft MVP - XML)

jmirickhai August 24th, 2006 08:34 AM

almost what I need...
In "starts-with(artist, $artistSearch)" I need the field to be a parameter too
So someone could search by artist, price, title, etc.

I dont think I can just have it as a parameter:
starts-with($field, $artistSearch)... because it will just compare the two strings. I need to get the element whose name matches $field

Thanks


joefawcett August 24th, 2006 09:41 AM

If they can only search by one field then:
Code:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:param name="field" select="'title'" />
  <xsl:param name="search" select="'H'"/>
  <xsl:template match="/">
    <html>
      <head>
        <title>CD Collection</title>
      </head>
      <body>
        <table>
          <caption>
            <xsl:value-of select="$field"/> starting with <xsl:value-of select="$search"/>
          </caption>
          <thead>
            <tr>
              <th>Title</th>
              <th>Artist</th>
              <th>Country</th>
              <th>Company</th>
              <th>Price</th>
              <th>Year</th>
            </tr>
          </thead>
          <tbody>
            <xsl:apply-templates select="catalog/cd[starts-with(*[name() = $field], $search)]" />
          </tbody>
        </table>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="cd">
    <tr>
      <td>
        <xsl:value-of select="title"/>
      </td>
      <td>
        <xsl:value-of select="artist"/>
      </td>
      <td>
        <xsl:value-of select="country"/>
      </td>
      <td>
        <xsl:value-of select="company"/>
      </td>
      <td>
        <xsl:value-of select="price"/>
      </td>
      <td>
        <xsl:value-of select="year"/>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

--

Joe (Microsoft MVP - XML)

mhkay August 24th, 2006 10:53 AM

all cd elements whose artist's name starts with "Bo"

==>

cd[starts-with(artist, 'Bo')]


Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference

mhkay August 24th, 2006 10:56 AM

You can do starts-with(*[name()=$param], $searchstring)

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference

jmirickhai August 24th, 2006 01:51 PM

Awesome thanks!

One last thing I would like to make the search case insensitive.
I have tried to convert them both to upper case.. with no luck:

catalog/cd[starts-with(upper-case(*[name() = $searchfield]), upper-case(($searchtext))]

Thanks for all your help.


jkmyoung August 24th, 2006 03:35 PM

You want the fieldname to not matter as well?
catalog/cd[starts-with(upper-case(*[upper-case(name()) = upper-case($searchfield])), upper-case(($searchtext))]

Also, you may need normalize-space().

jmirickhai August 24th, 2006 06:36 PM

No. I do not want the fieldname to not matter as well.
Just need the search strings case not to matter. So if someone searches "bo" they will get back "BOB".

It didnt look like you had changed the statement I had (besides for adding in the stuff to ignore fieldname case)

Here is what I have...
catalog/cd[starts-with(upper-case(*[name() = $searchfield]), upper-case(($searchtext))]

When I try to do the transformation, I get an error. If I remove the upper-case statements it works. So I'm guessing that I am using the upper-case statement incorrectly.

How would I change that statement so that it returns elements whose contents match the searchstring (case shouldnt matter).

Thanks


mhkay August 25th, 2006 02:54 AM

The upper-case() function is in XPath 2.0 only. In 1.0, use

translate($x, 'abcdefg...', 'ABCDEFG...')

so long as the strings you are dealing with are confined to the English alphabet.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference


All times are GMT -4. The time now is 01:16 AM.

Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.