Source for file RdfParser.php

Documentation is available at RdfParser.php

  1. <?php
  2.  
  3. // ----------------------------------------------------------------------------------
  4. // Class: RdfParser
  5. // ----------------------------------------------------------------------------------
  6.  
  7.  
  8.  
  9.  
  10.  
  11. /**
  12. * An RDF paser.
  13. * This class reads RDF data from files or URIs and generates models out of it. All valid
  14. * RDF XML syntaxes defined by the W3C in RDF/XML Syntax Specification (Revised)
  15. * - W3C Working Draft 10 October 2003
  16. * (http://www.w3.org/TR/2003/WD-rdf-syntax-grammar-20031010/) are supported.
  17. * The parser is based on the PHP version of repat
  18. * (http://phpxmlclasses.sourceforge.net/show_doc.php?class=class_rdf_parser.html)
  19. * by Luis Argerich (lrargerich@yahoo.com).
  20. *
  21. * <BR><BR>History:<UL>
  22. * <LI>12-06-2004 : improved namespace handling added (tobias.gauss@web.de)</LI>
  23. * <LI>08-13-2004 : Bug in rdf:resource="" fixed</LI>
  24. * <LI>08-10-2004 : function for converting strings to its unicode NFC form added. Benjamin Nowack <bnowack@appmosphere.com></LI>
  25. * <LI>06-01-2004 : Bug in xml:lang fixed, some bugs in the handling of collections fixed</LI>
  26. * <LI>05-03-2004 : generateModel(): added optional parameter $rdfBaseURI to set the rdf base URI manually for strings when there's
  27. * no xml:base stated <mail@d-westphal.de>.</LI>
  28. * <LI>11-18-2003 : Made compliant with the latest RDF Specification (10. October 2003) <radol@gmx.de>.
  29. *
  30. * Support for several aspects of the RDF Specification
  31. * was added or fixed, among others:
  32. * bugs in handling of xml:base and resolving relative URIs fixed,
  33. * support for parseType="Literal" (XMLLiterals) added,
  34. * support for parseType="Collection" added,
  35. * handling of xml:lang improved,
  36. * handling of containers improved,
  37. * handling of empty property elements improved,
  38. * handling of RDF vocabulary improved,
  39. * some cases of reification fixed,
  40. *
  41. * Several methods have been changed, unused variables and
  42. * parameters removed (see CVS for details).
  43. * new private methods: _is_forbidden_rdf_property_attribute(),
  44. * _is_forbidden_rdf_property_element ($local_name),
  45. * _is_rdf_node_element(),
  46. * _is_forbidded_node_element(),
  47. * _report_error(),
  48. * _handle_collection_element(),
  49. * _handle_xml_start_element(),
  50. * _handle_xml_end_element(),
  51. * _join_name_and_declare_prefix(),
  52. * _end_collection(),
  53. * _start_ns_declaration_handler(),
  54. * removed private methods: _delete_elements(),
  55. * _end_empty_resource_property(),
  56. * rdf_resolve_uri()
  57. *
  58. * BUGS WHICH HAVE NOT BEED FIXED:
  59. * - correct handling of non US-ASCII characters</LI>
  60. *
  61. * <LI>07-27-2003 : Functions addapted to the new class tree (MemModel extends Model)</LI>
  62. * <LI>04-23-2003 : Bug concerning bnode recognition fixed.</LI>
  63. * <LI>04-03-2003 : Bug concerning bnode identifier generation fixed.</LI>
  64. * <LI>01-10-2003 : Support for rdf:datatype and rdf:nodeID added.</LI>
  65. * <LI>01-05-2003 : Support for rdf:seeAlso added.</LI>
  66. * <LI>11-07-2002 : Possibility to pass RDF code directly to the method generateModel() added.</LI>
  67. * <LI>10-25-2002 : Bug concerning 1 character long literals fixed.</LI>
  68. * <LI>09-24-2002 : Recognition of blank nodes improved.</LI>
  69. * <LI>09-10-2002 : First version of this class.</LI>
  70. * </UL>
  71. * @version V0.9.1
  72. * @author Luis Argerich <lrargerich@yahoo.com>,
  73. * Chris Bizer <chris@bizer.de>,
  74. * Radoslaw Oldakowski <radol@gmx.de>
  75. * Daniel Westphal <mail@d-westphal.de>
  76. * @package syntax
  77. * @access public
  78. *
  79. */
  80. class RdfParser extends Object {
  81.  
  82. var $rdf_parser;
  83. var $model;
  84.  
  85. /* Private Methods */
  86.  
  87.  
  88. /**
  89. * converts a string to its unicode NFC form (e.g. \uHHHH or \UHHHHHHHH).
  90. *
  91. * @param String $str
  92. * @return String
  93. * @access private
  94. *
  95. */
  96. function str2unicode_nfc($str=""){
  97. $result="";
  98. /* try to detect encoding */
  99. $tmp=str_replace("?", "", $str);
  100. if(strpos(utf8_decode($tmp), "?")===false){
  101. $str=utf8_decode($str);
  102. }
  103. for($i=0,$i_max=strlen($str);$i<$i_max;$i++){
  104. $nr=0;/* unicode dec nr */
  105. /* char */
  106. $char=$str[$i];
  107. /* utf8 binary */
  108. $utf8_char=utf8_encode($char);
  109. $bytes=strlen($utf8_char);
  110. if($bytes==1){
  111. /* 0####### (0-127) */
  112. $nr=ord($utf8_char);
  113. }
  114. elseif($bytes==2){
  115. /* 110##### 10###### = 192+x 128+x */
  116. $nr=((ord($utf8_char[0])-192)*64) + (ord($utf8_char[1])-128);
  117. }
  118. elseif($bytes==3){
  119. /* 1110#### 10###### 10###### = 224+x 128+x 128+x */
  120. $nr=((ord($utf8_char[0])-224)*4096) + ((ord($utf8_char[1])-128)*64) + (ord($utf8_char[2])-128);
  121. }
  122. elseif($bytes==4){
  123. /* 1111#### 10###### 10###### 10###### = 240+x 128+x 128+x 128+x */
  124. $nr=((ord($utf8_char[0])-240)*262144) + ((ord($utf8_char[1])-128)*4096) + ((ord($utf8_char[2])-128)*64) + (ord($utf8_char[3])-128);
  125. }
  126. /* result (see http://www.w3.org/TR/rdf-testcases/#ntrip_strings) */
  127. if($nr<9){/* #x0-#x8 (0-8) */
  128. $result.="\\u".sprintf("%04X",$nr);
  129. }
  130. elseif($nr==9){/* #x9 (9) */
  131. $result.='\t';
  132. }
  133. elseif($nr==10){/* #xA (10) */
  134. $result.='\n';
  135. }
  136. elseif($nr<13){/* #xB-#xC (11-12) */
  137. $result.="\\u".sprintf("%04X",$nr);
  138. }
  139. elseif($nr==13){/* #xD (13) */
  140. $result.='\t';
  141. }
  142. elseif($nr<32){/* #xE-#x1F (14-31) */
  143. $result.="\\u".sprintf("%04X",$nr);
  144. }
  145. elseif($nr<34){/* #x20-#x21 (32-33) */
  146. $result.=$char;
  147. }
  148. elseif($nr==34){/* #x22 (34) */
  149. $result.='\"';
  150. }
  151. elseif($nr<92){/* #x23-#x5B (35-91) */
  152. $result.=$char;
  153. }
  154. elseif($nr==92){/* #x5C (92) */
  155. $result.='\\';
  156. }
  157. elseif($nr<127){/* #x5D-#x7E (93-126) */
  158. $result.=$char;
  159. }
  160. elseif($nr<65536){/* #x7F-#xFFFF (128-65535) */
  161. $result.="\\u".sprintf("%04X",$nr);
  162. }
  163. elseif($nr<1114112){/* #x10000-#x10FFFF (65536-1114111) */
  164. $result.="\\U".sprintf("%08X",$nr);
  165. }
  166. else{
  167. /* other chars are not defined => ignore */
  168. }
  169. }
  170. return $result;
  171. }
  172.  
  173.  
  174.  
  175.  
  176. /**
  177. * @access private
  178. */
  179. function _new_element()
  180. {
  181. $e['parent']=Array(); // Parent is a blank Array
  182. $e['state']=0;
  183. $e['has_property_atributes']=0;
  184. $e['has_member_attributes']=0;
  185. $e['subject_type']=0;
  186. $e['subject']='';
  187. $e['predicate']='';
  188. $e['ordinal']=0;
  189. $e['members']=0;
  190. $e['data']='';
  191. $e['xml_lang']='';
  192. $e['bag_id']='';
  193. $e['statements']=0;
  194. $e['statement_id']='';
  195. $e['datatype']='';
  196. $e['element_base_uri'] = '';
  197. return $e;
  198. }
  199.  
  200. /**
  201. * @param string $source
  202. * @param string &$destination
  203. *
  204. * @access private
  205. */
  206. function _copy_element($source, &$destination )
  207. {
  208. if( $source )
  209. {
  210. $destination['parent'] = $source;
  211. $destination['state'] = $source['state'];
  212. $destination['xml_lang'] = $source['xml_lang'];
  213. $destination['element_base_uri'] = $source['element_base_uri'];
  214. }
  215. }
  216.  
  217. /**
  218. * @param string &$e
  219. * @access private
  220. */
  221. function _clear_element(&$e)
  222. {
  223. $e['subject']='';
  224. $e['predicate']='';
  225. $e['data']='';
  226. $e['bag_id']='';
  227. $e['statement_id']='';
  228.  
  229. if(isset($e['parent'])) {
  230. if( $e['parent'] )
  231. {
  232. if( $e['parent']['xml_lang'] != $e['xml_lang'] )
  233. {
  234. $e['xml_lang']='';
  235. }
  236. }
  237. else
  238. {
  239. $e['xml_lang']='';
  240. }
  241. } else {
  242. $e['xml_lang']='';
  243. }
  244.  
  245. $e['parent']=Array();
  246. $e['state']=0;
  247. $e['has_property_attributes']=0;
  248. $e['has_member_attributes']=0;
  249. $e['subject_type']=0;
  250. $e['subject']='';
  251. $e['predicate']='';
  252. $e['ordinal']=0;
  253. $e['members']=0;
  254. $e['data']='';
  255. $e['xml_lang']='';
  256. $e['bag_id']='';
  257. $e['statements']=0;
  258. $e['statement_id']='';
  259. $e['datatype']='';
  260. $e['element_base_uri'] = '';
  261. }
  262.  
  263. /**
  264. * @access private
  265. */
  266. function _push_element()
  267. {
  268. if(!isset($this->rdf_parser['free'])) {
  269. $this->rdf_parser['free']=Array();
  270. }
  271. if(count($this->rdf_parser['free'])>0)
  272. {
  273. $e = $this->rdf_parser['free'];
  274. if(isset($e['parent'])) {
  275. $this->rdf_parser['free'] = $e['parent'];
  276. } else {
  277. $this->rdf_parser['free']=$this->_new_element();
  278. }
  279. }
  280. else
  281. {
  282. $e = $this->_new_element();
  283. }
  284. if(!isset($this->rdf_parser['top'])) {
  285. $this->rdf_parser['top']=Array();
  286. }
  287. $this->_copy_element( $this->rdf_parser['top'], $e );
  288. $this->rdf_parser['top'] = $e;
  289. }
  290.  
  291. /**
  292. * @access private
  293. */
  294. function _pop_element()
  295. {
  296. $e = $this->rdf_parser['top'];
  297. $this->rdf_parser['top'] = $e['parent'];
  298. $this->_clear_element( $e );
  299. $this->rdf_parser['free'] = $e;
  300. }
  301.  
  302. /**
  303. * @param string $local_name
  304. * @access private
  305. */
  306. function _is_rdf_property_attribute_resource($local_name )
  307. {
  308. return ( $local_name == RDF_TYPE );
  309. }
  310.  
  311. /**
  312. * @param string $local_name
  313. * @access private
  314. */
  315. function _is_rdf_property_attribute_literal($local_name )
  316. {
  317. return ( $local_name == RDF_VALUE )
  318. || ( $local_name == RDF_BAG )
  319. || ( $local_name == RDF_SEQ )
  320. || ( $local_name == RDF_ALT )
  321. || ( $local_name == RDF_STATEMENT )
  322. || ( $local_name == RDF_PROPERTY )
  323. || ( $local_name == RDF_LIST );
  324. }
  325.  
  326. /**
  327. * @param string $local_name
  328. * @access private
  329. */
  330. function _is_rdf_ordinal( $local_name )
  331. {
  332. $ordinal = -1;
  333.  
  334. if( $local_name{0} == '_' )
  335. {
  336. $ordinal = substr($local_name,1) + 1 ;
  337. }
  338.  
  339. return ( $ordinal > 0 ) ? $ordinal : 0;
  340. }
  341.  
  342. /**
  343. * @param string $local_name
  344. * @access private
  345. */
  346. function _is_rdf_property_attribute( $local_name )
  347. {
  348. return $this->_is_rdf_property_attribute_resource( $local_name )
  349. || $this->_is_rdf_property_attribute_literal( $local_name );
  350. }
  351.  
  352. function _is_forbidden_rdf_property_attribute($local_name)
  353. {
  354. return ( $local_name == RDF_RDF )
  355. || ( $local_name == RDF_DESCRIPTION)
  356. || ( $local_name == RDF_ID)
  357. || ( $local_name == RDF_ABOUT )
  358. || ( $local_name == RDF_BAG_ID )
  359. || ( $local_name == RDF_PARSE_TYPE )
  360. || ( $local_name == RDF_RESOURCE )
  361. || ( $local_name == RDF_NODEID )
  362. || ( $local_name == RDF_LI )
  363. || ( $local_name == RDF_ABOUT_EACH )
  364. || ( $local_name == RDF_ABOUT_EACH_PREFIX )
  365. || ( $local_name == RDF_DATATYPE );
  366. }
  367.  
  368. /**
  369. * @param string $local_name
  370. * @access private
  371. */
  372. function _is_rdf_property_element( $local_name )
  373. {
  374. return ( $local_name == RDF_TYPE )
  375. || ( $local_name == RDF_SUBJECT )
  376. || ( $local_name == RDF_PREDICATE )
  377. || ( $local_name == RDF_OBJECT )
  378. || ( $local_name == RDF_VALUE )
  379. || ( $local_name == RDF_LI )
  380. || ( $local_name == RDF_SEEALSO )
  381. || ( $local_name == RDF_BAG )
  382. || ( $local_name == RDF_SEQ )
  383. || ( $local_name == RDF_ALT )
  384. || ( $local_name == RDF_STATEMENT )
  385. || ( $local_name == RDF_PROPERTY )
  386. || ( $local_name == RDF_LIST )
  387. || ( $local_name == RDF_FIRST )
  388. || ( $local_name == RDF_REST )
  389. || ( $local_name{0} == '_' );
  390. }
  391.  
  392. /**
  393. * @param string $local_name
  394. * @access private
  395. */
  396. function _is_forbidden_rdf_property_element ($local_name)
  397. {
  398. return ( $local_name == RDF_RDF )
  399. || ( $local_name == RDF_DESCRIPTION)
  400. || ( $local_name == RDF_ID)
  401. || ( $local_name == RDF_ABOUT )
  402. || ( $local_name == RDF_BAG_ID )
  403. || ( $local_name == RDF_PARSE_TYPE )
  404. || ( $local_name == RDF_RESOURCE )
  405. || ( $local_name == RDF_NODEID )
  406. || ( $local_name == RDF_ABOUT_EACH )
  407. || ( $local_name == RDF_ABOUT_EACH_PREFIX )
  408. || ( $local_name == RDF_DATATYPE );
  409. }
  410.  
  411. /**
  412. * @param string $local_name
  413. * @access private
  414. */
  415. function _is_rdf_node_element( $local_name )
  416. {
  417. return ( $local_name == RDF_DESCRIPTION )
  418. || ( $local_name == RDF_STATEMENT )
  419. || ( $local_name == RDF_SUBJECT )
  420. || ( $local_name == RDF_PREDICATE )
  421. || ( $local_name == RDF_OBJECT )
  422. || ( $local_name == RDF_PROPERTY )
  423. || ( $local_name == RDF_TYPE )
  424. || ( $local_name == RDF_VALUE )
  425. || ( $local_name == RDF_BAG )
  426. || ( $local_name == RDF_SEQ )
  427. || ( $local_name == RDF_ALT )
  428. || ( $local_name == RDF_SEEALSO )
  429. || ( $local_name == RDF_LIST )
  430. || ( $local_name == RDF_FIRST )
  431. || ( $local_name == RDF_REST )
  432. || ( $local_name == RDF_NIL )
  433. || ( $local_name{0} == '_' );
  434. }
  435.  
  436. /**
  437. * @param string $local_name
  438. * @access private
  439. */
  440. function _is_forbidden_rdf_node_element ($local_name)
  441. {
  442. return ( $local_name == RDF_RDF )
  443. || ( $local_name == RDF_ID)
  444. || ( $local_name == RDF_ABOUT )
  445. || ( $local_name == RDF_BAG_ID )
  446. || ( $local_name == RDF_PARSE_TYPE )
  447. || ( $local_name == RDF_RESOURCE )
  448. || ( $local_name == RDF_NODEID )
  449. || ( $local_name == RDF_LI )
  450. || ( $local_name == RDF_ABOUT_EACH )
  451. || ( $local_name == RDF_ABOUT_EACH_PREFIX )
  452. || ( $local_name == RDF_DATATYPE );
  453. }
  454.  
  455. /**
  456. * @param string $val
  457. * @access private
  458. */
  459. function _istalnum($val) {
  460. return ereg("[A-Za-z0-9]",$val);
  461. }
  462. /**
  463. * @param string $val
  464. * @access private
  465. */
  466. function _istalpha($val) {
  467. return ereg("[A-Za-z]",$val);
  468. }
  469.  
  470. /**
  471. * @param string $uri
  472. * @access private
  473. */
  474. function _is_absolute_uri($uri )
  475. {
  476. $result = false;
  477. $uri_p=0;
  478. if( $uri && $this->_istalpha( $uri{$uri_p} ) )
  479. {
  480. ++$uri_p;
  481.  
  482. while( ($uri_p<strlen($uri))
  483. && ( $this->_istalnum( $uri{$uri_p} )
  484. || ( $uri{$uri_p} == '+' )
  485. || ( $uri{$uri_p} == '-' )
  486. || ( $uri{$uri_p} == '.' ) ) )
  487. {
  488. ++$uri_p;
  489. }
  490.  
  491. $result = ( $uri{$uri_p} == ':' );
  492. }
  493. return $result;
  494. }
  495.  
  496.  
  497. /*
  498. * This function returns an associative array returning any of the various components of the URL that are present. This includes the
  499. * $arr=parse_url($url)
  500. * scheme - e.g. http
  501. * host
  502. * port
  503. * user
  504. * pass
  505. * path
  506. * query - after the question mark ?
  507. * fragment - after the hashmark #
  508. *
  509. * @param string $uri
  510. * @param string $buffer
  511. * @param string &$scheme
  512. * @param string &$authority
  513. * @param string &$path
  514. * @param string &$query
  515. * @param string &$fragment
  516. * @access private
  517. */
  518. function _parse_uri($uri,$buffer,&$scheme,&$authority,&$path,&$query,&$fragment ) {
  519. $parsed=parse_url($uri);
  520. if(isset($parsed['scheme'])) {
  521. $scheme=$parsed['scheme'];
  522. } else {
  523. $scheme='';
  524. }
  525. if(isset($parsed['host'])) {
  526. $host=$parsed['host'];
  527. } else {
  528. $host='';
  529. }
  530. if(isset($parsed['host'])) {
  531. $authority=$parsed['host'];
  532. } else {
  533. $authority='';
  534. }
  535. if(isset($parsed['path'])) {
  536. $path=$parsed['path'];
  537. } else {
  538. $path='';
  539. }
  540. if(isset($parsed['query'])) {
  541. $query=$parsed['query'];
  542. } else {
  543. $query='';
  544. }
  545. if(isset($parsed['fragment'])) {
  546. $fragment=$parsed['fragment'];
  547. } else {
  548. $fragment='';
  549. }
  550.  
  551. }
  552.  
  553. /**
  554. * @param string $base_uri
  555. * @param string $reference_uri
  556. * @param string &$buffer
  557. * @access private
  558. */
  559. function _resolve_uri_reference($base_uri,$reference_uri,&$buffer )
  560. {
  561. if ($reference_uri == '')
  562. return ($buffer = preg_replace("/\#[^\/\\\]*$/", '', $base_uri));
  563. $base_buffer='';
  564. $reference_buffer='';
  565. $path_buffer='';
  566.  
  567. $buffer = '';
  568.  
  569. $this->_parse_uri($reference_uri,
  570. $reference_buffer,
  571. $reference_scheme,
  572. $reference_authority,
  573. $reference_path,
  574. $reference_query,
  575. $reference_fragment );
  576. $this->_parse_uri($base_uri,
  577. $base_buffer,
  578. $base_scheme,
  579. $base_authority,
  580. $base_path,
  581. $base_query,
  582. $base_fragment );
  583. if( $reference_scheme == ''
  584. && $reference_authority == ''
  585. && $reference_path == ''
  586. && $reference_query == '' )
  587. {
  588. $buffer=$base_uri;
  589.  
  590. if( $reference_fragment != '' )
  591. {
  592. if ($base_path == '' || $base_path == '/' || $base_path == "\\") {
  593. $buffer = $this->rdf_parser['document_base_uri'];
  594. }
  595. else
  596. {
  597. $buffer = preg_replace("/\#[^\/\\\]*$/", '', $base_uri);
  598. }
  599. // CB: Changed for base URI
  600. $c = substr($buffer, strlen($buffer)-1 ,1);
  601. if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
  602. $buffer.= '#' ;
  603. $buffer.=$reference_fragment;
  604. }
  605. }
  606. else if( $reference_scheme != '' )
  607. {
  608. $buffer=$reference_uri;
  609. }
  610. else
  611. {
  612. $result_scheme = $base_scheme;
  613. $result_path = '';
  614. if( $reference_authority != '' )
  615. {
  616. $result_authority = $reference_authority;
  617. }
  618. else
  619. {
  620. $result_authority = $base_authority;
  621. if ($reference_path != '')
  622. {
  623. if ($reference_path{0} == '/' || $reference_path{0} == "\\")
  624. {
  625. if ($reference_path{1} == '/' || $reference_path{1} == "\\")
  626. {
  627. $result_authority = '';
  628. $result_path = $reference_path;
  629. }
  630. else
  631. $result_path = $reference_path;
  632. }
  633. elseif (substr($reference_path, 0, 3) == '../' ||
  634. substr($reference_path, 0, 3) == '..\\')
  635. {
  636. $slash = $reference_path{2};
  637. while($base_path != '' && ( substr($reference_path, 0, 3) == '../'
  638. || substr($reference_path, 0, 3) == '..\\'))
  639. {
  640. $base_path = preg_replace("/((\/)|(\\\))[^\/\\\]*$/", '', $base_path);
  641. if ($base_path != '') {
  642. $base_path = preg_replace("/((\/)|(\\\))[^\/\\\]*$/", '', $base_path);
  643. $reference_path = substr($reference_path, 3);
  644. }
  645. }
  646. $result_path = $base_path .$slash .$reference_path;
  647. }
  648. else
  649. {
  650. if ($base_path)
  651. $result_path = preg_replace("/[^\/\\\]*$/", $reference_path, $base_path, 1);
  652. else
  653. $result_path = '/' .$reference_path;
  654. }
  655. }
  656. }
  657. if( $result_scheme != '' )
  658. {
  659. $buffer=$result_scheme;
  660. $buffer.=':';
  661. }
  662.  
  663. if( $result_authority != '' )
  664. {
  665. $buffer.="//";
  666. $buffer.=$result_authority;
  667. }
  668.  
  669. if( $result_path != '' )
  670. {
  671. $buffer.=$result_path;
  672. }
  673.  
  674. if( $reference_query != '' )
  675. {
  676. $buffer.='?';
  677. $buffer.=$reference_query;
  678. }
  679.  
  680. if( $reference_fragment != '' )
  681. {
  682. $buffer.='#';
  683. $buffer.=$reference_fragment;
  684. }
  685. }
  686. }
  687.  
  688.  
  689. /**
  690. * IDs which contain CombiningChars or Extenders
  691. * (see http://www.w3.org/TR/REC-xml-names/#NT-NCName) are assumed to be invalid.
  692. * If you want to use IDs containing these characters you can turn off
  693. * the validating by setting the constant VALIDATE_IDS to FALSE (see constants.php).
  694. *
  695. * @param string $id
  696. * @access private
  697. */
  698. function is_valid_id($id )
  699. {
  700. if (!VALIDATE_IDS)
  701. return TRUE;
  702. $result = FALSE;
  703. if( $id )
  704. {
  705. if( $this->_istalpha($id{0}) || $id{0} == '_')
  706. {
  707. $result = TRUE;
  708. $i=0;
  709. $len = strlen($id);
  710. while( $result != FALSE && ++$i < $len )
  711. {
  712. if( !($this->_istalnum( $id{$i})
  713. || $id{$i} == '.'
  714. || $id{$i} == '-'
  715. || $id{$i} == '_'))
  716. {
  717. $result = FALSE;
  718. }
  719. }
  720. }
  721. }
  722. if (!$result)
  723. $this->_report_error('illegal ID, nodeID or bagID attribute value');
  724. else
  725. return TRUE;
  726. }
  727.  
  728. /**
  729. * @param string $id
  730. * @param string &$buffer
  731. * @access private
  732. */
  733. function _resolve_id($id,&$buffer )
  734. {
  735. $id_buffer='';
  736.  
  737. if( $this->is_valid_id($id) )
  738. {
  739. $id_buffer="#$id";
  740. }
  741.  
  742. $this->_resolve_uri_reference( $this->rdf_get_base(), $id_buffer, $buffer );
  743. }
  744.  
  745. /**
  746. * @param string $name
  747. * @param string &$buffer
  748. * @param string &$namespace_uri
  749. * @param string &$local_name
  750. * @access private
  751. */
  752. function _split_name($name, &$buffer, &$namespace_uri, &$local_name )
  753. {
  754. static $nul = 0;
  755. $buffer=$name;
  756.  
  757. if( strstr( $buffer, NAMESPACE_SEPARATOR_CHAR ) )
  758. {
  759. $cosas=explode(NAMESPACE_SEPARATOR_CHAR,$buffer);
  760. $namespace_uri = $cosas[0];
  761. $local_name = $cosas[1];
  762. }
  763. else
  764. {
  765. if( ( $buffer{ 0 } == 'x' )
  766. && ( $buffer{ 1 } == 'm' )
  767. && ( $buffer{ 2 } == 'l' )
  768. && ( $buffer{ 3 } == ':' ) )
  769. {
  770. $namespace_uri = XML_NAMESPACE_URI;
  771. $local_name = substr($buffer,4);
  772. }
  773. else
  774. {
  775. $namespace_uri = '';
  776. $local_name = $buffer;
  777. }
  778. }
  779. }
  780. /**
  781. * @param string &$buf
  782. * @access private
  783. */
  784. function _generate_anonymous_uri(&$buf )
  785. {
  786. $id='';
  787. if(!isset($this->rdf_parser['anonymous_id'])) {
  788. $this->rdf_parser['anonymous_id']=0;
  789. }
  790. $this->rdf_parser['anonymous_id']++;
  791.  
  792. $buf= BNODE_PREFIX . $this->rdf_parser['anonymous_id'];
  793.  
  794. }
  795. /**
  796. * @param string $subject_type
  797. * @param string $subject
  798. * @param string $predicate
  799. * @param string $ordinal
  800. * @param string $object_type
  801. * @param string $object
  802. * @param string $xml_lang
  803. * @param string $bag_id
  804. * @param string $statements
  805. * @param string $statement_id
  806. * @access private
  807. */
  808. function _report_statement( $subject_type, $subject, $predicate, $ordinal, $object_type, $object, $xml_lang, $bag_id, $statements, $statement_id, $datatype )
  809. {
  810. $statement_id_type = RDF_SUBJECT_TYPE_URI;
  811. $statement_id_buffer='';
  812. $predicate_buffer='';
  813. if (!$xml_lang && $object_type == RDF_OBJECT_TYPE_LITERAL && isset($this->rdf_parser['document_xml_lang']))
  814. $xml_lang = $this->rdf_parser['document_xml_lang'];
  815. // call add statement
  816. $this->add_statement_to_model($this->rdf_parser['user_data'],$subject_type,$subject,$predicate,$ordinal,$object_type,$object,$xml_lang, $datatype );
  817.  
  818. if( $bag_id )
  819. {
  820. if( $statements == '' )
  821. {
  822. $this->_report_statement(RDF_SUBJECT_TYPE_URI,
  823. $bag_id,
  824. RDF_NAMESPACE_URI.RDF_TYPE,
  825. 0,
  826. RDF_OBJECT_TYPE_RESOURCE,
  827. RDF_NAMESPACE_URI.RDF_BAG,
  828. '',
  829. '',
  830. '',
  831. '',
  832. $datatype );
  833. }
  834.  
  835. if( ! $statement_id )
  836. {
  837. $statement_id_type = RDF_SUBJECT_TYPE_BNODE;
  838. $this->_generate_anonymous_uri( $statement_id_buffer );
  839. $statement_id = $statement_id_buffer;
  840. }
  841. $statements++;
  842. $predicate_buffer='RDF_NAMESPACE_URI_'.$statements;
  843.  
  844. $this->_report_statement(
  845. RDF_SUBJECT_TYPE_URI,
  846. $bag_id,
  847. $predicate_buffer,
  848. $statements,
  849. RDF_OBJECT_TYPE_BNODE,
  850. $statement_id,
  851. '',
  852. '',
  853. '',
  854. '',
  855. $datatype );
  856. }
  857.  
  858. if( $statement_id )
  859. {
  860. // rdf:type = rdf:Statement
  861. $this->_report_statement(
  862. $statement_id_type,
  863. $statement_id,
  864. RDF_NAMESPACE_URI.RDF_TYPE,
  865. 0,
  866. RDF_OBJECT_TYPE_RESOURCE,
  867. RDF_NAMESPACE_URI.RDF_STATEMENT,
  868. '',
  869. '',
  870. '',
  871. '',
  872. $datatype );
  873. if ($subject_type == RDF_SUBJECT_TYPE_BNODE)
  874. $obj_type = RDF_OBJECT_TYPE_BNODE;
  875. else
  876. $obj_type = RDF_OBJECT_TYPE_RESOURCE;
  877. // rdf:subject
  878. $this->_report_statement(
  879. $statement_id_type,
  880. $statement_id,
  881. RDF_NAMESPACE_URI.RDF_SUBJECT,
  882. 0,
  883. $obj_type,
  884. $subject,
  885. '',
  886. '',
  887. '',
  888. '',
  889. $datatype );
  890.  
  891. // rdf:predicate
  892. $this->_report_statement(
  893. $statement_id_type,
  894. $statement_id,
  895. RDF_NAMESPACE_URI.RDF_PREDICATE,
  896. 0,
  897. RDF_OBJECT_TYPE_RESOURCE,
  898. $predicate,
  899. '',
  900. '',
  901. '',
  902. '',
  903. $datatype );
  904.  
  905. // rdf:object
  906. $this->_report_statement(
  907. $statement_id_type,
  908. $statement_id,
  909. RDF_NAMESPACE_URI.RDF_OBJECT,
  910. 0,
  911. $object_type,
  912. $object,
  913. '',
  914. '',
  915. '',
  916. '',
  917. $datatype );
  918. }
  919. }
  920. /**
  921. * @param string $subject_type
  922. * @param string $subject
  923. * @param string $attributes
  924. * @param string $xml_lang
  925. * @param string $bag_id
  926. * @param string $statements
  927. * @access private
  928. */
  929. function _handle_property_attributes($subject_type, $subject, $attributes, $xml_lang, $bag_id, $statements )
  930. {
  931. $i=0;
  932.  
  933. $attribute='';
  934. $predicate='';
  935.  
  936. $attribute_namespace_uri='';
  937. $attribute_local_name='';
  938. $attribute_value='';
  939.  
  940. $ordinal=0;
  941.  
  942. for( $i = 0; isset($attributes[ $i ]); $i += 2 )
  943. {
  944. $this->_split_name(
  945. $attributes[ $i ],
  946. $attribute,
  947. $attribute_namespace_uri,
  948. $attribute_local_name );
  949.  
  950. $attribute_value = $attributes[ $i + 1 ];
  951.  
  952. $predicate=$attribute_namespace_uri;
  953. $predicate.=$attribute_local_name;
  954.  
  955. if( RDF_NAMESPACE_URI == $attribute_namespace_uri )
  956. {
  957. if( $this->_is_rdf_property_attribute_literal( $attribute_local_name ) )
  958. {
  959. $this->_report_statement(
  960. $subject_type,
  961. $subject,
  962. $predicate,
  963. 0,
  964. RDF_OBJECT_TYPE_LITERAL,
  965. $attribute_value,
  966. $xml_lang,
  967. $bag_id,
  968. $statements,
  969. '',
  970. '');
  971. }
  972. else if( $this->_is_rdf_property_attribute_resource( $attribute_local_name ) )
  973. {
  974. $this->_report_statement(
  975. $subject_type,
  976. $subject,
  977. $predicate,
  978. 0,
  979. RDF_OBJECT_TYPE_RESOURCE,
  980. $attribute_value,
  981. '',
  982. $bag_id,
  983. $statements,
  984. '',
  985. '');
  986. }
  987. else if( ( $ordinal = $this->_is_rdf_ordinal( $attribute_local_name ) ) != 0 )
  988. {
  989. $this->_report_statement(
  990. $subject_type,
  991. $subject,
  992. $predicate,
  993. $ordinal,
  994. RDF_OBJECT_TYPE_LITERAL,
  995. $attribute_value,
  996. $xml_lang,
  997. $bag_id,
  998. $statements,
  999. '',
  1000. '' );
  1001. }
  1002. else if ( ($attribute_local_name != RDF_ABOUT)
  1003. && ($attribute_local_name != RDF_RDF)
  1004. && ($attribute_local_name != RDF_DESCRIPTION)
  1005. && ($attribute_local_name != RDF_ID)
  1006. && ($attribute_local_name != RDF_ABOUT_EACH)
  1007. && ($attribute_local_name != RDF_ABOUT_EACH_PREFIX)
  1008. && ($attribute_local_name != RDF_BAG_ID)
  1009. && ($attribute_local_name != RDF_RESOURCE)
  1010. && ($attribute_local_name != RDF_PARSE_TYPE)
  1011. && ($attribute_local_name != RDF_PARSE_TYPE_LITERAL)
  1012. && ($attribute_local_name != RDF_PARSE_TYPE_RESOURCE)
  1013. && ($attribute_local_name != RDF_LI)
  1014. && ($attribute_local_name != RDF_SUBJECT)
  1015. && ($attribute_local_name != RDF_PREDICATE)
  1016. && ($attribute_local_name != RDF_OBJECT)
  1017. && ($attribute_local_name != RDF_NODEID)
  1018. && ($attribute_local_name != RDF_DATATYPE)
  1019. && ($attribute_local_name != RDF_SEEALSO)
  1020. && ($attribute_local_name != RDF_NIL)
  1021. && ($attribute_local_name != RDF_REST)
  1022. && ($attribute_local_name != RDF_FIRST)
  1023. )
  1024. {
  1025. $this->_report_statement(
  1026. $subject_type,
  1027. $subject,
  1028. $predicate,
  1029. 0,
  1030. RDF_OBJECT_TYPE_LITERAL,
  1031. $attribute_value,
  1032. $xml_lang,
  1033. $bag_id,
  1034. $statements,
  1035. '',
  1036. '' );
  1037. }
  1038. }
  1039. else if( XML_NAMESPACE_URI == $attribute_namespace_uri )
  1040. {
  1041. if ($attribute_local_name == 'base')
  1042. {
  1043. $this->rdf_parser['top']['element_base_uri'] = $attribute_value;
  1044. }
  1045. }
  1046. else if( $attribute_namespace_uri )
  1047. {
  1048. // is it required that property attributes be in an explicit namespace?
  1049.  
  1050. $this->_report_statement(
  1051. $subject_type,
  1052. $subject,
  1053. $predicate,
  1054. 0,
  1055. RDF_OBJECT_TYPE_LITERAL,
  1056. $attribute_value,
  1057. $xml_lang,
  1058. $bag_id,
  1059. $statements,
  1060. '',
  1061. '' );
  1062. }
  1063. }
  1064. }
  1065.  
  1066.  
  1067.  
  1068. /**
  1069. * @param string $warning
  1070. * @access private
  1071. */
  1072. function _report_warning($warning)
  1073. {
  1074. $errmsg = RDFAPI_ERROR . '(class: parser): ' . $warning .'.';
  1075. trigger_error($errmsg, E_USER_WARNING);
  1076. }
  1077.  
  1078.  
  1079. function _report_error($error)
  1080. {
  1081. $errmsg = RDFAPI_ERROR . '(class: parser): ' . $error .'.';
  1082. trigger_error($errmsg, E_USER_ERROR);
  1083. }
  1084.  
  1085.  
  1086. /**
  1087. * @param string $namespace_uri
  1088. * @param string $local_name
  1089. * @param string $attributes
  1090. * @param string $parent
  1091. * @access private
  1092. */
  1093. function _handle_resource_element( $namespace_uri, $local_name, $attributes, $parent )
  1094. {
  1095. $subjects_found = 0;
  1096. $aux=$attributes;
  1097. $aux2=Array();
  1098. foreach($attributes as $atkey=>$atvalue) {
  1099. $aux2[]=$atkey;
  1100. $aux2[]=$atvalue;
  1101. }
  1102. $attributes=$aux2;
  1103. $id = '';
  1104. $about = '';
  1105.  
  1106. $bag_id = '';
  1107. $node_id = '';
  1108. $datatype = '';
  1109.  
  1110. $i=0;
  1111.  
  1112. $attribute='';
  1113.  
  1114. $attribute_namespace_uri='';
  1115. $attribute_local_name='';
  1116. $attribute_value='';
  1117.  
  1118. $id_buffer='';
  1119.  
  1120. $type='';
  1121.  
  1122. $this->rdf_parser['top']['has_property_attributes'] = false;
  1123. $this->rdf_parser['top']['has_member_attributes'] = false;
  1124.  
  1125. if( $namespace_uri == RDF_NAMESPACE_URI )
  1126. {
  1127. if( ! $this->_is_rdf_node_element( $local_name ) )
  1128. {
  1129. $msg = 'unknown or out of context rdf node element: '.$local_name;
  1130. if ($this->_is_forbidden_rdf_node_element($local_name))
  1131. $this->_report_error($msg);
  1132. else
  1133. $this->_report_warning($msg);
  1134. }
  1135. }
  1136.  
  1137. // examine each attribute for the standard RDF "keywords"
  1138. for( $i = 0; isset($attributes[$i]); $i += 2 )
  1139. {
  1140. $this->_split_name(
  1141. $attributes[ $i ],
  1142. $attribute,
  1143. $attribute_namespace_uri,
  1144. $attribute_local_name );
  1145.  
  1146. $attribute_value = $attributes[ $i + 1 ];
  1147.  
  1148. // if the attribute is not in any namespace
  1149. // or the attribute is in the RDF namespace
  1150. if( ( $attribute_namespace_uri == '' )
  1151. || ( $attribute_namespace_uri == RDF_NAMESPACE_URI ))
  1152. {
  1153. if( $attribute_local_name == RDF_ID )
  1154. {
  1155. $id = $attribute_value;
  1156. ++$subjects_found;
  1157. } else if( $attribute_local_name == RDF_ABOUT ) {
  1158. $about = '_'.$attribute_value;
  1159. ++$subjects_found;
  1160. } else if( $attribute_local_name == RDF_NODEID) {
  1161. $node_id = $attribute_value;
  1162. ++$subjects_found;
  1163. } else if( $attribute_local_name == RDF_ABOUT_EACH ) {
  1164. $error = 'aboutEach has been removed from the RDF specifications';
  1165. $this->_report_error($error);
  1166. } else if( $attribute_local_name == RDF_ABOUT_EACH_PREFIX ) {
  1167. $error = 'aboutEachPrefix has been removed from the RDF specifications';
  1168. $this->_report_error($error);
  1169. } else if( $attribute_local_name == RDF_BAG_ID) {
  1170. $bag_id = $attribute_value;
  1171. } else if( $attribute_local_name == RDF_DATATYPE) {
  1172. $datatype = $attribute_value;
  1173. } else if( $this->_is_rdf_property_attribute( $attribute_local_name )) {
  1174. $this->rdf_parser['top']['has_property_attributes'] = true;
  1175. } else if( $this->_is_rdf_ordinal( $attribute_local_name )) {
  1176. $this->rdf_parser['top']['has_property_attributes'] = true;
  1177. $this->rdf_parser['top']['has_member_attributes'] = true;
  1178. } else {
  1179. $this->rdf_parser['top']['has_property_attributes'] = true;
  1180. $msg = 'unknown or out of context rdf attribute: '.$attribute_local_name;
  1181. if ($this->_is_forbidden_rdf_property_attribute($attribute_local_name))
  1182. $this->_report_error($msg);
  1183. else
  1184. $this->_report_warning($msg);
  1185. }
  1186. }
  1187. else if( $attribute_namespace_uri == XML_NAMESPACE_URI )
  1188. {
  1189. if( $attribute_local_name == XML_LANG )
  1190. {
  1191. $this->rdf_parser['top']['xml_lang'] = $attribute_value;
  1192. }
  1193. elseif ($attribute_local_name == 'base')
  1194. {
  1195. $this->rdf_parser['top']['element_base_uri'] = $attribute_value;
  1196. }
  1197. }
  1198. else if( $attribute_namespace_uri )
  1199. {
  1200. $this->rdf_parser['top']['has_property_attributes'] = true;
  1201. }
  1202. }
  1203.  
  1204. // if no subjects were found, generate one.
  1205. if( $subjects_found == 0 )
  1206. {
  1207. $this->_generate_anonymous_uri( $id_buffer );
  1208. $this->rdf_parser['top']['subject']=$id_buffer;
  1209. $this->rdf_parser['top']['subject_type'] = RDF_SUBJECT_TYPE_BNODE;
  1210. }
  1211. else if( $subjects_found > 1 )
  1212. {
  1213. $this->_report_error('ID, about and nodeID are mutually exclusive');
  1214. }
  1215. else if( $id )
  1216. {
  1217. $this->_resolve_id( $id, $id_buffer );
  1218. $this->rdf_parser['top']['subject_type'] = RDF_SUBJECT_TYPE_URI;
  1219. $this->rdf_parser['top']['subject']=$id_buffer;
  1220. }
  1221. else if( $about )
  1222. {
  1223. $this->_resolve_uri_reference( $this->rdf_get_base(), substr($about,1), $id_buffer );
  1224. $this->rdf_parser['top']['subject_type'] = RDF_SUBJECT_TYPE_URI;
  1225. $this->rdf_parser['top']['subject']=$id_buffer;
  1226. }
  1227. else if( $node_id )
  1228. {
  1229. $this->is_valid_id($node_id);
  1230. $this->rdf_parser['top']['subject_type'] = RDF_SUBJECT_TYPE_BNODE;
  1231. $this->rdf_parser['top']['subject']=$node_id;
  1232. }
  1233. // if the subject is empty, assign it the document uri
  1234. if( $this->rdf_parser['top']['subject'] == '' )
  1235. {
  1236. $this->rdf_parser['top']['subject']=$this->rdf_get_base();
  1237. }
  1238.  
  1239. if( $bag_id )
  1240. {
  1241. $this->_resolve_id( $bag_id, $id_buffer );
  1242. $this->rdf_parser['top']['bag_id']=$id_buffer;
  1243. }
  1244.  
  1245. // only report the type for non-rdf:Description elements.
  1246. if( ($local_name != RDF_DESCRIPTION )
  1247. || ( $namespace_uri != RDF_NAMESPACE_URI ) )
  1248. {
  1249. $type=$namespace_uri;
  1250. $type.=$local_name;
  1251.  
  1252. $this->_report_statement(
  1253. $this->rdf_parser['top']['subject_type'],
  1254. $this->rdf_parser['top']['subject'],
  1255. RDF_NAMESPACE_URI.RDF_TYPE,
  1256. 0,
  1257. RDF_OBJECT_TYPE_RESOURCE,
  1258. $type,
  1259. '',
  1260. $this->rdf_parser['top']['bag_id'],
  1261. $this->rdf_parser['top']['statements'],
  1262. '',
  1263. $datatype);
  1264.  
  1265. }
  1266.  
  1267. // if this element is the child of some property,
  1268. // report the appropriate statement.
  1269. if( $parent )
  1270. {
  1271. if ($this->rdf_parser['top']['subject_type'] == RDF_SUBJECT_TYPE_BNODE)
  1272. $objtype = RDF_OBJECT_TYPE_BNODE;
  1273. else
  1274. $objtype = RDF_OBJECT_TYPE_RESOURCE;
  1275. $this->_report_statement(
  1276. $parent['parent']['subject_type'],
  1277. $parent['parent']['subject'],
  1278. $parent['predicate'],
  1279. $parent['ordinal'],
  1280. $objtype,
  1281. $this->rdf_parser['top']['subject'],
  1282. '',
  1283. $parent['parent']['bag_id'],
  1284. $parent['parent']['statements'],
  1285. $parent['statement_id'],
  1286. $parent['datatype']);
  1287.  
  1288. }
  1289.  
  1290. if( $this->rdf_parser['top']['has_property_attributes'] )
  1291. {
  1292. $this->_handle_property_attributes(
  1293. $this->rdf_parser['top']['subject_type'],
  1294. $this->rdf_parser['top']['subject'],
  1295. $attributes,
  1296. $this->rdf_parser['top']['xml_lang'],
  1297. $this->rdf_parser['top']['bag_id'],
  1298. $this->rdf_parser['top']['statements'] );
  1299. }
  1300. }
  1301.  
  1302. /**
  1303. * @param string &$namespace_uri
  1304. * @param string &$local_name
  1305. * @param string &$attributes
  1306. * @access private
  1307. */
  1308. function _handle_property_element( &$namespace_uri, &$local_name, &$attributes )
  1309. {
  1310. $buffer='';
  1311.  
  1312. $i=0;
  1313.  
  1314. $aux=$attributes;
  1315. $aux2=Array();
  1316. foreach($attributes as $atkey=>$atvalue) {
  1317. $aux2[]=$atkey;
  1318. $aux2[]=$atvalue;
  1319. }
  1320. $attributes=$aux2;
  1321.  
  1322. $attribute_namespace_uri='';
  1323. $attribute_local_name='';
  1324. $attribute_value = '';
  1325.  
  1326. $resource = NULL;
  1327. $statement_id = '';
  1328. $bag_id = '';
  1329. $parse_type = '';
  1330. $node_id = '';
  1331. $datatype = '';
  1332.  
  1333. $this->rdf_parser['top']['ordinal'] = 0;
  1334.  
  1335. if( $namespace_uri == RDF_NAMESPACE_URI )
  1336. {
  1337. if( ! $this->_is_rdf_property_element( $local_name ) )
  1338. {
  1339. $msg = 'unknown or out of context rdf property element: '.$local_name;
  1340. if ($this->_is_forbidden_rdf_property_element($local_name))
  1341. $this->_report_error($msg);
  1342. else
  1343. $this->_report_warning($msg);
  1344. }
  1345. }
  1346.  
  1347. $buffer=$namespace_uri;
  1348.  
  1349. if( ( $namespace_uri == RDF_NAMESPACE_URI )
  1350. && ( $local_name == RDF_LI ) )
  1351. {
  1352. $this->rdf_parser['top']['parent']['members']++;
  1353. $this->rdf_parser['top']['ordinal'] = $this->rdf_parser['top']['parent']['members'];
  1354.  
  1355. $this->rdf_parser['top']['ordinal']=$this->rdf_parser['top']['ordinal'];
  1356.  
  1357. $buffer.='_'.$this->rdf_parser['top']['ordinal'];
  1358. }
  1359. else
  1360. {
  1361. $buffer.=$local_name;
  1362. }
  1363.  
  1364. $this->rdf_parser['top']['predicate']=$buffer;
  1365.  
  1366. $this->rdf_parser['top']['has_property_attributes'] = false;
  1367. $this->rdf_parser['top']['has_member_attributes'] = false;
  1368.  
  1369. for( $i = 0; isset($attributes[$i]); $i += 2 )
  1370. {
  1371. $this->_split_name(
  1372. $attributes[$i],
  1373. $buffer,
  1374. $attribute_namespace_uri,
  1375. $attribute_local_name );
  1376.  
  1377. $attribute_value = $attributes[$i + 1];
  1378.  
  1379. // if the attribute is not in any namespace
  1380. // or the attribute is in the RDF namespace
  1381. if( ( $attribute_namespace_uri == '' )
  1382. || ( $attribute_namespace_uri == RDF_NAMESPACE_URI ) )
  1383. {
  1384. if( ( $attribute_local_name == RDF_ID ) )
  1385. {
  1386. $statement_id = $attribute_value;
  1387. }
  1388. else if( $attribute_local_name == RDF_PARSE_TYPE )
  1389. {
  1390. $parse_type = $attribute_value;
  1391. }
  1392. else if( $attribute_local_name == RDF_RESOURCE )
  1393. {
  1394. $resource = $attribute_value;
  1395. }
  1396. else if( $attribute_local_name == RDF_NODEID )
  1397. {
  1398. $node_id = $attribute_value;
  1399. }
  1400. else if( $attribute_local_name == RDF_BAG_ID )
  1401. {
  1402. $bag_id = $attribute_value;
  1403. }
  1404. else if( $attribute_local_name == RDF_DATATYPE )
  1405. {
  1406. $datatype = $attribute_value;
  1407. $this->rdf_parser['top']['datatype'] = $attribute_value;
  1408. }
  1409. else if( $this->_is_rdf_property_attribute( $attribute_local_name ) )
  1410. {
  1411. $this->rdf_parser['top']['has_property_attributes'] = true;
  1412. }
  1413. else
  1414. {
  1415. $this->_report_warning('unknown rdf attribute: '.$attribute_local_name );
  1416. return;
  1417. }
  1418. }
  1419. else if( $attribute_namespace_uri == XML_NAMESPACE_URI )
  1420. {
  1421. if( $attribute_local_name == XML_LANG )
  1422. {
  1423. $this->rdf_parser['top']['xml_lang'] = $attribute_value;
  1424. }
  1425. elseif ($attribute_local_name == 'base')
  1426. {
  1427. $this->rdf_parser['top']['element_base_uri'] = $attribute_value;
  1428. }
  1429. }
  1430. else if( $attribute_namespace_uri )
  1431. {
  1432. $this->rdf_parser['top']['has_property_attributes'] = true;
  1433. }
  1434. }
  1435.  
  1436. if( $statement_id )
  1437. {
  1438. $this->_resolve_id($statement_id, $buffer );
  1439. $this->rdf_parser['top']['statement_id']=$buffer;
  1440. }
  1441. if ($node_id)
  1442. {
  1443. $this->is_valid_id($node_id);
  1444. if ($resource)
  1445. {
  1446. $this->_report_error('nodeID and resource are mutually exclusive');
  1447. }
  1448. if ($statement_id)
  1449. {
  1450. // reify statement
  1451. $this->_report_statement(
  1452. $this->rdf_parser['top']['parent']['subject_type'],
  1453. $this->rdf_parser['top']['parent']['subject'],
  1454. $this->rdf_parser['top']['predicate'],
  1455. $this->rdf_parser['top']['ordinal'],
  1456. RDF_OBJECT_TYPE_BNODE,
  1457. $node_id,
  1458. '',
  1459. $this->rdf_parser['top']['parent']['bag_id'],
  1460. $this->rdf_parser['top']['parent']['statements'],
  1461. $this->rdf_parser['top']['statement_id'],
  1462. '');
  1463. $statement_id = '';
  1464. }
  1465. else
  1466. {
  1467. $this->_report_statement(
  1468. $this->rdf_parser['top']['parent']['subject_type'],
  1469. $this->rdf_parser['top']['parent']['subject'],
  1470. $this->rdf_parser['top']['predicate'],
  1471. $this->rdf_parser['top']['ordinal'],
  1472. RDF_OBJECT_TYPE_BNODE,
  1473. $node_id,
  1474. '',
  1475. $this->rdf_parser['top']['parent']['bag_id'],
  1476. $this->rdf_parser['top']['parent']['statements'],
  1477. '',
  1478. $datatype );
  1479. }
  1480. $this->rdf_parser['top']['state'] = IN_PROPERTY_EMPTY_RESOURCE;
  1481. }
  1482. if( $parse_type )
  1483. {
  1484. if( $resource ) {
  1485. $this->_report_error('property elements with rdf:parseType do not allow rdf:resource' );
  1486. }
  1487.  
  1488. if( $bag_id ) {
  1489. $this->_report_warning('property elements with rdf:parseType do not allow rdf:bagID' );
  1490. return;
  1491. }
  1492.  
  1493. if( $this->rdf_parser['top']['has_property_attributes'] )
  1494. {
  1495. $this->_report_error('property elements with rdf:parseType do not allow property attributes');
  1496. return;
  1497. }
  1498. if( $attribute_value == RDF_PARSE_TYPE_RESOURCE )
  1499. {
  1500. $this->_generate_anonymous_uri( $buffer );
  1501. // since we are sure that this is now a resource property we can report it
  1502. $this->_report_statement(
  1503. $this->rdf_parser['top']['parent']['subject_type'],
  1504. $this->rdf_parser['top']['parent']['subject'],
  1505. $this->rdf_parser['top']['predicate'],
  1506. 0,
  1507. RDF_OBJECT_TYPE_BNODE,
  1508. $buffer,
  1509. '',
  1510. $this->rdf_parser['top']['parent']['bag_id'],
  1511. $this->rdf_parser['top']['parent']['statements'],
  1512. $this->rdf_parser['top']['statement_id'],
  1513. $datatype );
  1514.  
  1515. $this->_push_element( );
  1516.  
  1517. $this->rdf_parser['top']['state'] = IN_PROPERTY_PARSE_TYPE_RESOURCE;
  1518. $this->rdf_parser['top']['subject_type'] = RDF_SUBJECT_TYPE_BNODE;
  1519. $this->rdf_parser['top']['subject']=$buffer;
  1520. $this->rdf_parser['top']['bag_id']='';
  1521. $this->rdf_parser['top']['datatype']= $datatype;
  1522. }
  1523. elseif ( $attribute_value == RDF_PARSE_TYPE_LITERAL )
  1524. {
  1525. $this->rdf_parser['top']['state'] = IN_PROPERTY_PARSE_TYPE_LITERAL;
  1526. $this->rdf_parser['top']['datatype']= RDF_NAMESPACE_URI .RDF_XMLLITERAL;
  1527. $this->rdf_parser['xml_literal']['buffer'] = '';
  1528. $this->rdf_parser['xml_literal']['depth'] = 0;
  1529. }
  1530. elseif ($attribute_value == RDF_PARSE_TYPE_COLLECTION)
  1531. {
  1532. $this->_generate_anonymous_uri( $buffer );
  1533. $this->_report_statement(
  1534. $this->rdf_parser['top']['parent']['subject_type'],
  1535. $this->rdf_parser['top']['parent']['subject'],
  1536. $this->rdf_parser['top']['predicate'],
  1537. 0,
  1538. RDF_OBJECT_TYPE_BNODE,
  1539. $buffer,
  1540. '',
  1541. $this->rdf_parser['top']['parent']['bag_id'],
  1542. $this->rdf_parser['top']['parent']['statements'],
  1543. $this->rdf_parser['top']['statement_id'],
  1544. $datatype );
  1545. $this->rdf_parser['top']['state'] = IN_PROPERTY_PARSE_TYPE_COLLECTION;
  1546. $this->rdf_parser['top']['collection']['first_blank_node_id'] = $buffer;
  1547. }
  1548. else
  1549. {
  1550. $this->_report_statement(
  1551. $this->rdf_parser['top']['parent']['subject_type'],
  1552. $this->rdf_parser['top']['parent']['subject'],
  1553. $this->rdf_parser['top']['predicate'],
  1554. 0,
  1555. RDF_OBJECT_TYPE_XML,
  1556. '',
  1557. '',
  1558. $this->rdf_parser['top']['parent']['bag_id'],
  1559. $this->rdf_parser['top']['parent']['statements'],
  1560. $this->rdf_parser['top']['statement_id'],
  1561. $datatype );
  1562.  
  1563. $this->rdf_parser['top']['state'] = IN_PROPERTY_PARSE_TYPE_LITERAL;
  1564. }
  1565. }
  1566. else if( $resource !== NULL || $bag_id || $this->rdf_parser['top']['has_property_attributes'] )
  1567. {
  1568. if( $resource !== NULL )
  1569. {
  1570. $subject_type = RDF_SUBJECT_TYPE_URI;
  1571. $this->_resolve_uri_reference( $this->rdf_get_base(), $resource, $buffer );
  1572. $object_type=RDF_OBJECT_TYPE_RESOURCE;
  1573. }
  1574. else
  1575. {
  1576. $subject_type = RDF_SUBJECT_TYPE_BNODE;
  1577. $this->_generate_anonymous_uri( $buffer );
  1578. $object_type=RDF_OBJECT_TYPE_BNODE;
  1579. }
  1580. $this->rdf_parser['top']['state'] = IN_PROPERTY_EMPTY_RESOURCE;
  1581.  
  1582. // since we are sure that this is now a resource property we can report it.
  1583. $this->_report_statement(
  1584. $this->rdf_parser['top']['parent']['subject_type'],
  1585. $this->rdf_parser['top']['parent']['subject'],
  1586. $this->rdf_parser['top']['predicate'],
  1587. $this->rdf_parser['top']['ordinal'],
  1588. $object_type,
  1589. $buffer,
  1590. '',
  1591. $this->rdf_parser['top']['parent']['bag_id'],
  1592. $this->rdf_parser['top']['parent']['statements'],
  1593. $this->rdf_parser['top']['statement_id'],
  1594. $datatype ); // should we allow IDs?
  1595. if( $bag_id )
  1596. {
  1597. $this->_resolve_id( $bag_id, $buffer );
  1598. $this->rdf_parser['top']['bag_id']=$buffer;
  1599. }
  1600.  
  1601. if( $this->rdf_parser['top']['has_property_attributes'] )
  1602. {
  1603. $this->_handle_property_attributes(
  1604. $subject_type,
  1605. $buffer,
  1606. $attributes,
  1607. $this->rdf_parser['top']['xml_lang'],
  1608. $this->rdf_parser['top']['bag_id'],
  1609. $this->rdf_parser['top']['statements'] );
  1610. }
  1611. }
  1612. }
  1613. /**
  1614. * @param string &$namespace_uri
  1615. * @param string &$local_name
  1616. * @param string &$attributes
  1617. * @access private
  1618. */
  1619. function _handle_collection_element(&$namespace_uri, &$local_name, &$attributes)
  1620. {
  1621. $aux2=Array();
  1622. foreach($attributes as $atkey=>$atvalue) {
  1623. $aux2[]=$atkey;
  1624. $aux2[]=$atvalue;
  1625. }
  1626. $attributes=$aux2;
  1627. /* collection construction site
  1628. // old:
  1629. if ( ($namespace_uri == RDF_NAMESPACE_URI || $namespace_uri == '')
  1630. && ($local_name == RDF_DESCRIPTION || $local_name == RDF_LI) )
  1631. {
  1632. for( $i = 0; isset($attributes[$i]); $i += 2 )
  1633. {
  1634. $this->_split_name(
  1635. $attributes[ $i ],
  1636. $attribute,
  1637. $attribute_namespace_uri,
  1638. $attribute_local_name );
  1639.  
  1640. $attribute_value = $attributes[ $i + 1 ];
  1641. if( $attribute_namespace_uri == '' || $attribute_namespace_uri == RDF_NAMESPACE_URI )
  1642. {
  1643. if( $attribute_local_name == RDF_ABOUT ||
  1644. $attribute_local_name == RDF_RESOURCE)
  1645. {
  1646. $this->rdf_parser['top']['parent']['collection']['object_type'][] = RDF_OBJECT_TYPE_RESOURCE;
  1647. }
  1648. elseif ( $attribute_local_name == RDF_NODEID ) {
  1649. $this->rdf_parser['top']['parent']['collection']['object_type'][] = RDF_OBJECT_TYPE_BNODE;
  1650. }
  1651. $this->rdf_parser['top']['parent']['collection']['object_label'][] = $attribute_value;
  1652. }
  1653. }
  1654. }
  1655. */
  1656. // new
  1657.  
  1658. for( $i = 0; isset($attributes[$i]); $i += 2 )
  1659. {
  1660. $this->_split_name(
  1661. $attributes[ $i ],
  1662. $attribute,
  1663. $attribute_namespace_uri,
  1664. $attribute_local_name );
  1665.  
  1666. $attribute_value = $attributes[ $i + 1 ];
  1667. if( $attribute_namespace_uri == '' || $attribute_namespace_uri == RDF_NAMESPACE_URI )
  1668. {
  1669. $tmp_subject_type = RDF_SUBJECT_TYPE_URI;
  1670. if( $attribute_local_name == RDF_ABOUT ||
  1671. $attribute_local_name == RDF_RESOURCE)
  1672. {
  1673. $this->rdf_parser['top']['parent']['collection']['object_type'][] = RDF_OBJECT_TYPE_RESOURCE;
  1674. }
  1675. elseif ( $attribute_local_name == RDF_NODEID ) {
  1676. $this->rdf_parser['top']['parent']['collection']['object_type'][] = RDF_OBJECT_TYPE_BNODE;
  1677. $tmp_subject_type = RDF_SUBJECT_TYPE_BNODE;
  1678. }
  1679. $id_buffer = '';
  1680. $this->_resolve_uri_reference( $this->rdf_get_base(), $attribute_value, $id_buffer );
  1681. $this->rdf_parser['top']['parent']['collection']['object_label'][] = $id_buffer;
  1682. if (!( ($namespace_uri == RDF_NAMESPACE_URI || $namespace_uri == '')
  1683. && ($local_name == RDF_DESCRIPTION || $local_name == RDF_LI) ))
  1684. {
  1685. $this->_report_statement(
  1686. $tmp_subject_type,
  1687. $id_buffer,
  1688. RDF_NAMESPACE_URI.RDF_TYPE,
  1689. '',
  1690. RDF_OBJECT_TYPE_RESOURCE,
  1691. $namespace_uri.$local_name,
  1692. '',
  1693. '',
  1694. '',
  1695. '',
  1696. '');
  1697. }
  1698. }
  1699. }
  1700.  
  1701.  
  1702. // collection construction site
  1703. }
  1704.  
  1705. /**
  1706. * @param string &$namespace_uri
  1707. * @param string &$local_name
  1708. * @param string &$attributes
  1709. * @access private
  1710. */
  1711. function _handle_xml_start_element(&$namespace_uri, &$local_name, &$attributes)
  1712. {
  1713. $aux2=Array();
  1714. foreach($attributes as $atkey=>$atvalue) {
  1715. $aux2[]=$atkey;
  1716. $aux2[]=$atvalue;
  1717. }
  1718. $attributes=$aux2;
  1719. $element = '<' .$this->_join_name_and_declare_prefix($namespace_uri, $local_name);
  1720. for( $i = 0; isset($attributes[$i]); $i += 2 )
  1721. {
  1722. $this->_split_name(
  1723. $attributes[ $i ],
  1724. $attribute,
  1725. $attribute_namespace_uri,
  1726. $attribute_local_name );
  1727.  
  1728. $attribute_value = $attributes[ $i + 1 ];
  1729.  
  1730. $element .= ' ' .$this->_join_name_and_declare_prefix($attribute_namespace_uri, $attribute_local_name);
  1731. $element .= '=\"' .$attribute_value .'\"';
  1732. }
  1733. $element .= '>';
  1734. $this->rdf_parser['xml_literal']['buffer'] .= $element;
  1735. }
  1736.  
  1737. /**
  1738. * @param string $name
  1739. * @access private
  1740. */
  1741. function _handle_xml_end_element($name)
  1742. {
  1743. $buffer='';
  1744. $namespace_uri='';
  1745. $local_name='';
  1746. $this->_split_name(
  1747. $name,
  1748. $buffer,
  1749. $namespace_uri,
  1750. $local_name );
  1751. $element = '</';
  1752. if ($namespace_uri && isset($this->rdf_parser['default_namespace'])
  1753. &&$namespace_uri != $this->rdf_parser['default_namespace'])
  1754. {
  1755. $element .= $this->rdf_parser['namespaces'][$namespace_uri] .':';
  1756. }
  1757. $element .= $local_name .'>';
  1758. $this->rdf_parser['xml_literal']['buffer'] .= $element;
  1759. $depth = $this->rdf_parser['xml_literal']['depth']--;
  1760. if (isset($this->rdf_parser['xml_literal']['declared_ns']))
  1761. foreach ($this->rdf_parser['xml_literal']['declared_ns'] as $prefix => $_depth)
  1762. {
  1763. if ($depth == $_depth)
  1764. unset($this->rdf_parser['xml_literal']['declared_ns'][$prefix]);
  1765. }
  1766. }
  1767.  
  1768. /**
  1769. * @param string $namespace_uri
  1770. * @param string $local_name
  1771. * @access private
  1772. */
  1773. function _join_name_and_declare_prefix($namespace_uri, $local_name) {
  1774. $name = '';
  1775. if ($namespace_uri)
  1776. {
  1777. if (isset($this->rdf_parser['default_namespace'])
  1778. && $namespace_uri == $this->rdf_parser['default_namespace'])
  1779. {
  1780. $name .= $local_name;
  1781. if (!isset($this->rdf_parser['xml_literal']['declared_ns']['_DEFAULT_'])
  1782. && $namespace_uri != XML_NAMESPACE_URI)
  1783. {
  1784. $name .= ' xmlns=' . '\"' .$namespace_uri .'\"';
  1785. $this->rdf_parser['xml_literal']['declared_ns']['_DEFAULT_']
  1786. = $this->rdf_parser['xml_literal']['depth'];
  1787. }
  1788. }
  1789. else
  1790. {
  1791. $ns_prefix = $this->rdf_parser['namespaces'][$namespace_uri];
  1792. $name .= $ns_prefix .':' .$local_name;
  1793. if (!isset($this->rdf_parser['xml_literal']['declared_ns'][$ns_prefix])
  1794. && $namespace_uri != XML_NAMESPACE_URI)
  1795. {
  1796. $name .= " xmlns:$ns_prefix=" . '\"' .$namespace_uri .'\"';
  1797. $this->rdf_parser['xml_literal']['declared_ns'][$ns_prefix]
  1798. = $this->rdf_parser['xml_literal']['depth'];
  1799. }
  1800. }
  1801. }
  1802. else
  1803. $name .= $local_name;
  1804. return $name;
  1805. }
  1806.  
  1807. /**
  1808. * @access private
  1809. */
  1810. function _end_collection() {
  1811. if (isset($this->rdf_parser['top']['collection']))
  1812. {
  1813. $subject = $this->rdf_parser['top']['collection']['first_blank_node_id'];
  1814. for ($i=0; isset($this->rdf_parser['top']['collection']['object_label'][$i]); $i++)
  1815. {
  1816. $this->_report_statement(
  1817. RDF_SUBJECT_TYPE_BNODE,
  1818. $subject,
  1819. RDF_NAMESPACE_URI.RDF_FIRST,
  1820. '',
  1821. $this->rdf_parser['top']['collection']['object_type'][$i],
  1822. $this->rdf_parser['top']['collection']['object_label'][$i],
  1823. '',
  1824. '',
  1825. '',
  1826. '',
  1827. '');
  1828.  
  1829. if (!isset($this->rdf_parser['top']['collection']['object_label'][$i+1]))
  1830. {
  1831. $obj_type_2 = RDF_OBJECT_TYPE_RESOURCE;
  1832. $object_2 = RDF_NAMESPACE_URI.RDF_NIL;
  1833. }
  1834. else
  1835. {
  1836. $obj_type_2= RDF_OBJECT_TYPE_BNODE;
  1837. $this->_generate_anonymous_uri($object_2);
  1838. }
  1839. $this->_report_statement(
  1840. RDF_SUBJECT_TYPE_BNODE,
  1841. $subject,
  1842. RDF_NAMESPACE_URI.RDF_REST,
  1843. '',
  1844. $obj_type_2,
  1845. $object_2,
  1846. '',
  1847. '',
  1848. '',
  1849. '',
  1850. '');
  1851.  
  1852. $subject = $object_2;
  1853. }
  1854. }
  1855. }
  1856.  
  1857. /**
  1858. * @param string $parser
  1859. * @param string $name
  1860. * @param string $attributes
  1861. * @access private
  1862. */
  1863. function _start_element_handler($parser, $name, $attributes )
  1864. {
  1865. $buffer='';
  1866.  
  1867. $namespace_uri='';
  1868. $local_name='';
  1869.  
  1870. $this->_push_element();
  1871.  
  1872.  
  1873. $this->_split_name(
  1874. $name,
  1875. $buffer,
  1876. $namespace_uri,
  1877. $local_name );
  1878.  
  1879. switch( $this->rdf_parser['top']['state'] )
  1880. {
  1881. case IN_TOP_LEVEL:
  1882. // set base_uri, if possible
  1883. foreach ($attributes as $key => $value) {
  1884. if($key == XML_NAMESPACE_URI . NAMESPACE_SEPARATOR_CHAR . 'base') {
  1885. $this->rdf_parser['base_uri'] = $value;
  1886. $this->rdf_parser['document_base_uri'] = $value;
  1887. $c = substr($value, strlen($value)-1 ,1);
  1888. if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
  1889. $this->rdf_parser['normalized_base_uri'] = $value . '#';
  1890. else
  1891. $this->rdf_parser['normalized_base_uri'] = $value;
  1892. }
  1893. elseif ($key == XML_NAMESPACE_URI . NAMESPACE_SEPARATOR_CHAR .'lang')
  1894. $this->rdf_parser['document_xml_lang'] = $value;
  1895. echo "";
  1896. }
  1897. if( RDF_NAMESPACE_URI.NAMESPACE_SEPARATOR_STRING.RDF_RDF == $name )
  1898. {
  1899. $this->rdf_parser['top']['state'] = IN_RDF;
  1900.  
  1901. break;
  1902. }
  1903. case IN_RDF:
  1904. $this->rdf_parser['top']['state'] = IN_DESCRIPTION;
  1905. $this->_handle_resource_element( $namespace_uri, $local_name, $attributes, '' );
  1906. break;
  1907. case IN_DESCRIPTION:
  1908. case IN_PROPERTY_PARSE_TYPE_RESOURCE:
  1909. $this->rdf_parser['top']['state'] = IN_PROPERTY_UNKNOWN_OBJECT;
  1910. $this->_handle_property_element( $namespace_uri, $local_name, $attributes );
  1911. break;
  1912. case IN_PROPERTY_PARSE_TYPE_COLLECTION:
  1913. $this->_handle_collection_element($namespace_uri, $local_name, $attributes);
  1914. break;
  1915. case IN_PROPERTY_UNKNOWN_OBJECT:
  1916. /* if we're in a property with an unknown object type and we encounter
  1917. an element, the object must be a resource, */
  1918. $this->rdf_parser['top']['data']='';
  1919. $this->rdf_parser['top']['parent']['state'] = IN_PROPERTY_RESOURCE;
  1920. $this->rdf_parser['top']['state'] = IN_DESCRIPTION;
  1921. $this->_handle_resource_element(
  1922. $namespace_uri,
  1923. $local_name,
  1924. $attributes,
  1925. $this->rdf_parser['top']['parent'] );
  1926. break;
  1927. case IN_PROPERTY_LITERAL:
  1928. $this->_report_warning( 'no markup allowed in literals' );
  1929. break;
  1930. case IN_PROPERTY_PARSE_TYPE_LITERAL:
  1931. $this->rdf_parser['top']['state'] = IN_XML;
  1932. /* fall through */
  1933. case IN_XML:
  1934. $this->rdf_parser['xml_literal']['depth']++;
  1935. $this->_handle_xml_start_element($namespace_uri, $local_name, $attributes);
  1936. break;
  1937. case IN_PROPERTY_RESOURCE:
  1938. $this->_report_warning(
  1939. 'only one element allowed inside a property element' );
  1940. break;
  1941. case IN_PROPERTY_EMPTY_RESOURCE:
  1942. $this->_report_warning(
  1943. 'no content allowed in property with rdf:resource, rdf:bagID, or property attributes' );
  1944. break;
  1945. case IN_UNKNOWN:
  1946. break;
  1947. }
  1948. }
  1949.  
  1950. /**
  1951. property elements with text only as content set the state to
  1952. IN_PROPERTY_LITERAL. as character data is received from expat,
  1953. it is saved in a buffer and reported when the end tag is
  1954. received.
  1955. * @access private
  1956. */
  1957. function _end_literal_property()
  1958. {
  1959. if(!isset($this->rdf_parser['top']['statement_id'])) {
  1960. $this->rdf_parser['top']['statement_id']='';
  1961. }
  1962. if(!isset($this->rdf_parser['top']['parent']['subject_type'])) {
  1963. $this->rdf_parser['top']['parent']['subject_type']='';
  1964. }
  1965. if(!isset($this->rdf_parser['top']['parent']['subject'])) {
  1966. $this->rdf_parser['top']['parent']['subject']='';
  1967. }
  1968. if(!isset($this->rdf_parser['top']['parent']['bag_id'])) {
  1969. $this->rdf_parser['top']['parent']['bag_id']='';
  1970. }
  1971. if(!isset($this->rdf_parser['top']['parent']['statements'])) {
  1972. $this->rdf_parser['top']['parent']['statements']=0;
  1973. }
  1974. if(!isset($this->rdf_parser['top']['predicate'])) {
  1975. $this->rdf_parser['top']['predicate']='';
  1976. }
  1977. if(!isset($this->rdf_parser['top']['datatype'])) {
  1978. $this->rdf_parser['top']['datatype']='';
  1979. }
  1980. if(!isset($this->rdf_parser['top']['ordinal'])) {
  1981. $this->rdf_parser['top']['ordinal']=0;
  1982. }
  1983. $this->_report_statement(
  1984. $this->rdf_parser['top']['parent']['subject_type'],
  1985. $this->rdf_parser['top']['parent']['subject'],
  1986. $this->rdf_parser['top']['predicate'],
  1987. $this->rdf_parser['top']['ordinal'],
  1988. RDF_OBJECT_TYPE_LITERAL,
  1989. $this->rdf_parser['top']['data'],
  1990. $this->rdf_parser['top']['xml_lang'],
  1991. $this->rdf_parser['top']['parent']['bag_id'],
  1992. $this->rdf_parser['top']['parent']['statements'],
  1993. $this->rdf_parser['top']['statement_id'],
  1994. $this->rdf_parser['top']['datatype']);
  1995.  
  1996. }
  1997.  
  1998. /**
  1999. * @param string $parser
  2000. * @param string $name
  2001. * @access private
  2002. */
  2003. function _end_element_handler( $parser, $name )
  2004. {
  2005. switch( $this->rdf_parser['top']['state'] )
  2006. {
  2007. case IN_TOP_LEVEL:
  2008. break;
  2009. case IN_XML:
  2010. $this->_handle_xml_end_element($name);
  2011. break;
  2012. case IN_PROPERTY_UNKNOWN_OBJECT:
  2013. case IN_PROPERTY_LITERAL:
  2014. $this->_end_literal_property( );
  2015. break;
  2016. case IN_PROPERTY_PARSE_TYPE_RESOURCE:
  2017. $this->_pop_element( );
  2018. break;
  2019. case IN_PROPERTY_PARSE_TYPE_LITERAL:
  2020. // $search = array((0) => chr(10), (1) => chr(13), (2) => chr(9));
  2021. // $replace = array((0) => '\n' , (1) => '\r' , (2) => '\t');
  2022. // $this->rdf_parser["xml_literal"]["buffer"]
  2023. // = str_replace($search, $replace, $this->rdf_parser["xml_literal"]["buffer"]);
  2024.  
  2025. $this->rdf_parser['top']['data'] = $this->rdf_parser['xml_literal']['buffer'];
  2026. $this->_end_literal_property();
  2027. $this->rdf_parser['xml_literal']['buffer'] = '';
  2028. break;
  2029. case IN_PROPERTY_PARSE_TYPE_COLLECTION:
  2030. $this->_end_collection();
  2031. break;
  2032. case IN_RDF:
  2033. case IN_DESCRIPTION:
  2034. case IN_PROPERTY_RESOURCE:
  2035. case IN_PROPERTY_EMPTY_RESOURCE:
  2036. case IN_UNKNOWN:
  2037. break;
  2038. }
  2039.  
  2040. $this->_pop_element();
  2041. }
  2042.  
  2043. /**
  2044. * @param string $parser
  2045. * @param string $s
  2046. * @access private
  2047. */
  2048. function _character_data_handler( $parser,$s)
  2049. {
  2050. $len=strlen($s);
  2051. switch( $this->rdf_parser['top']['state'] )
  2052. {
  2053. case IN_PROPERTY_LITERAL:
  2054. case IN_PROPERTY_UNKNOWN_OBJECT:
  2055. if( isset($this->rdf_parser['top']['data']) )
  2056. {
  2057. $n = strlen( $this->rdf_parser['top']['data'] );
  2058. $this->rdf_parser['top']['data'].= $s;
  2059.  
  2060. }
  2061. else
  2062. {
  2063. $this->rdf_parser['top']['data']=$s;
  2064. }
  2065.  
  2066. if( $this->rdf_parser['top']['state'] == IN_PROPERTY_UNKNOWN_OBJECT )
  2067. {
  2068. /* look for non-whitespace */
  2069. for( $i = 0; (( $i < $len ) && ( ereg(" |\n|\t",$s{ $i }) )); $i++ );
  2070. /* if we found non-whitespace, this is a literal */
  2071. if( $i < $len )
  2072. {
  2073. $this->rdf_parser['top']['state'] = IN_PROPERTY_LITERAL;
  2074. }
  2075. }
  2076.  
  2077. break;
  2078. case IN_TOP_LEVEL:
  2079. break;
  2080. case IN_PROPERTY_PARSE_TYPE_LITERAL:
  2081. case IN_XML:
  2082. $this->rdf_parser['xml_literal']['buffer'] .= $s;
  2083. break;
  2084. case IN_RDF:
  2085. case IN_DESCRIPTION:
  2086. case IN_PROPERTY_RESOURCE:
  2087. case IN_PROPERTY_EMPTY_RESOURCE:
  2088. case IN_PROPERTY_PARSE_TYPE_RESOURCE:
  2089. case IN_UNKNOWN:
  2090. break;
  2091. }
  2092. }
  2093.  
  2094.  
  2095. /**
  2096. * Adds a new statement to the model
  2097. * This method is called by generateModel().
  2098. *
  2099. * @access private
  2100. * @param string &$user_data
  2101. * @param string $subject_type
  2102. * @param string $subject
  2103. * @param string $predicate
  2104. * @param string $ordinal
  2105. * @param string $object_type
  2106. * @param string $object
  2107. * @param string $xml_lang )
  2108. * @return object MemModel
  2109. */
  2110. function add_statement_to_model(
  2111. &$user_data,
  2112. $subject_type,
  2113. $subject,
  2114. $predicate,
  2115. $ordinal,
  2116. $object_type,
  2117. $object,
  2118. $xml_lang,
  2119. $datatype )
  2120. {
  2121.  
  2122. // ParseUnicode
  2123. if(UNIC_RDF){
  2124. $subject=$this->str2unicode_nfc($subject);
  2125. $predicate=$this->str2unicode_nfc($predicate);
  2126. $object=$this->str2unicode_nfc($object);
  2127. }
  2128. //create subject
  2129. if ($subject_type == RDF_SUBJECT_TYPE_BNODE)
  2130. $objsub = new BlankNode($subject);
  2131. else
  2132. $objsub = new Resource($subject);
  2133. // create predicate
  2134. $objpred = new Resource($predicate);
  2135. // create object
  2136. if (($object_type == RDF_OBJECT_TYPE_RESOURCE) || ($object_type == RDF_OBJECT_TYPE_BNODE)) {
  2137. if ($object_type == RDF_OBJECT_TYPE_BNODE)
  2138. $objobj = new BlankNode($object);
  2139. else
  2140. $objobj = new Resource($object);
  2141. } else {
  2142. $objobj = new Literal($object);
  2143. if ($datatype != '') {
  2144. $objobj->setDatatype($datatype);
  2145. }
  2146. elseif ($xml_lang !='') {
  2147. $objobj->setLanguage($xml_lang);
  2148. }
  2149. }
  2150.  
  2151. // create statement
  2152. $statement = new Statement($objsub, $objpred, $objobj);
  2153. // add statement to model
  2154. if(CREATE_MODEL_WITHOUT_DUPLICATES == TRUE){
  2155. $this->model->addWithoutDuplicates($statement);
  2156. }else
  2157. $this->model->add($statement);
  2158. }
  2159.  
  2160.  
  2161. /* public functions */
  2162.  
  2163. /**
  2164. * Generates a new MemModel from a URI, a file or from memory.
  2165. * If you want to parse an RDF document, pass the URI or location in the filesystem
  2166. * of the RDF document. You can also pass RDF code direct to the function. If you pass
  2167. * RDF code directly to the parser and there is no xml:base included, you should set
  2168. * the base URI manually using the optional second parameter $rdfBaseURI.
  2169. * Make sure that here are proper namespace declarations in your input document.
  2170. *
  2171. * @access public
  2172. * @param string $base
  2173. * @param boolean $rdfBaseURI
  2174. * @return object MemModel
  2175. */
  2176. function & generateModel($base,$rdfBaseURI = false, $model = false) {
  2177.  
  2178. // Check if $base is a URI or filename or a string containing RDF code.
  2179. if (substr(ltrim($base),0 ,1) != '<') {
  2180. // $base is URL or filename
  2181. $this->model = $model?$model:new MemModel($base);
  2182. $input = fopen($base,'r') or die("RDF Parser: Could not open File: $base. Stopped parsing.");
  2183. $this->rdf_parser_create( NULL );
  2184. $this->rdf_set_base($base);
  2185. $done=false;
  2186. while(!$done)
  2187. {
  2188. $buf = fread( $input, 512 );
  2189. $done = feof($input);
  2190. if ( ! $this->rdf_parse( $buf, feof($input) ) )
  2191. {
  2192. $err_code = xml_get_error_code( $this->rdf_get_xml_parser());
  2193. $line = xml_get_current_line_number($this->rdf_get_xml_parser() );
  2194. $errmsg = RDFAPI_ERROR . '(class: parser; method: generateModel): XML-parser-error ' . $err_code .' in Line ' . $line .' of input document.';
  2195. trigger_error($errmsg, E_USER_ERROR);
  2196. }
  2197. }
  2198. /* close file. */
  2199. fclose( $input );
  2200. } else {
  2201. // $base is RDF string
  2202. $this->model = $model?$model:new MemModel($base);
  2203. $this->rdf_parser_create( NULL );
  2204. if ($rdfBaseURI!==false)
  2205. {
  2206. $this->rdf_set_base($rdfBaseURI);
  2207. } else
  2208. {
  2209. $this->rdf_set_base( NULL );
  2210. }
  2211. if ( ! $this->rdf_parse( $base, TRUE ) )
  2212. {
  2213. $err_code = xml_get_error_code( $this->rdf_get_xml_parser());
  2214. $line = xml_get_current_line_number($this->rdf_get_xml_parser() );
  2215. $errmsg = RDFAPI_ERROR . '(class: parser; method: generateModel): XML-parser-error ' . $err_code .' in Line ' . $line .' of input document.';
  2216. trigger_error($errmsg, E_USER_ERROR);
  2217. }
  2218. }
  2219. // base_uri could have changed while parsing
  2220. $this->model->setBaseURI($this->rdf_parser['base_uri']);
  2221.  
  2222. if(isset($this->rdf_parser['namespaces'])){
  2223. $this->model->addParsedNamespaces($this->rdf_parser['namespaces']);
  2224. }
  2225. $this->rdf_parser_free();
  2226. return $this->model;
  2227.  
  2228. }
  2229.  
  2230. /**
  2231. * @param string $encoding
  2232. * @access private
  2233. */
  2234. function rdf_parser_create( $encoding )
  2235. {
  2236.  
  2237. $parser = xml_parser_create_ns( $encoding, NAMESPACE_SEPARATOR_CHAR );
  2238.  
  2239. xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
  2240. $this->rdf_parser['xml_parser'] = $parser;
  2241.  
  2242. xml_set_object($this->rdf_parser['xml_parser'], $this);
  2243. xml_set_element_handler( $this->rdf_parser['xml_parser'], '_start_element_handler', '_end_element_handler' );
  2244. xml_set_character_data_handler( $this->rdf_parser['xml_parser'], '_character_data_handler' );
  2245. xml_set_start_namespace_decl_handler($this->rdf_parser['xml_parser'], '_start_ns_declaration_handler');
  2246.  
  2247. return $this->rdf_parser;
  2248. }
  2249.  
  2250. /**
  2251. * @param resource &$parser
  2252. * @param string $ns_prefix
  2253. * @param string $ns_uri
  2254. * @access private
  2255. */
  2256. function _start_ns_declaration_handler(&$parser, $ns_prefix, $ns_uri)
  2257. {
  2258. if (!$ns_prefix)
  2259. $this->rdf_parser['default_namespace'] = $ns_uri;
  2260. else
  2261. $this->rdf_parser['namespaces'][$ns_uri] = $ns_prefix;
  2262. }
  2263.  
  2264.  
  2265. /**
  2266. * @access private
  2267. */
  2268. function rdf_parser_free( )
  2269. {
  2270. $z=3;
  2271.  
  2272. $this->rdf_parser['base_uri']='';
  2273. $this->rdf_parser['document_base_uri'] = '';
  2274.  
  2275. unset( $this->rdf_parser );
  2276. }
  2277.  
  2278. /**
  2279. * @param string $s
  2280. * @param string $is_final
  2281. * @access private
  2282. */
  2283. function rdf_parse( $s, $is_final )
  2284. {
  2285. return XML_Parse( $this->rdf_parser['xml_parser'], $s, $is_final );
  2286. }
  2287.  
  2288. /**
  2289. * @access private
  2290. */
  2291. function rdf_get_xml_parser()
  2292. {
  2293. return ( $this->rdf_parser['xml_parser']);
  2294. }
  2295.  
  2296. /**
  2297. * @param string $base
  2298. * @access private
  2299. */
  2300. function rdf_set_base($base )
  2301. {
  2302. $this->rdf_parser['base_uri']=$base;
  2303. $c = substr($base, strlen($base)-1 ,1);
  2304. if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
  2305. $this->rdf_parser['normalized_base_uri'] = $base . '#';
  2306. else
  2307. $this->rdf_parser['normalized_base_uri'] = $base;
  2308.  
  2309. return 0;
  2310. }
  2311.  
  2312. /**
  2313. * @access private
  2314. */
  2315. function rdf_get_base()
  2316. {
  2317. if ($this->rdf_parser['top']['element_base_uri'])
  2318. return $this->rdf_parser['top']['element_base_uri'];
  2319. else
  2320. return $this->rdf_parser['base_uri'];
  2321. }
  2322.  
  2323.  
  2324. } // end: rdf_parser
  2325.  
  2326. ?>

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