PHP XMLOPAC Class update

iii-xmlopac-1.4.tar.gz

Another update to the III XMLOPAC class. The function get_opac_data() now returns the number of holds a bib-item has. Originally I thought this wasn’t going to be possible since I didn’t see anything overtly obvious in the XML result set, but I did see a bunch of weird “HOLD” elements with a lot of useless associated data. My hunch was that each one of these represented a bib-level hold, and I was right! Anyway, by tallying the number of these hold objects in the XML, I was able to determine the number of holds for that record.

Incidentally, this is what the nonsense looks like to SimpleXML:

[21] => SimpleXMLElement Object (
   [VARFLDPRIMARY] => SimpleXMLElement Object ( 
    [VARFLD] => SimpleXMLElement Object (
       [HEADER] => SimpleXMLElement Object ( 
        [TAG] => 8
        [NAME] => HOLD 
        [LABEL] => Hold 
        [SEQUENCENUM] => 12
      )
      [DisplayForm] => SimpleXMLElement Object ( )
      [RTL] => 0
      [FIELDDATA] => SimpleXMLElement Object ( )
    )
  )
)

What a mess. Anyway, it’s workable, the number of holds is now passed back, keyed by “holds”. If there are no holds, there will be no holds key in the result.

III item# to bib# conversion

Here is a great way to quickly convert III item numbers to bib numbers. You could stick this function in your php script and go to town:

(PHP 4 >= 4.3.0, PHP 5 with fopen_wrappers)

PHP:
  1. $opac_server = "my.opac.org";
  2.  
  3. function get_bibnum($itemnum, $opac_server) {
  4. $item_url = 'http://' . $opac_server . '/record=i' . $itemnum;
  5. $item_rec = file_get_contents($item_url);
  6. if (preg_match('%record=b(.+?)">%s', $item_rec, $bnum_matches)) {
  7. $bibnum = $bnum_matches[1];
  8. return $bibnum;
  9. } else {
  10. return 0;
  11. }
  12. }
  13. ?>

It's really so simple, I can't believe I didn't think of it before. I'm actually using it now to cache the results in a database so I'm not always chewing on the OPAC to get the result.

Enjoy!

[update]

In response to your comment/question Ryan, this is verbatim the code I'm using to cache the bib numbers. First, this is the table I'm using:

[mysql]
DESCRIBE item2bib;
+---------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+----------------+
| id | int(8) | NO | PRI | NULL | auto_increment |
| itemnum | varchar(9) | NO | MUL | | |
| bibnum | varchar(9) | NO | | | |
+---------+------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
[/mysql]

This is the code (which is actually inside a class, so you'll need to strip the class-specific stuff, but you get the general idea):

[php]
public function get_bibnum($itemnum) {
$db = DB::connect($this->dsn);
$bibnum = $db->getone("SELECT bibnum FROM item2bib WHERE itemnum = '$itemnum' LIMIT 1");
if ($bibnum) { return $bibnum; }
$item_url = 'http://' . $this->opac_server . '/record=i' . $itemnum;
$item_rec = file_get_contents($item_url);
if (preg_match('%record=b(.+?)"><%s', $item_rec, $bnum_matches)) {
$bibnum = $bnum_matches[1];
$db->query("INSERT INTO item2bib VALUES (0, '$itemnum', '$bibnum')");
return $bibnum;
} else {
return 0;
}
}
?>
[/php]

Run some data through and verify that it's working correctly:

[mysql]
mysql> select count(distinct itemnum) as itemnum, count(distinct bibnum) as bibnum, count(*) as total from item2bib;
+---------+--------+-------+
| itemnum | bibnum | total |
+---------+--------+-------+
| 45809 | 33303 | 45809 |
+---------+--------+-------+
1 row in set (0.00 sec)
[/mysql]

[/update]

Top and New Items RSS

Did I mention that I love PHP, oh yes.. I love Drupal too...

I've been on an kick to get caught up on my to-do list. On that list was getting RSS feeds working for catalog keyword searches as well as top and new item lists. Anyway, I was able to componentize the bit of code that generates an RSS bib-record summary and use it to provide customizable feeds for newly added and popular items.

Drupal has a nice bit of internal code that allows you to create an RSS stream. You essentially only need two functions:

<?php
 
header("Content-Type: text/xml");
 
/* Put together your content here */
 
$rss = '<rss version="2.0" xml:base="' . $base_url . '">';
foreach ($array_of_whatevers as $whatever) {
    $rssitems .= format_rss_item($item_title, $item_link, $whatever[content]);
}
$rss .= format_rss_channel($feed_title, $feed_url, $feed_description, $rssitems);
print($rss);
 
?>

Well, you get the idea.. My point is, Drupal is dreamy...

III-XMLOPAC Class Update

There was a minor bug in the initial version of the xmlopac class I released the other day. This update should take care of it. In addition, I've added a few more data-points to the result-set. The function should now return something like this:

Array
(
    [author] => Gleitzman, Morris
    [fulltitle] => Toad rage / Morris Gleitzman
    [title] => Toad rage
    [edition] => 1st American ed
    [pubinfo] => New York : Random House, [2004], c1999
    [desc] => 161 p.
    [summary] => Determined to understand why humans hate cane toads and to improve relations between the species, Limpy embarks on a dangerous trek from his swamp to t$
    [isbn] => 0375827625
    [price] => $16.99
    [lang] => eng
    [copies] => 4
    [catdate] => 05-05-2005
    [mattype] => a
    [avail] => 4 copies available at NE Youth, Malletts Youth, West Youth and Downtown Youth
)

By the way, this is the class I used for generating the content in the catalog RSS feeds. (The RSS feeds were the proof-of-concept I was working on for features yet to come...)

Enjoy!

UPDATE

I discovered a nasty bug in III's xmlopac that spews out some malformed utf8 garbage. This was making simplexml so very unhappy. Anyway, here is yet another fix (not worth a separate post). So if you downloaded 1.1, make sure you get 1.2.

RSS Feeds for Keyword Searches

Create a custom RSS feed for keyword searches in our catalog

Check it out, RSS feeds for keyword searches on our catalog:

Flickr Photo

Basically, it'll display the top 12 records sorted by date so that when new material matching your search is cataloged, it should show up in your feed.

This is what it looks like in NetNewsWire:

Flickr Photo

It actually didn't take that long to throw together.  I can think of worse ways of spending the afternoon!