The Library, Reloaded

Following up on , I put together a simple 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).