Source for file Parser.php
Documentation is available at Parser.php
// ----------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------
* This parser can parse a subset of n3, reporting triples to a callback function
* or constructing a RAP Model ( http://www.wiwiss.fu-berlin.de/suhl/bizer/rdfapi )
* <li>Standard things, repeated triples ( ; and , ), blank nodes using [ ], self-reference ('<>')</li>
* <li>@prefix mappings</li>
* <li>= maps to owl#sameAs</li>
* <li>a maps to rdf-syntax-ns#type</li>
* <li>Literal datytype- and xmlLanguageTag support
* Un-supported N3 Features include:
* <li>Reification using { }</li>
* <li>. and ^ operators for tree traversal</li>
* <li>Any log operators, like log:forAll etc.</li>
* This parser is based on n3.py from Epp released 2nd March, 2002.
* ( http://infomesh.net/2002/eep/20020302-013802/n3.py )
* This parser is released under the GNU GPL license.
* ( http://www.gnu.org/licenses/gpl.txt )
* @author Sean B. Palmer <sean@mysterylights.com>, Gunnar AA. Grimnes <ggrimnes@csd.abdn.ac.uk>, Daniel Westphal <mail@d-westphal.de>
/* ==================== Variables ==================== */
/* ==================== Public Methods ==================== */
$Name = '[A-Za-z0-9_@\.]+[^\.,;\[\] ]';
$QName = '(?:[A-Za-z][A-Za-z0-9_@\.]*)?:' . $Name;
$Literal = '"(\\\"|[^"])*"'; # '"(?:\\"|[^"])*"'
// $Literal = '"[^"\\\\]*(?:\\.\\[^"\\]*)*"'; # '"(?:\\"|[^"])*"'
$LangTag = '@[A-Za-z\-]*[^ \^\.\;\,]';
$Datatype = '(\^\^)[^ ,\.;)]+';
$Datatype_URI = '(\^\^)' . $URI;
// $LLiteral = '"""[^"\\\\]*(?:(?:.|"(?!""))[^"\\\\]*)*"""';
$LLiteral = '"""[^"\\\\]*(?:(?:\\\\.|"(?!""))[^"\\\\]*)*"""';
// '"""[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
$Prefix = '(?:[A-Za-z][A-Za-z0-9_]*)?:';
$this->RDF_NS = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; # for 'a' keyword
$this->DAML_NS = 'http://www.daml.org/2001/03/daml+oil#'; # for '=' keyword
$this->OWL_NS = 'http://www.w3.org/2002/07/owl#';
// $t = array( $LLiteral, $URI); //, $Literal, $PrefixDecl, $QName, $bNode, $Prefix,
// $Univar, 'a', '{', '}', '\(', '\)', '\[', '\]', ',', ';', '\.', $WS, $Comment);
$Datatype_URI, $Datatype, $LLiteral, $URI, $Literal,
$PrefixDecl, $QName, $bNode, $Prefix, $Univar,
'a', '=', '{', '}', '\(', '\)', '\[', '\]', ',', ';', '\.',
$this->bNodeMap = array ();
$this->FixBnodes = RDF_FIX_BLANKNODES;
* Sets, if BlankNode labels should be replaced by the generic label from the constants.php file
* default is "false" -> the used label in n3 is parsed to the model
if (($set = true ) OR ($set = false )) {
* This parses a N3 string and prints out the triples
// """Get a string, tokenize, create list, convert to Eep store."""
for ($i = 3; $i < 5; $i++ ) {
if (substr($t[$i], 0 , 2 ) == '^^') {
print '('. $t[0 ]. ', '. $t[1 ]. ', '. $object. ")\n";
// return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
* This parses a N3 string and calls func($subject, $predicate, $object) with each trioke
// """Get a string, tokenize, create list, convert to Eep store."""
for ($i = 3; $i < 5; $i++ ) {
if (substr($t[$i], 0 , 2 ) == '^^') {
// print "(".$t[0].", ".$t[1].", ".$t[2].")";
$func($t[0 ], $t[1 ], $object);
// return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
* This parses a N3 string and prints out the triples
$m = & new RDF_Model_Memory ();
// """Get a string, tokenize, create list, convert to Eep store."""
$new_statement = & RDF_Statement ::factory ($s, $p, $o);
if (PEAR ::isError ($new_statement)) {
$result = $m->add ($new_statement);
if (PEAR ::isError ($result)) {
* Generate a new Model_Memory from an URI or file.
* @return object Model_Memory
$handle = fopen($path, 'r') or die (" N3 Parser: Could not open File: '$path' - Stopped parsing." );
$input .= fread($handle, 512 );
/* ==================== protected Methods from here ==================== */
// General list processing functions
* Returns FALSE if argument is a whitespace character
$ws = array ("", " ", "\t", "\n", "\r");
* Callback function for trimming whitespace from lines
* Returns true if the string is not a comment
$N3Comment = '/^[ \t]*\#/';
* Removes all whitespace tokens from list
// """Filter whitespace from a list."""
* Gets a slice of an array.
* Returns the wanted slice, as well as the remainder of the array.
* e.g. getSpan(['p', 'q', 'r'], 1, 2) gives (['q'], ['p', 'r'])
function getSpan($list, $start, $end)
* Concatenates two arrays
* Returns an array with all indexes where item appears in list
function posns($list, $item)
/* More N3 specific functions */
* Returns a list of tokens
// """Notation3 tokenizer. Takes in a string, returns a raw token list."""
if (strlen($s) == 0 ) die ('Document has no content!');
* Returns a list with the elements between start and end as one quoted string
* e.g. listify(["a","b","c","d"],1,2) => ["a","b c", "d"]
function listify($list, $start, $end)
// Re-form a list, merge elements start->end into one quoted element
// Start and end are offsets...
// array_push($s,"\"".join($m," ")."\"");
* Returns an array with prefixes=>namespace mappings
// while '@prefix' in list {
// pos = list.index('@prefix')
$r = $this->getSpan($list, $pos, ($pos + 4 )); # processes the prefix tokens
$prefixes[$binding[$ns]] = substr($binding[$name], 1 , -1 );
return array ($prefixes, $list);
* Callback function for replacing "a" elements with the right RDF uri.
$l = '<' . $this->RDF_NS . 'type>';
* Callback function for replacing "=" elements with the right DAML+OIL uri.
$l = '<' . $this->OWL_NS . 'sameAs>';
* Callback function for replacing "this" elements with the right RDF uri.
* Expands namespace prefixes etc.
array_walk($list, array ($this, 'replace_a_type'));
for ($i = 0; $i < count($list); $i++ ) {
// for i in range(len(list)) {
// if (!strstr('<_"?.;,{}[]()',$list[$i]{0})) {
// if a <> resource occours, change it to the parsed filename or local URI + timestamp
if (!isset ($_SERVER['SERVER_ADDR'])) {
$_SERVER['SERVER_ADDR'] = 'localhost';
if (!isset ($_SERVER['REQUEST_URI'])) {
$_SERVER['REQUEST_URI'] = '/rdfapi-php';
$list[$i] = '<http://' . $_SERVER['SERVER_ADDR'] .
$_SERVER['REQUEST_URI'] . '#generate_timestamp_' . time() . '>';
$list[$i] = '<' . $path . '>';
if ((!strstr('<_"?.;,{}[]()@', $list[$i] {
))AND (substr($list[$i], 0 , 3 ) != '^^<')) {
if (isset ($prefixes[$ns])) {
$list[$i] = '<' . $prefixes[$ns] . $name . '>';
} else if (isset ($prefixes[substr($ns, 2 )])) {
$list[$i] = '^^' . $prefixes[substr($ns, 2 )] . $name . '';
die ('Prefix not declared:' . $ns);
0 } == '"') { // Congratulations - it's a literal!
if (substr($list[$i], 0 , 3 ) == '"""') {
if (substr($list[$i], -3 , 3 ) == '"""') { // A big literal...
$lit = substr($list[$i], 3 , -3 );
$list[$i] = '"' . $lit . '"';
die ("Incorrect string formatting: " . substr($list[$i], -3 , 3 ));
if (strstr($list[$i], "\n")) die ('Newline in literal: ' + $list[$i]);
if (substr($list[$i], 0 , 2 ) == '^^') {
if ($list[$i][2 ] != '<') {
$list[$i] = '^^<' . substr($list[$i], 2 ) . '>';
* Returns an array of triples extracted from the list of n3 tokens
// for ($i=0;$i<count($list); $i++) {
$r = $this->getSpan($list, 0 , $pos + 1 );
$statements[] = $statement;
* Gets a list of triples with same subject
* e.g. :Gunnar :firstname "Gunnar" ; :lastname "Grimnes.
$r = $this->posns($list, ';');
$r = $this->getSpan($list, $pos[0 ], $pos[1 ]);
return array ($list, $povs);
* * Gets a list of triples with same predicate
* e.g. :Gunnar :likes "Cheese", "Wine".
// for ($i=0;$i<count($list); $i++) {
if (isset ($list[$pos + 2 ])) {
if (@$list[$pos + 2 ][0 ] == '@') {
if (@$list[$pos + 2 ][0 ] == '^') {
if (isset ($list[$pos + 3 ])) {
if (@$list[$pos + 3 ][0 ] == '^') {
$r = $this->getSpan($list, $pos, ($pos + $get_array_fields));
return array ($list, $objs);
* Does the real work, returns a list of subject, predicate, object triples.
if (count($list) == 1 && preg_match('/_' . RDF_BNODE_PREFIX . '[0-9]+_/', $list[0 ])) {
print " Ignored bNode exists statement. $list\n";
die ('Error: statement too short!');
// (spo, po), all = getPovs(list), []
// myPo, obj = getObjs(pop)
$all[] = array ($subject, $predicate, $myPo[1 ], $myPo[2 ], $myPo[3 ]);
// all.append([subject, predicate, myPo[1]])
foreach ($obj as $o) $all[] = array ($subject, $predicate, $o[1 ], $o[2 ], $o[3 ]);
// for x in obj: all.append([subject, predicate, x])
// spo, objs = getObjs(spo)
$all[] = array ($subject, $predicate, $spo[2 ], $spo[3 ], $spo[4 ]);
foreach ($objs as $obj) $all[] = array ($subject, $predicate, $obj[1 ], $obj[2 ], $obj[3 ]);
* Makes lists of elements in list into a seperate array element.
* e.g. doLists(["a","b","[","c","]","d"], "[","]")=> ["a","b", ["c"], "d"]
function doLists($list, $schar, $echar)
for ($i = 0; $i < count($list); $i++ ) {
if ($list[$i] == $schar) {
$ndict[$nestingLevel] = array (array ($i));
$ndict[$nestingLevel][] = array ($i);
if ($list[$i] == $echar) {
$ndict[$nestingLevel] = array (array ($i));
$ndict[$nestingLevel][count($ndict[$nestingLevel])-1 ][] = $i;
// elif type(list[i]) == type([]) {
// list[i] = doLists(list[i], schar, echar)
$tol = $ndict[$biggest][0 ];
$list = $this->listify($list, $tol[0 ], ($tol[1 ] + 1 ));
* Apply doLists for all different types of list.
// y, z = zip(['[', ']'], ['{', '}'], ['(', ')'])
// return map(doLists, [list, list, list], y, z).pop()
$list = $this->doLists($list, '[', ']');
$list = $this->doLists($list, '{', '}');
return $this->doLists($list, '(', ')');
* Generates a new node id.
return '_' . RDF_BNODE_PREFIX . $this->bNode . '_';
* This makes bNodes out of variables like _:a etc.
for ($i = 0; $i < count($list); $i++ ) {
if (substr($l, 0 , 2 ) == '_:') {
if (!isset ($this->bNodeMap[$l])) {
$this->bNodeMap[$l] = $a;
} else $a = $this->bNodeMap[$l];
* This makes [ ] lists into bnodes.
for ($i = 0; $i < count($list); $i++ ) {
if ($list[$i][0 ] == '[') {
die ('Only [ ] lists are supported!');
* Main work-horse function. This converts a N3 string to a list of statements
// """Convert an N3 string into a list of triples as strings."""
$t = $this->filterWs($this->toke($s)); # tokenize the stream, and filter whitespace tokens
$r = $this->getPrefixes($t); # get the prefix directives, and add to a dict
$t = $this->applyStuff($prefixes, $t); #apply prefixes, keywords, and string formatting
print "Stuff applied:\n";
$t = $this->fixAnon($t); # fix _:a anons
$t = $this->listStuff($t); # apply list stuff: todo
print "Lists applied:\n";
$t = $this->getStatements($t); # get all of the "statements" from the stream
// for x in [statementize(stat) for stat in t] {
// for y in x: result.append(y)
* Constructs a RAP RDFNode from URI/Literal/Bnode
* @returns object RDFNode
for ($i = 3; $i < count($state); $i++ ) {
if ($state[$i][0 ] == '@') {
if (substr($state[$i], 0 , 2 ) == '^^') {
$dtype = substr($state[$i], 2 );
$dtype = substr($dtype, 1 , -1 );
$new_literal = & RDF_Literal ::factory (substr($s, 1 , -1 ), $lang);
if (PEAR ::isError ($new_literal)) {
$new_literal->setDatatype ($dtype);
if (strstr($s, '_' . RDF_BNODE_PREFIX )) {
if (($this->FixBnodes) || (!array_search($s, $this->bNodeMap))) {
return RDF_BlankNode ::factory (substr($s, 1 , -1 ));
return RDF_Resource ::factory (substr($s, 1 , -1 ));
Documentation generated on Mon, 11 Mar 2019 15:39:51 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|