PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/rdfapi-php/api/syntax/N3Serializer.php

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