The Library, Reloaded


Following up on my earlier post, I put together a simple PHP class to query the Delicious Library XML database:

// Class to parse and query a Delicious Library database
// Sample usage:
// $oLibrary = new CLibrary('Library Media Data.xml');
// print_r( $oLibrary->query( array("tagname" => "/book/",
//                            "author" => "/douglas/i") ) );

class CLibrary { // {{{
  
var $m_oDom;

  
// Constructor - simply parses the XML into memory
  
function CLibrary($szFilename = "") { // {{{
    
if($szFilename && file_exists($szFilename)) {
      if ( !
$this->m_oDom = domxml_open_file($szFilename) ) {
        echo
"Error while parsing the document $szFilename\n";
        exit;
      }
    }
  }
// Library }}}

  // For each XML item tossed in, see if it's a valid element and
  // if it matches all of the regexps in the filter
  
function filter( $oItem, $aFilter ) { // {{{
    
if($aFilter == "")
      return
true; // no filter matches everything
    
if($oItem->type != XML_ELEMENT_NODE)
      return
false; // not interested in this kind of items
    
$nMatches = 0;
    if(
$aFilter["tagname"]) { // special case
      
if(preg_match( $aFilter["tagname"], $oItem->tagname ) )
        
$nMatches++;
    }
    foreach(
$aFilter as $szAttribute => $szRegexp) {
      if(
preg_match($szRegexp, $oItem->get_attribute($szAttribute))) {
        
$nMatches++;
      }
    }
    if(
$nMatches == count($aFilter))
      return
true;
    return
false;
  }
// filter }}}


  // Build a nice alphabetical index of items by a given field
  
function index( $szField, $aFilter = "" ) { // {{{
    
$aIndex = array();
    
$oRoot = $this->m_oDom->document_element();
    
$aNodes = $oRoot->child_nodes();
    
print_r( $oRoot );
    foreach(
$aNodes as $oNode ) {
      if(@
$oNode->tagname == "items" ) {
        
$aItems = $oNode->child_nodes();
        foreach(
$aItems as $oItem ) {
          if(
$this->filter($oItem, $aFilter)) {
            
// Get rid of extra whitespace
            
$szBuffer = trim($oItem->get_attribute($szField));
            
$szBuffer = preg_replace("/\s+/m", " ", $szBuffer);
            
$aLetter = strtoupper(substr($szBuffer,0,1));
            if(@
$aIndex[$aLetter][$szBuffer])
              
$aIndex[$aLetter][$szBuffer][] = $oItem->get_attribute("uuid");
            else
              
$aIndex[$aLetter][$szBuffer] = array($oItem->get_attribute("uuid"));
          }
        }
      }
    }
    
ksort($aIndex);
    return
$aIndex;
  }
// index }}}

  // Query the database
  
function query( $aFilter = "" ) { // {{{
    
$aResult = array();
    
$oRoot = $this->m_oDom->document_element();
    
$aNodes = $oRoot->child_nodes();
    foreach(
$aNodes as $oNode ) {
      if(@
$oNode->tagname == "items" ) {
        
$aItems = $oNode->child_nodes();
        foreach(
$aItems as $oItem ) {
          if(
$this->filter($oItem, $aFilter)) {
            
$szUUID = $oItem->get_attribute("uuid");
            
$aResult[$szUUID]["author"] = $oItem->get_attribute("author");
            
$aResult[$szUUID]["title"] = $oItem->get_attribute("title");
            
$aResult[$szUUID]["publisher"] = $oItem->get_attribute("publisher");
          }
        }
      }
    }
    return
$aResult;
  }
// index }}}
} // CLibrary }}}

The WAP front-end is (as it should be) an entirely different matter, and it's not fit for publishing yet. When it is, it will come up on my CVS. Still, this may give people some ideas.

Monday Mode, Vacation Style

I'm thinking of getting a T-Shirt with "I survived IKEA" written on it. I wouldn't be surprised if there was an urban legend about people who walk in to buy a lamp and are never heard of again, or are found years later wandering the inside looking for pink kitchen utensils, etc.

Oh, and with impeccable timing, my division was re-structured on my first day on vacation. A mere formality, but I'm glad it's out of the way (the less bureaucracy I have to live through, the better).