Source for file N3Serializer.php

Documentation is available at N3Serializer.php

  1. <?php
  2.  
  3. // ----------------------------------------------------------------------------------
  4. // Class: N3Serializer
  5. // ----------------------------------------------------------------------------------
  6.  
  7. /**
  8.  * PHP Notation3 Serializer
  9.  * 
  10.  * This class serialises models to N3 Syntax.
  11.  * 
  12.  * Supported N3 features:
  13.  * <ul>
  14.  *   <li>Using [ ] for blank nodes, or _: if nescessary</li>
  15.  *   <li>Literal datytype- and xmlLanguageTag support</li>
  16.  * </ul>
  17.  * 
  18.  * Un-supported N3 Features include:
  19.  * <ul>
  20.  *   <li>Reification</li>
  21.  * </ul>
  22.  *
  23.  *
  24.  * TODO: * added namespace prefixes are persisent...
  25.  *
  26.  * @author Gunnar AA. Grimnes <ggrimnes@csd.abdn.ac.uk>, Daniel Westphal <mail@d-westphal.de>
  27.  * @version $Id: fsource_syntax__syntaxN3Serializer.php.html 443 2007-06-01 16:25:38Z cax $
  28.  * @package syntax
  29.  * @access public
  30.  ***/
  31.  
  32. define('MAGIC_STRING', '~~~');
  33.  
  34. class N3Serializer extends Object {
  35.  
  36.   var $debug; 
  37.  
  38.   var $prefixes; 
  39.  
  40.   var $done;  // keeps track of already serialized resources
  41.   var $resourcetext; 
  42.   var $model;
  43.   var $res; 
  44.   var $anon;
  45.  
  46.    /**
  47.     * Constructor
  48.     *
  49.     * @access   public
  50.     */
  51.   function N3Serializer() { 
  52.     $this->debug=FALSE;
  53.   }
  54.  
  55.  
  56.   /** 
  57.    * Adds a new namespace prefix to use.
  58.    * Unknown namespaces will become ns0, ns1 etc.
  59.    * @access public
  60.    * @param string $s 
  61.    * @returns void
  62.    ***/
  63.  
  64.   function addNSPrefix( $ns, $prefix) { 
  65.     $this->prefixes[$ns]=$prefix; 
  66.   }
  67.  
  68.   /**
  69.    * Serializes a model to N3 syntax.
  70.    *
  71.    * @param     object Model $model 
  72.    * @return    string 
  73.    * @access    public
  74.    */
  75.   function & serialize(&$m) { 
  76.  
  77.     if (is_a($m, 'DbModel')) 
  78.         $m=$m->getMemModel();
  79.     
  80.     $this->reset();
  81.     $this->model=$m;
  82.     $this->res=""; 
  83.     
  84.     // copy default namespaces
  85.     global $default_prefixes;
  86.     foreach($default_prefixes as $prefix => $namespace)
  87.             $this->addNSPrefix($namespace,$prefix);
  88.     
  89.     $nps= $this->model->getParsedNamespaces(); 
  90.     if($nps!=false){
  91.         foreach($nps as $uri => $prefix){
  92.             $this->addNSPrefix($uri,$prefix);
  93.         }
  94.     }
  95.     
  96.     $namespaces=array();
  97.     $count=array();
  98.     $resources=array(); 
  99.     foreach ($this->model->triples as $t) { 
  100.       $s=$t->getSubject();
  101.       if ( is_a($s, 'Resource')) 
  102.         $namespaces[$s->getNamespace()]=1;
  103.  
  104.       $p=$t->getPredicate();
  105.       if ( is_a($p, 'Resource')) 
  106.         $namespaces[$p->getNamespace()]=1;
  107.  
  108.       $o=$t->getObject();
  109.       if ( is_a($o, 'Resource')) 
  110.         $namespaces[$o->getNamespace()]=1;
  111.      
  112.       $uri=$s->getURI();
  113.       
  114.       if (isset($count[$uri])) { 
  115.         $count[$uri]++;
  116.       } else {     
  117.         $count[$uri]=0;
  118.         $resources[$uri]=$s;
  119.       }
  120.     }
  121.  
  122.     if (!HIDE_ADVERTISE) 
  123.         $this->res .= '# Generated by N3Serializer.php from RDF RAP.'.LINEFEED
  124.                      .'# http://www.wiwiss.fu-berlin.de/suhl/bizer/rdfapi/index.html'
  125.                      .LINEFEED.LINEFEED;
  126.  
  127.     $this->doNamespaces($namespaces); 
  128.  
  129.     $this->res.=LINEFEED.LINEFEED;
  130.  
  131.     arsort($count);
  132.     
  133.     foreach ( $count as $k=>$v) { 
  134.       $this->doResource($resources[$k]); 
  135.       //      $this->res.=" .\n";
  136.     }
  137.  
  138.     $c=0;
  139.     foreach ( $this->resourcetext as $r=>$t) { 
  140.  
  141.       if ( preg_match_all('/'.MAGIC_STRING.'([^ ]+)'.MAGIC_STRING.'/', $t, $ms, PREG_SET_ORDER)) {
  142.  
  143.     foreach($ms as $mseach) { 
  144.       $rp=$this->resourcetext[$mseach[1]];
  145.       $t=preg_replace('/'.MAGIC_STRING.$mseach[1].MAGIC_STRING.'/', $rp, $t);
  146.     }
  147.       }
  148.  
  149.       if ($this->debug) $this->res.=$c.': ';
  150.       if ( !( isset($this->resourcetext_taken[$r]) && $this->resourcetext_taken[$r]>0) ) 
  151.          $this->res.=$t.' .'.LINEFEED; 
  152.       else if ( $this->debug ) 
  153.          $this->res.=' Skipping : '.$t.LINEFEED;
  154.       $c++;
  155.     } 
  156.  
  157. //     $max=-1111;
  158. //     $maxkey="";
  159. //     foreach ($count as $k=>$c) { 
  160. //       if ( $c>$max) { $maxkey=$k; $max=$c; }
  161. //     }
  162.     
  163. //     if ($this->debug) { 
  164. //       print "$maxkey is subject of most triples! ($max) \n"; 
  165. //     }
  166.  
  167.     return $this->res;
  168.   }
  169.  
  170. /**
  171.  * Serializes a model and saves it into a file.
  172.  * Returns FALSE if the model couldn't be saved to the file.
  173.  *
  174.  * @param     object MemModel $model 
  175.  * @param     string $filename 
  176.  * @return    boolean 
  177.  * @access    public
  178.  */
  179.  function  saveAs(&$model, $filename) {
  180.  
  181.    // serialize model
  182.    $n3 = $this->serialize($model);
  183.  
  184.    // write serialized model to file
  185.    $file_handle = @fopen($filename, 'w');
  186.    if ($file_handle) {
  187.       fwrite($file_handle, $n3);
  188.       fclose($file_handle);
  189.       return TRUE;
  190.    }else{
  191.       return FALSE;
  192.    };
  193.  }
  194.   
  195.  
  196.   /* ==================== Private Methods from here ==================== */
  197.  
  198.  
  199. /**
  200.  * Readies this object for serializing another model
  201.  * @access private
  202.  * @param void 
  203.  * @returns void
  204.  ***/
  205.   function reset() {
  206.     $this->anon=0;
  207.     $this->done=array();
  208.     $this->resourcetext_taken=array();
  209.     $this->resourcetext=array();
  210.     $this->res='';
  211.     $this->model=NULL;
  212.     unset($this->prefixes);
  213.   }
  214.  
  215. /**
  216.  * Makes ns0, ns1 etc. prefixes for unknown prefixes.
  217.  * Outputs @prefix lines.
  218.  * @access private
  219.  * @param array $n 
  220.  * @returns void
  221.  ***/
  222.   function doNamespaces(&$n) { 
  223.     $c=0;
  224.     foreach ($n as $ns => $nonsense) { 
  225.       if ( !$ns ) continue;  
  226.       if ( isset($this->prefixes[$ns]) ) {
  227.     $p=$this->prefixes[$ns];
  228.       } else { 
  229.     $p='ns'.$c;
  230.     $this->prefixes[$ns]=$p;
  231.     $c++;
  232.       }
  233.       $this->res.="@prefix $p: <".$ns.'> .'.LINEFEED;
  234.     }
  235.   }
  236.  
  237. /**
  238.  * Fill in $resourcetext for a single resource.
  239.  * Will recurse into Objects of triples, but should never look ? (really?)
  240.  * @access private
  241.  * @param object Resource $r 
  242.  * @returns boolean
  243.  ***/
  244.  
  245.   function doResource(&$r) { 
  246.     //    print $r->getURI(); 
  247.  
  248.     $ts=$this->model->find($r, null, null);
  249.     if (count($ts->triples)==0) return; 
  250.     
  251.     $out="";
  252.  
  253.     if ( isset($this->done[$r->getURI()]) && $this->done[$r->getURI()] ) {
  254.       if ( is_a($r, 'BlankNode')) { 
  255.       
  256.           if ( $this->resourcetext_taken[$r->getURI()] == 1) { 
  257.               //Oh bother, we must use the _:blah construct. 
  258.               $a=$this->resourcetext[$r->getURI()];
  259.               $this->resourcetext[$r->getURI()]='_:anon'.$this->anon;
  260.               $this->resourcetext['_:anon'.$this->anon]=$this->fixAnon($a, '_:anon'.$this->anon);
  261.               $this->resourcetext_taken[$r->getURI()]=2; 
  262.               $this->anon++;
  263.         }
  264.  
  265.       }
  266.       return false; 
  267.     }
  268.  
  269.     $this->done[$r->getURI()]=TRUE;
  270.  
  271.     if ( is_a($r, 'Resource') ) {
  272.  
  273.       if ( is_a($r, 'BlankNode') ) { 
  274.  
  275.            //test, if this blanknode is referenced somewhere
  276.           $rbn=$this->model->find(null, null, $r);
  277.  
  278.           if (count($rbn->triples)>0 | !N3SER_BNODE_SHORT) {
  279.               $out.='_:'.$r->getLabel();
  280.           } else {
  281.               $out.='[ ';
  282.           };    
  283.       } else { 
  284.  
  285.         $this->doURI($r, $out);
  286.  
  287.       };
  288.     };
  289.   
  290.     usort($ts->triples, 'statementsorter');
  291.     $lastp='';
  292.  
  293.     $out.=' ';
  294.  
  295.     foreach ($ts->triples as $t) { 
  296.       
  297.       $p=$t->getPredicate(); 
  298.       
  299.       if ($p == $lastp) {
  300.     $out.=' , '; 
  301.       } else { 
  302.     if ($lastp!='') $out.=' ; '; 
  303.     $this->doURI($p, $out);
  304.     $lastp=$p;
  305.       }
  306.  
  307.       $out.=' ';
  308.       
  309.       $o=$t->getObject();
  310.       
  311.       if ( is_a($o, 'Literal')) { 
  312.     $l=$o->getLabel();
  313.     if ( strpos($l, LINEFEED) === FALSE ) { 
  314.       $out.="\"$l\"";
  315.     } else { 
  316.       $out.="\"\"\"$l\"\"\"";      
  317.     }
  318.     if ( $o->getLanguage()!='' ) { 
  319.       $out.='@'.$o->getLanguage();
  320.     }
  321.     if ( $o->getDatatype()!='' ) { 
  322.       $out.='^^<'.$o->getDatatype().'>';
  323.     }
  324.     
  325.       } 
  326.       
  327.       if (is_a($o, 'Resource')) {
  328.     if ($this->debug) print 'Doing object: '.$o->getURI().LINEFEED;
  329.     if ( is_a($o,'BlankNode')) {
  330.  
  331. //    $this->doResource($o);
  332. //      $out.=MAGIC_STRING.$o->getURI().MAGIC_STRING; #$this->resourcetext[$o->getURI()];
  333. //      $this->resourcetext_taken[$o->getURI()]=1;
  334.  
  335.     $out .='_:'.$o->getLabel();
  336.     } else { 
  337.  
  338.       $this->doURI($o, $out);
  339.     }
  340.       }
  341.     }
  342.  
  343.     if (isset($rbn) && !count($rbn->triples)>0 && N3SER_BNODE_SHORT) {$out.=' ] ';};
  344.     $this->resourcetext[$r->getURI()]=$out; 
  345.  
  346.     return TRUE;
  347.   }
  348.  
  349.   /** 
  350.    * Format a single URI
  351.    * @param string $s 
  352.    * @access private
  353.    * @return void 
  354.    ***/
  355.   function doURI(&$r, &$out) { 
  356.     if ( $r->getURI()=='http://www.w3.org/1999/02/22-rdf-syntax-ns#type') {
  357.       $out.='a';
  358.       return; 
  359.     }
  360.     if ($r->getNamespace()!='') {
  361.       $out.=$this->prefixes[$r->getNamespace()].':'.$r->getLocalName();
  362.     } else { 
  363.       //Will this ever happen? 
  364.       $out.=$r->getURI();
  365.     }
  366.   }
  367.  
  368.   
  369.   /** 
  370.    * Fix the resourcetext for a blanknode where the _: construct was used
  371.    * @param string $s 
  372.    * @param string $a 
  373.    * @access private
  374.    * @return void 
  375.    ***/
  376.   function fixAnon($t,$a) { 
  377.     $t=preg_replace("/( \] $|^\[ )/", '', $t); 
  378.  
  379.     return $a.$t;
  380.   }
  381.  
  382. }
  383.  
  384. ?>

Documentation generated on Fri, 1 Jun 2007 16:50:01 +0200 by phpDocumentor 1.3.2