protected function EasyRdf_Parser_Rdfa::processNode in Zircon Profile 8
Same name and namespace in other branches
- 8.0 vendor/easyrdf/easyrdf/lib/EasyRdf/Parser/Rdfa.php \EasyRdf_Parser_Rdfa::processNode()
1 call to EasyRdf_Parser_Rdfa::processNode()
- EasyRdf_Parser_Rdfa::parse in vendor/
easyrdf/ easyrdf/ lib/ EasyRdf/ Parser/ Rdfa.php - Parse RDFa 1.1 into an EasyRdf_Graph
File
- vendor/
easyrdf/ easyrdf/ lib/ EasyRdf/ Parser/ Rdfa.php, line 298
Class
- EasyRdf_Parser_Rdfa
- Class to parse RDFa 1.1 with no external dependancies.
Code
protected function processNode($node, &$context, $depth = 1) {
if ($this->debug) {
$this
->printNode($node, $depth);
}
// Step 1: establish local variables
$skip = false;
$subject = null;
$typedResource = null;
$object = null;
$rels = array();
$revs = array();
$lang = $context['lang'];
$incompleteRels = array();
$incompleteRevs = array();
if ($node->nodeType === XML_ELEMENT_NODE) {
$context['path'] .= '/' . $node->nodeName;
$content = $node
->hasAttribute('content') ? $node
->getAttribute('content') : null;
$datatype = $node
->hasAttribute('datatype') ? $node
->getAttribute('datatype') : null;
$property = $node
->getAttribute('property') ? $node
->getAttribute('property') : null;
$typeof = $node
->getAttribute('typeof') ? $node
->getAttribute('typeof') : null;
// Step 2: Default vocabulary
if ($node
->hasAttribute('vocab')) {
$context['vocab'] = $node
->getAttribute('vocab');
if ($context['vocab']) {
$this
->addTriple($this->baseUri, 'rdfa:usesVocabulary', array(
'type' => 'uri',
'value' => $context['vocab'],
));
}
}
// Step 3: Set prefix mappings
// Support for deprecated xmlns if present in document
foreach ($context['xmlns'] as $prefix => $uri) {
if ($node
->hasAttribute('xmlns:' . $prefix)) {
$context['prefixes'][$prefix] = $node
->getAttribute('xmlns:' . $prefix);
if ($this->debug) {
print "Prefix (xmlns): {$prefix} => {$uri}\n";
}
}
}
if ($node
->hasAttribute('prefix')) {
$mappings = preg_split('/\\s+/', $node
->getAttribute('prefix'));
while (count($mappings)) {
$prefix = strtolower(array_shift($mappings));
$uri = array_shift($mappings);
if (substr($prefix, -1) === ':') {
$prefix = substr($prefix, 0, -1);
}
else {
continue;
}
if ($prefix === '_') {
continue;
}
elseif (!empty($prefix)) {
$context['prefixes'][$prefix] = $uri;
if ($this->debug) {
print "Prefix: {$prefix} => {$uri}\n";
}
}
}
}
// Step 4
if ($node
->hasAttributeNS(self::XML_NS, 'lang')) {
$lang = $node
->getAttributeNS(self::XML_NS, 'lang');
}
elseif ($node
->hasAttribute('lang')) {
$lang = $node
->getAttribute('lang');
}
// HTML+RDFa 1.1: ignore rel and rev unless they contain CURIEs.
foreach (array(
'rel',
'rev',
) as $attr) {
if ($node
->hasAttribute('property') and $node
->hasAttribute($attr)) {
// Quick check in case there are no CURIEs to deal with.
if (strpos($node
->getAttribute($attr), ':') === false) {
$node
->removeAttribute($attr);
}
else {
// Only keep CURIEs.
$curies = array();
foreach (preg_split('/\\s+/', $node
->getAttribute($attr)) as $token) {
if (strpos($token, ':')) {
$curies[] = $token;
}
}
$node
->setAttribute($attr, implode(' ', $curies));
}
}
}
$rels = $this
->processUriList($node, $context, $node
->getAttribute('rel'));
$revs = $this
->processUriList($node, $context, $node
->getAttribute('rev'));
if (!$node
->hasAttribute('rel') and !$node
->hasAttribute('rev')) {
// Step 5: Establish a new subject if no rel/rev
if ($property and is_null($content) and is_null($datatype)) {
$subject = $this
->getUriAttribute($node, $context, 'about');
if ($typeof and !$subject) {
$typedResource = $this
->getUriAttribute($node, $context, array(
'resource',
'href',
'src',
));
if (!$typedResource) {
$typedResource = $this->graph
->newBNodeId();
}
$object = $typedResource;
}
}
else {
$subject = $this
->getUriAttribute($node, $context, array(
'about',
'resource',
'href',
'src',
));
}
// Establish a subject if there isn't one
# FIXME: refactor this
if (is_null($subject)) {
if ($context['path'] === '/html/head') {
$subject = $context['object'];
}
elseif ($depth <= 2) {
$subject = $this->baseUri;
}
elseif ($typeof and !$property) {
$subject = $this->graph
->newBNodeId();
}
else {
if (!$property) {
$skip = true;
}
$subject = $context['object'];
}
}
}
else {
// Step 6
// If the current element does contain a @rel or @rev attribute, then the next step is to
// establish both a value for new subject and a value for current object resource:
$subject = $this
->getUriAttribute($node, $context, 'about');
$object = $this
->getUriAttribute($node, $context, array(
'resource',
'href',
'src',
));
if ($typeof) {
if (!$object and !$subject) {
$object = $this->graph
->newBNodeId();
}
$typedResource = $subject ? $subject : $object;
}
# FIXME: if the element is the root element of the document
# then act as if there is an empty @about present
if (!$subject) {
$subject = $context['object'];
}
}
# FIXME: better place for this?
if ($typeof and $subject and !$typedResource) {
$typedResource = $subject;
}
// Step 7: Process @typeof if there is a subject
if ($typedResource) {
foreach ($this
->processUriList($node, $context, $typeof) as $type) {
$this
->addTriple($typedResource, 'rdf:type', array(
'type' => 'uri',
'value' => $type,
));
}
}
// Step 8: Create new List mapping if the subject has changed
if ($subject and $subject !== $context['subject']) {
$listMapping = new StdClass();
}
else {
$listMapping = $context['listMapping'];
}
// Step 9: Generate triples with given object
if ($subject and $object) {
foreach ($rels as $prop) {
$obj = array(
'type' => 'uri',
'value' => $object,
);
if ($node
->hasAttribute('inlist')) {
$this
->addToList($listMapping, $prop, $obj);
}
else {
$this
->addTriple($subject, $prop, $obj);
}
}
foreach ($revs as $prop) {
$this
->addTriple($object, $prop, array(
'type' => 'uri',
'value' => $subject,
));
}
}
elseif ($rels or $revs) {
// Step 10: Incomplete triples and bnode creation
$object = $this->graph
->newBNodeId();
if ($rels) {
if ($node
->hasAttribute('inlist')) {
foreach ($rels as $prop) {
# FIXME: add support for incomplete lists
if (!isset($listMapping->{$prop})) {
$listMapping->{$prop} = array();
}
}
}
else {
$incompleteRels = $rels;
if ($this->debug) {
print "Incomplete rels: " . implode(',', $rels) . "\n";
}
}
}
if ($revs) {
$incompleteRevs = $revs;
if ($this->debug) {
print "Incomplete revs: " . implode(',', $revs) . "\n";
}
}
}
// Step 11: establish current property value
if ($subject and $property) {
$value = array();
if ($datatype) {
$datatype = $this
->processUri($node, $context, $datatype, true);
}
if ($content !== null) {
$value['value'] = $content;
}
elseif ($node
->hasAttribute('datetime')) {
$value['value'] = $node
->getAttribute('datetime');
$datetime = true;
}
elseif ($datatype === '') {
$value['value'] = $node->textContent;
}
elseif ($datatype === self::RDF_XML_LITERAL) {
$value['value'] = '';
foreach ($node->childNodes as $child) {
$value['value'] .= $child
->C14N();
}
}
elseif (is_null($datatype) and empty($rels) and empty($revs)) {
$value['value'] = $this
->getUriAttribute($node, $context, array(
'resource',
'href',
'src',
));
if ($value['value']) {
$value['type'] = 'uri';
}
}
if (empty($value['value']) and $typedResource and !$node
->hasAttribute('about')) {
$value['type'] = 'uri';
$value['value'] = $typedResource;
}
if (empty($value['value'])) {
$value['value'] = $node->textContent;
}
if (empty($value['type'])) {
$value['type'] = 'literal';
if ($datatype) {
$value['datatype'] = $datatype;
}
elseif (isset($datetime) or $node->nodeName === 'time') {
$value['datatype'] = $this
->guessTimeDatatype($value['value']);
}
if (empty($value['datatype']) and $lang) {
$value['lang'] = $lang;
}
}
// Add each of the properties
foreach ($this
->processUriList($node, $context, $property) as $prop) {
if ($node
->hasAttribute('inlist')) {
$this
->addToList($listMapping, $prop, $value);
}
elseif ($subject) {
$this
->addTriple($subject, $prop, $value);
}
}
}
// Step 12: Complete the incomplete triples from the evaluation context
if (!$skip and $subject and ($context['incompleteRels'] or $context['incompleteRevs'])) {
foreach ($context['incompleteRels'] as $prop) {
$this
->addTriple($context['subject'], $prop, array(
'type' => 'uri',
'value' => $subject,
));
}
foreach ($context['incompleteRevs'] as $prop) {
$this
->addTriple($subject, $prop, array(
'type' => 'uri',
'value' => $context['subject'],
));
}
}
}
// Step 13: create a new evaluation context and proceed recursively
if ($node
->hasChildNodes()) {
if ($skip) {
$newContext = $context;
}
else {
// Prepare a new evaluation context
$newContext = $context;
if ($object) {
$newContext['object'] = $object;
}
elseif ($subject) {
$newContext['object'] = $subject;
}
else {
$newContext['object'] = $context['subject'];
}
if ($subject) {
$newContext['subject'] = $subject;
}
$newContext['incompleteRels'] = $incompleteRels;
$newContext['incompleteRevs'] = $incompleteRevs;
if (isset($listMapping)) {
$newContext['listMapping'] = $listMapping;
}
}
// The language is always updated, even if skip is set
$newContext['lang'] = $lang;
foreach ($node->childNodes as $child) {
if ($child->nodeType === XML_ELEMENT_NODE) {
$this
->processNode($child, $newContext, $depth + 1);
}
}
}
// Step 14: create triples for lists
if (!empty($listMapping)) {
foreach ($listMapping as $prop => $list) {
if ($context['listMapping'] !== $listMapping) {
if ($this->debug) {
print "Need to create triples for {$prop} => " . count($list) . " items\n";
}
$this
->generateList($subject, $prop, $list);
}
}
}
}