Source for file N3Serializer.php

Documentation is available at N3Serializer.php

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

Documentation generated on Fri, 17 Dec 2004 16:16:19 +0100 by phpDocumentor 1.3.0RC3