/rdfapi-php/api/syntax/N3Serializer.php
PHP | 526 lines | 304 code | 87 blank | 135 comment | 78 complexity | 2b85627759d05ce1a04e9c2d19144939 MD5 | raw file
Possible License(s): LGPL-2.1
- <?php
- // ----------------------------------------------------------------------------------
- // Class: N3Serializer
- // ----------------------------------------------------------------------------------
- /**
- * PHP Notation3 Serializer
- *
- * This class serialises models to N3 Syntax.
- *
- * Supported N3 features:
- * <ul>
- * <li>Using [ ] for blank nodes, or _: if necessary</li>
- * <li>Literal datatype- and xmlLanguageTag support</li>
- * </ul>
- *
- * Un-supported N3 Features include:
- * <ul>
- * <li>Reification</li>
- * </ul>
- *
- *
- * @author Gunnar AA. Grimnes <ggrimnes@csd.abdn.ac.uk>
- * @author Daniel Westphal <mail@d-westphal.de>
- * @author Christian Weiske <cweiske@cweiske.de>
- * @version $Id: N3Serializer.php 556 2008-01-22 10:52:48Z fusel2k $
- * @package syntax
- * @access public
- **/
- define('MAGIC_STRING', '~~~');
- class N3Serializer extends Object
- {
- var $debug = false;
- var $prefixes = array();
- var $noPrefixes = array();
- var $done; // keeps track of already serialized resources
- var $resourcetext;
- var $resourcetext_taken;
- var $model;
- var $res;
- var $anon;
- var $styleCompress = false;
- var $stylePretty = false;
- var $styleNest = false;
- /**
- * Constructor
- *
- * @access public
- */
- function N3Serializer()
- {
- $this->debug = false;
- }
- /**
- * Adds a new namespace prefix to use.
- * Unknown namespaces will become ns0, ns1 etc.
- * @access public
- * @param string $s
- * @returns void
- **/
- function addNSPrefix($ns, $prefix)
- {
- $this->prefixes[$ns] = $prefix;
- }
- /**
- * Clears all previously set namespace prefixes
- */
- function clearNSPrefixes()
- {
- $this->prefixes = array();
- }
- /**
- * Add a namespace that shall not get shortened by using a prefix.
- *
- * @param string $ns Namespace URI like "http://example.com/"
- */
- function addNoNSPrefix($ns)
- {
- $this->noPrefixes[$ns] = true;
- }
- /**
- * Clears all previously set noNamespace prefixes
- */
- function clearNoNSPrefixes()
- {
- $this->noPrefixes = array();
- }
- /**
- * Serializes a model to N3 syntax.
- *
- * @param object Model $model
- * @return string
- * @access public
- */
- function &serialize(&$m)
- {
- if (is_a($m, 'DbModel')) {
- $m=$m->getMemModel();
- }
- $this->reset();
- $this->model = $m;
- $this->res = "";
- // copy default namespaces
- global $default_prefixes;
- foreach($default_prefixes as $prefix => $namespace) {
- $this->addNSPrefix($namespace,$prefix);
- }
- $nps= $this->model->getParsedNamespaces();
- if ($nps!=false) {
- foreach ($nps as $uri => $prefix){
- $this->addNSPrefix($uri,$prefix);
- }
- }
- $namespaces = array();
- $count = array();
- $resources = array();
- foreach ($this->model->triples as $t) {
- $s = $t->getSubject();
- if (is_a($s, 'Resource')) {
- $namespaces[$s->getNamespace()] = 1;
- }
- $p = $t->getPredicate();
- if (is_a($p, 'Resource')) {
- $namespaces[$p->getNamespace()] = 1;
- }
- $o = $t->getObject();
- if (is_a($o, 'Resource')) {
- $namespaces[$o->getNamespace()] = 1;
- }
- $uri = $s->getURI();
- if (isset($count[$uri])) {
- $count[$uri]++;
- } else {
- $count[$uri] = 0;
- $resources[$uri] = $s;
- }
- if ($this->styleNest && is_a($s, 'BlankNode')) {
- //make sure blank nodes are sorted *after* normal nodes
- //so that they can be included
- $count[$uri] -= 0.00001;
- }
- }
- if (!HIDE_ADVERTISE) {
- $this->res .= '# Generated by N3Serializer.php from RDF RAP.'.LINEFEED
- .'# http://www.wiwiss.fu-berlin.de/suhl/bizer/rdfapi/index.html'
- .LINEFEED.LINEFEED;
- }
- $this->doNamespaces($namespaces);
- $this->res .= LINEFEED.LINEFEED;
- arsort($count);
- foreach ( $count as $k => $v) {
- $this->doResource($resources[$k]);
- // $this->res.=" .\n";
- }
- //make all replacements
- do {
- $bReplacements = false;
- foreach ($this->resourcetext as $r => $t) {
- if (preg_match_all('/'.MAGIC_STRING.'([^ ]+)'.MAGIC_STRING.'/', $t, $ms, PREG_SET_ORDER)) {
- foreach ($ms as $mseach) {
- $rp = $this->resourcetext[$mseach[1]];
- $this->resourcetext[$r] = preg_replace('/'.MAGIC_STRING.$mseach[1].MAGIC_STRING.'/', $rp, $t);
- $bReplacements = true;
- }
- }
- }
- } while ($bReplacements);
- //after all replacements took place, put the lines out
- $c = 0;
- foreach ($this->resourcetext as $r => $t) {
- if ($this->debug) {
- $this->res .= $c . ': ';
- }
- if (!(isset($this->resourcetext_taken[$r]) && $this->resourcetext_taken[$r]>0)) {
- $this->res .= $t . ' .' . LINEFEED;
- if ($this->stylePretty) {
- $this->res .= LINEFEED;
- }
- } else if ($this->debug ) {
- $this->res.=' Skipping : '.$t.LINEFEED;
- }
- $c++;
- }
- // $max=-1111;
- // $maxkey="";
- // foreach ($count as $k=>$c) {
- // if ( $c>$max) { $maxkey=$k; $max=$c; }
- // }
- // if ($this->debug) {
- // print "$maxkey is subject of most triples! ($max) \n";
- // }
- return $this->res;
- }//function &serialize(&$m)
- /**
- * Serializes a model and saves it into a file.
- * Returns FALSE if the model couldn't be saved to the file.
- *
- * @param object MemModel $model
- * @param string $filename
- * @return boolean
- * @access public
- */
- function saveAs(&$model, $filename)
- {
- // serialize model
- $n3 = $this->serialize($model);
- // write serialized model to file
- $file_handle = @fopen($filename, 'w');
- if ($file_handle) {
- fwrite($file_handle, $n3);
- fclose($file_handle);
- return true;
- } else {
- return false;
- };
- }
- /**
- * Set to true, if the N3 serializer should try to compress the blank node
- * syntax using [] whereever possible.
- */
- function setCompress($compress)
- {
- $this->styleCompress = $compress;
- }
- /**
- * Enables pretty printing in semicolon delimited sentences.
- */
- function setPrettyPrint($prettyPrint)
- {
- $this->stylePretty = $prettyPrint;
- }
- /**
- * Enables nesting of blank nodes with [] if
- * compression is activated via @see setCompress
- */
- function setNest($nest)
- {
- $this->styleNest = $nest;
- }
- /* ==================== Private Methods from here ==================== */
- /**
- * Readies this object for serializing another model
- * @access private
- * @param void
- * @returns void
- **/
- function reset()
- {
- $this->anon = 0;
- $this->done = array();
- $this->resourcetext_taken = array();
- $this->resourcetext = array();
- $this->res = '';
- $this->model = null;
- }
- /**
- * Makes ns0, ns1 etc. prefixes for unknown prefixes.
- * Outputs @prefix lines.
- * @access private
- * @param array $n
- * @returns void
- **/
- function doNamespaces(&$n)
- {
- $c = 0;
- foreach ($n as $ns => $nonsense) {
- if (!$ns || isset($this->noPrefixes[$ns])) {
- continue;
- }
- if (isset($this->prefixes[$ns])) {
- $p = $this->prefixes[$ns];
- } else {
- $p = 'ns' . $c;
- $this->prefixes[$ns] = $p;
- $c++;
- }
- $this->res .= "@prefix $p: <".$ns.'> .'.LINEFEED;
- }
- }
- /**
- * Fill in $resourcetext for a single resource.
- * Will recurse into Objects of triples, but should never look ? (really?)
- * @param object Resource $r
- * @returns boolean
- * @access private
- **/
- function doResource(&$r, $bEmbedded = false, $strIndent = ' ')
- {
- //var_dump($r->getURI());
- $ts = $this->model->find($r, null, null);
- if (count($ts->triples) == 0) {
- if ($bEmbedded) {
- $this->resourcetext[$r->getURI()] = '_:' . $r->getLabel();
- }
- return;
- }
- $out = '';
- if (isset($this->done[$r->getURI()]) && $this->done[$r->getURI()]) {
- if (!$this->styleNest && is_a($r, 'BlankNode')) {
- if ($this->resourcetext_taken[$r->getURI()] == 1) {
- //Oh bother, we must use the _:blah construct.
- $a = $this->resourcetext[$r->getURI()];
- $this->resourcetext[$r->getURI()]='_:anon'.$this->anon;
- $this->resourcetext['_:anon'.$this->anon]=$this->fixAnon($a, '_:anon'.$this->anon);
- $this->resourcetext_taken[$r->getURI()]=2;
- $this->anon++;
- }
- }
- return false;
- }
- $this->done[$r->getURI()] = true;
- $compress = false;
- if (is_a($r, 'Resource')) {
- if (is_a($r, 'BlankNode')) {
- //test if this blanknode is referenced somewhere
- $rbn = $this->model->find(null, null, $r);
- $compress = (N3SER_BNODE_SHORT || $this->styleCompress)
- && (
- count($rbn->triples) == 0
- || (count($rbn->triples) == 1 && $bEmbedded)
- );
- if ($compress) {
- $out.='[';
- } else {
- $out.='_:'.$r->getLabel();
- }
- } else {
- $this->doURI($r, $out);
- }
- }
- usort($ts->triples, 'statementsorter');
- $lastp = '';
- $out .= ' ';
- foreach ($ts->triples as $t) {
- $p = $t->getPredicate();
- if ($p === $lastp) {
- $out .= ' , ';
- } else {
- if ($lastp!='') {
- if ($this->stylePretty) {
- $out .= ";\n" . $strIndent;
- } else {
- $out .= ' ; ';
- }
- }
- $this->doURI($p, $out);
- $lastp = $p;
- }
- $out .= ' ';
- $o = $t->getObject();
- if (is_a($o, 'Literal')) {
- $l = $o->getLabel();
- if (strpos($l, LINEFEED) === false) {
- $long = false;
- } else {
- $long = true;
- }
- //try to be intelligent
- $quoteSingle = strpos($l, '\'') !== false;
- $quoteDouble = strpos($l, '"') !== false;
- if ($quoteSingle && !$quoteDouble) {
- $quoteChar = $long ? '"""' : '"';
- } else if ($quoteDouble && !$quoteSingle) {
- $quoteChar = $long ? '\'\'\'' : '\'';
- } else if ($quoteDouble && $quoteSingle) {
- //both quotation chars inside
- $quoteChar = $long ? '"""' : '"';
- $l = addslashes($l);
- } else {
- //no quotation chars
- $quoteChar = $long ? '"""' : '"';
- }
- $out .= $quoteChar . $l . $quoteChar;
- if ( $o->getLanguage()!='' ) {
- $out.='@'.$o->getLanguage();
- }
- if ( $o->getDatatype()!='' ) {
- $out.='^^<'.$o->getDatatype().'>';
- }
- }
- if (is_a($o, 'Resource')) {
- if ($this->debug) {
- print 'Doing object: '.$o->getURI().LINEFEED;
- }
- if (is_a($o, 'BlankNode')) {
- if ($this->styleNest && $this->styleCompress
- && !isset($this->done[$o->getURI()])
- ) {
- $this->doResource($o, true, $strIndent . ' ');
- $out .= MAGIC_STRING . $o->getURI() . MAGIC_STRING;
- //$out .= $this->resourcetext[$o->getURI()];
- $this->resourcetext_taken[$o->getURI()] = 1;
- } else {
- $out .= '_:'.$o->getLabel();
- }
- } else {
- $this->doURI($o, $out);
- }
- }
- }
- if ($compress) {
- $out .= ' ]';
- };
- $this->resourcetext[$r->getURI()]=$out;
- return true;
- }//function doResource(&$r)
- /**
- * Format a single URI
- * @param string $s
- * @return void
- * @access private
- **/
- function doURI(&$r, &$out)
- {
- if ($r->getURI() == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') {
- $out .= 'a';
- return;
- }
- $ns = $r->getNamespace();
- if ($ns != '' && !isset($this->noPrefixes[$ns])) {
- $out .= $this->prefixes[$ns].':'.$r->getLocalName();
- } else {
- //Will this ever happen? It does, now.
- $out .= '<' . $r->getURI() . '>';
- }
- }
- /**
- * Fix the resourcetext for a blanknode where the _: construct was used
- * @param string $s
- * @param string $a
- * @access private
- * @return void
- **/
- function fixAnon($t,$a)
- {
- $t = preg_replace("/( \] $|^\[ )/", '', $t);
- return $a . $t;
- }
- }
- ?>