rdf_format.inc in Taxonomy import/export via XML 5
Same filename and directory in other branches
Include routines for RDF parsing and taxonomy/term creation.
This lib is included on demand by the taxonomy_xml.module when needed to read or write the RDF syntax.
@author dman (Dan Morrison) http://coders.co.nz/
File
rdf_format.incView source
<?php
/**
* @file Include routines for RDF parsing and taxonomy/term creation.
*
* This lib is included on demand by the taxonomy_xml.module when needed
* to read or write the RDF syntax.
*
* @author dman (Dan Morrison) http://coders.co.nz/
*/
define('TAXONOMY_XML_RDF_NS', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
define('TAXONOMY_XML_TYPE', TAXONOMY_XML_RDF_NS . 'type');
define('TAXONOMY_XML_RDFS_NS', 'http://www.w3.org/2000/01/rdf-schema#');
// See http://www.w3.org/2004/12/q/doc/rdf-labels.html
define('TAXONOMY_XML_CONTENTLABEL_NS', 'http://www.w3.org/2004/12/q/contentlabel#');
define('TAXONOMY_XML_CATEGORY', TAXONOMY_XML_CONTENTLABEL_NS . 'Category');
define('TAXONOMY_XML_OWL_NS', 'http://www.w3.org/2002/07/owl#');
define('TAXONOMY_XML_W3C_WN', 'http://www.w3.org/2006/03/wn/wn20/');
define('TAXONOMY_XML_W3C_WN_SCHEMA', TAXONOMY_XML_W3C_WN . 'schema/');
define('TAXONOMY_XML_SKOS_NS', 'http://www.w3.org/2004/02/skos/core#');
/**
* Read in RDF taxonomies and vocabularies. Create vocabs and terms as needed.
*
* See formats.html readme for information about the RDF input supported.
*
* Targets include :
* ICRA Content Rating http://www.icra.org/vocabulary/
* WordNet Lexicon http: //wordnet.princeton.edu/
* SUMO http://www. ontologyportal.org/
*
* ... and the ontologies found at http://www.schemaweb.info/ that implement
* appropriate parts of the RDF Schema "rdfs" (eg Classes with subclassOf)
*/
function taxonomy_xml_rdf_parse(&$data, $vid) {
if (!file_exists(drupal_get_path('module', 'taxonomy_xml'))) {
drupal_set_message(t('This method requires the ARC library to be available. Please check the taxonomy_xml INSTALL.txt'));
return false;
}
// Use ARC parser
include_once "arc/ARC_rdfxml_parser.php";
$parser_args = array(
"bnode_prefix" => "genid",
"base" => "",
);
$parser = new ARC_rdfxml_parser($parser_args);
$triples = $parser
->parse_data($data);
if (!is_array($triples)) {
drupal_set_message(t("Problem parsing input %message", array(
'%message' => $triples,
)), 'error');
return false;
}
drupal_set_message(t("%count data triples (atomic statements) found in the source RDF doc", array(
'%count' => count($triples),
)));
#dpm($triples);
// The RDF input may come in several flavours,
// Resources of the following 'types' may be cast into taxonomy terms for our purposes.
// That is, an rdf:Class is a Drupal:term
//
// Add to this list as needed
//
$term_types = array(
TAXONOMY_XML_RDF_NS . 'Property',
'http://purl.org/dc/elements/1.1/subject',
TAXONOMY_XML_RDFS_NS . 'Class',
TAXONOMY_XML_W3C_WN_SCHEMA . 'Word',
TAXONOMY_XML_W3C_WN_SCHEMA . 'NounWordSense',
TAXONOMY_XML_W3C_WN_SCHEMA . 'NounSynset',
'http://www.w3.org/2004/12/q/contentlabel#Category',
TAXONOMY_XML_SKOS_NS . 'Concept',
);
// A Drupal 'vocabulary' is represented by an owl:Ontology
// or other similar shaped constructs
$vocabulary_types = array(
TAXONOMY_XML_OWL_NS . 'Ontology',
TAXONOMY_XML_RDF_NS . 'Description',
'http://www.w3.org/2001/12/Glossary',
);
$resources_by_type = taxonomy_xml_convert_triples_to_sorted_objects($triples);
// The resources are all initialized as data objects.
// Resource types we expect to be dealing with are just vocabs and terms.
drupal_set_message(t("Found %count different <strong>kinds</strong> of resources in the input : %types", array(
'%count' => count($resources_by_type),
'%types' => join(', ', array_keys($resources_by_type)),
)));
#dpm($resources_by_type);
// Scan the sorted objects for vocabulary definitions
// Hopefully there's only one vocab per file, but loop anyway
$vocabularies = array();
foreach ($vocabulary_types as $vocabulary_type) {
if (isset($resources_by_type[$vocabulary_type]) && is_array($resources_by_type[$vocabulary_type])) {
foreach ($resources_by_type[$vocabulary_type] as $uri => &$vocabulary_handle) {
$vocabularies[$uri] =& $vocabulary_handle;
}
}
}
drupal_set_message(t("Found %count resources to be used as vocabulary definitions", array(
'%count' => count($vocabularies),
)));
if ($vid == 0) {
// We've been asked to use the vocab described in the source file.
if (!$vocabularies) {
// Create a placeholder.
$vocabularies[] = array(
'name' => 'Imported Vocabulary',
);
}
}
$vid = taxonomy_xml_absorb_vocabulary_definitions($vocabularies);
// $vocabularies now contains a keyed array of target vocabularies the terms may be put into
// $vid is the default one (most common is one vocab per input file) to be used unless otherwise defined per-term.
// Gather the resources that will become terms.
// Slightly long way (not using array_merge), as I need to merge indexed and by reference
$terms = array();
foreach ($term_types as $term_type) {
if (isset($resources_by_type[$term_type]) && is_array($resources_by_type[$term_type])) {
foreach ($resources_by_type[$term_type] as $uri => &$term_handle) {
// Grab name/label early for debugging and indexing
$predicates = $term_handle->predicates;
if (isset($predicates['label'])) {
$term_handle->name = $predicates['label'][0];
}
$terms[$uri] =& $term_handle;
}
}
}
drupal_set_message(t("Found %count resources to be imported as terms into vocabulary %vid", array(
'%count' => count($terms),
'%vid' => $vid,
)));
// $predicate_synonyms is a translation array to match rdf-speak with Drupal concepts
$predicate_synonyms = taxonomy_xml_relationship_synonyms();
//
// START MAKING TERMS
//
foreach ($terms as $uri => &$term) {
drupal_set_message(t("Reviewing term %uri '%name' and analyzing its properties", array(
'%uri' => $uri,
'%name' => $term->name,
)));
if (!isset($term->vid)) {
// This is just a default fallback. Imported terms should really have already chosen their vid.
$term->vid = $vid;
}
// Build term from data
// Convert all input predicates into attributes on the object the taxonomy.module will understand
foreach ($term->predicates as $predicate => $values) {
$original_predicate = $predicate;
// First translate misc terminology synonyms to the cannonic predicate I use everywhere
// This allows us to interpret several XML dialects at once
if (isset($predicate_synonyms[$predicate]) && ($cannonic = $predicate_synonyms[$predicate])) {
$predicate = $cannonic;
}
#drupal_set_message(t("Applying '$predicate' ($predicate) value of ". print_r($values, 1) ." found in $uri"));
switch ($predicate) {
case 'type':
// These are already done. Ignore
case 'subPropertyOf':
// Useless, ignore also
break;
case TAXONOMY_XML_NAME:
$term->name = taxonomy_xml_get_literal_string($values);
break;
case TAXONOMY_XML_DESCRIPTION:
$term->description = taxonomy_xml_get_literal_string($values);
break;
case TAXONOMY_XML_PARENT:
case TAXONOMY_XML_RELATED:
case TAXONOMY_XML_CHILD:
// A term relationship.
// Translate each referred item from URI to label or handle,
// and save to be linked in later
foreach ($values as $i => $target_uri) {
$term->predicates[$predicate][$target_uri] = $target_uri;
}
break;
case TAXONOMY_XML_HAS_SYNONYM:
$term->synonyms_array = isset($term->synonyms_array) ? array_merge($term->synonyms_array, $values) : $values;
$term->synonyms = join("\n", array_unique($term->synonyms_array));
break;
case TAXONOMY_XML_IN_VOCABULARY:
// This term need to be in the vocabulary referred to by this URI
// check our known vocabs to see if they are recognised
// Do we know a vocab with an ID matching this 'isdefinedby' value?
foreach ($values as $value) {
// probably just one...
if ($target_vocab = $vocabularies[$value]) {
// I know this vocab!
$term->vid = $target_vocab->vid;
}
}
break;
case 'unused':
// Explicitly ignore these
break;
default:
drupal_set_message(t("Dunno what to do with '{$predicate}' value of " . print_r($values, 1) . " found in {$uri}", array(
'$predicate' => $predicate,
'%values' => print_r($values, 1),
'%uri' => $uri,
)));
}
}
// Look for existing term matching this one and blend the properties
// Ensure name is valid
if (!$term->name) {
// Fallback to a name, identifier derived (roughly) from the URI - not always meaningful, but all we have in some contexts.
$term->name = basename($uri);
drupal_set_message(t("Problem, we were unable to find a specific label for the term referred to as %uri. Guessing that %name will be good enough.", array(
'%uri' => $uri,
'%name' => $term->name,
)));
}
if (!$term->name) {
// Should never get here
drupal_set_message(t("Problem, this term %uri does not have a readable label.", array(
'%uri' => $uri,
)));
next;
}
# dpm(array('data to merge' => $term));
// See if a definition already exisits in the DB. Build on that.
$existing_term = _taxonomy_xml_get_term_placeholder($term->name, $vid);
// Merge the old term objects properties into this one. Really just want its tid, but there may be more info I should not lose.
// New input takes precedence over older data
foreach ((array) $existing_term as $key => $value) {
if (!isset($term->{$key})) {
$term->{$key} = $value;
}
}
// The term object is now as tidy as it can be as a self-contained entity.
# dpm($term);
// MAINTAIN IDS
// Because this is likely to be used with a site-cloning set-up, it would help if we tried to match IDs
// OTOH, doing so could be very messy for other situations.
// So,
// iff there is no pre-existing term with this id,
// create this one as a clone with the old ID.
// This requires a little DB sneakiness.
if ($term->internal_id && !taxonomy_get_term($term->internal_id)) {
$term->tid = $term->internal_id;
drupal_set_message(t("Doing sneaky import of %term_name re-using the internal id = %term_id", array(
'%term_name' => $term->name,
'%term_id' => $term->internal_id,
)));
db_query("INSERT INTO {term_data} (tid, name, description, vid, weight) VALUES (%d, '%s', '%s', %d, %d)", $term->tid, $term->name, $term->description, $term->vid, $term->weight);
// Fudge the sequences table to patch the hack we just did, avoid over-writing later
$current_id = db_result(db_query("SELECT id FROM {sequences} WHERE name = '%s'", '{term_data}_tid'));
if ($current_id < $term->tid) {
db_query("REPLACE INTO {sequences} VALUES ('%s', %d)", '{term_data}_tid', $term->tid);
}
}
#dpm(array("ready to save" => $term));
$save_term = (array) $term;
taxonomy_save_term($save_term);
// Re-retrieve the new term definition, just in case anything extra happened to it during processing
$new_term = taxonomy_xml_get_term_by_name_from_vocab($term->name, $term->vid);
if (!$new_term) {
drupal_set_message(t("It seems like we failed to create and retrieve a term called %term_name", array(
'%term_name' => $term->name,
)), 'error');
}
// Merge retrieved values back over our main definition so the handles are up-to-date
foreach ((array) $new_term as $key => $value) {
$term->{$key} = $value;
}
}
// end term-construction loop;
#dpm("Saved all, now linking!");
#dpm($terms);
// Now the terms are all happily created, create their relationships
// Couldn't do so until they had all been given tids.
taxonomy_xml_set_term_relations($terms);
$term_list = array();
foreach ($terms as $term) {
$term_list[] = l($term->name, 'admin/content/taxonomy/edit/term/' . $term->tid);
}
drupal_set_message(t('Updated %count term(s)', array(
'%count' => count($terms),
)) . ' <i>' . implode(', ', $term_list) . '.</i> ');
drupal_set_message(t("\n Finished importing vocabulary %vocab_name. \n You may now need to <a href='!settings_link'>Review the vocabulary settings</a> \n or <a href='!list_link'>List the terms</a>", array(
'%vocab_name' => $vocabulary->name,
'!settings_link' => url('admin/content/taxonomy/edit/vocabulary/' . $vid),
'!list_link' => url('admin/content/taxonomy/' . $vid),
)));
return count($term_list);
}
/**
* Compile triple statements into information objects again.
*
* Returns a nested array, Indexed on their URI/id, and grouped by type
* (references so we can change them) This currently assumes ALL found info
* objects as terms, which is not quite right
*/
function taxonomy_xml_convert_triples_to_sorted_objects(&$triples) {
// Triples are boringly granular bits of information.
// Merge them.
$resources = array();
$resources_by_type = array();
foreach ($triples as $triplenum => $statement) {
$subject_uri = $statement['s']['uri'];
if (!isset($resources[$subject_uri])) {
// Create placeholder if this is the first occurance
$resources[$subject_uri] = (object) array();
}
$subject =& $resources[$subject_uri];
# dpm(array("Processing a statement about $subject_uri" => $statement));
switch ($statement['o']['type']) {
case 'uri':
$object_uri = $statement['o']['uri'];
// Also make a placeholder for the object, for convenience
// It's not much fun referring to something that doesn't exist.
if (!isset($resources[$object_uri])) {
$resources[$object_uri] = (object) array();
}
$object_val = $object_uri;
break;
default:
$object_val = trim($statement['o']['val']);
}
// Placeholders ready, now add this statements info
// Namespaces are boring, Simplify the predicates
// TODO - revisit if namespaces are needed
$predicate = taxonomy_xml_rdf_shortname($statement['p']);
if (!isset($subject->predicates[$predicate])) {
$subject->predicates[$predicate] = array();
}
// Some properties can be collated, listed
// Some need to be merged or selected (languages)
// In this stage of pre-processing, we cannot select which string we need, so gather all values
if ($statement['o']['type'] == 'literal' && ($lang = $statement['o']['lang'])) {
$subject->predicates[$predicate][$lang] = $object_val;
}
else {
// Only add uniques, Keeps clutter down
if (!in_array($object_val, $subject->predicates[$predicate])) {
$subject->predicates[$predicate][] = $object_val;
}
}
if ($predicate == 'type') {
// Very important info!
$subject->type = $object_val;
// Sort it! (by reference)
$resources_by_type[$subject->type][$subject_uri] =& $subject;
}
if ($predicate == TAXONOMY_XML_NAME) {
$subject->name = $object_val;
}
// This is very memory-intensive for big vocabs. Try to clean up :(
unset($triples[$triplenum]);
}
// Scan the full array for any lost data - just FYI
$unknown_resources = array();
foreach ($resources as $uri => &$resource) {
if (!isset($resource->type)) {
$unknown_resources[$uri] =& $resource;
}
// While we are looping,
// Make a guess at its original, internal ID
// grabbing the last numeric bit from the id in the document
// eg from '#vocab/1' or '#vocabulary:1' or #term33
// Be very generic and forgiving in the format we look for
$parts = preg_split('|[^\\d]|', $uri);
$last_num = array_pop($parts);
if (is_numeric($last_num)) {
$resource->internal_id = $last_num;
}
}
if ($unknown_resources) {
#drupal_set_message(t("Found %count Unsorted (untyped) resources. Not sure what I'll do with these. They are things that have had statements made about them .. that I don't recognise. Probably just extra data found in the input and ignored. %unknown", array('%count' => count($unknown_resources), '%unknown' => join(', ', array_keys($unknown_resources))) ));
}
return $resources_by_type;
}
/**
* Choose a string from an array of language-tagged possibilities
*
* Util func to help read complex RDF statements.
*/
function taxonomy_xml_get_literal_string($values) {
if (!is_array($values)) {
return trim($values);
}
// May need to choose language
if (count($values) == 1) {
$out = array_pop($values);
}
else {
// TODO add language selector
if ($label = $values['en']) {
$out = $label;
}
else {
// fine, whatever
$out = array_pop($values);
}
}
return trim($out);
}
/**
* Return the shorthand label of a potentially long RDF URI
*
* EG, for http://www.w3.org/1999/02/22-rdf-syntax-ns#Property
* return 'Property'
* ... for sanity
*/
function taxonomy_xml_rdf_shortname($uri) {
$parts = parse_url($uri);
$shortname = $parts['fragment'] ? $parts['fragment'] : ($parts['query'] ? $parts['query'] : basename($parts['path']));
// The proper method for guessing simple names is probably documented elsewhere.
// ... this does the trick for now.
return $shortname;
}
/**
* Return an XML/RDF document representing this vocab
*
* I'd like to use ARC libraries, but it doesn't appear to include an RDF
* serializer output method, only an input parser...
*
* Uses PHP DOM to create DOM document and nodes.
*
* We use namespaces carefully here, although it may create wordy output if the
* DOM is not optimizing the declarations for us. Still, best to be explicit, it
* would seem.
*
* The URI used to refer to other resources is based on the source document
* location, eg
* http://this.server/taxonomy_xml/{vid}/rdf#{tid}
*
* Preamble should look something like:
*
* <rdf:RDF xmlns:rdf ="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
* xmlns: rdfs="http://www.w3.org/2000/01/rdf-schema#"
* xmlns: owl="http://www.w3.org/2002/07/owl#"
*
*/
function taxonomy_xml_rdf_create($vid, $parent = 0, $depth = -1, $max_depth = NULL) {
$vocabulary = taxonomy_vocabulary_load($vid);
$domcontainer = taxonomy_xml_rdf_document();
$dom = $domcontainer->ownerDocument;
#dpm(array(domcontainer => $domcontainer, dom => $dom));
// define the vocab
taxonomy_xml_add_vocab_as_rdf($domcontainer, $vocabulary);
// and more details?
// Now start adding terms.
// They are listed as siblings, not children of the ontology
$tree = module_invoke('taxonomy', 'get_tree', $vid, $parent, $depth, $max_depth);
taxonomy_xml_add_terms_as_rdf($domcontainer, $tree);
$result = $dom
->savexml();
// Minor layout tweak for readability
$result = preg_replace('|(<[^<]*/[^>]*>)|', "\$1\n", $result);
$result = preg_replace('|><|', ">\n<", $result);
# dpm($result);
return $result;
}
/**
* Set up an RDF document preamble.
* Returns a document, also sets the passed handle to the RDF node that content
* should land in
*
*/
function taxonomy_xml_rdf_document() {
$dom = new domdocument('1.0', 'UTF-8');
$dom
->appendchild($dom
->createcomment(htmlentities("\n This file was created by Drupal taxonomy_xml import/export tool. \n http://drupal.org/project/taxonomy_xml\n\n The RDF schema in this file is intended to follow the Working Draft\n described at http://www.w3.org/TR/wordnet-rdf/ for the notation of\n thesauri and taxonomies.\n ")));
$dom
->appendchild($dom
->createprocessinginstruction('xml-stylesheet', 'href="render-taxonomy-rdf.xsl" type="text/xsl"'));
$domcontainer = $dom
->createelementns(TAXONOMY_XML_RDF_NS, 'rdf:RDF');
# $rdfnode->setattribute('xmlns', TAXONOMY_XML_RDFS_NS);
$dom
->appendchild($domcontainer);
// Why can't I set more namespaces?
// By appending a namespaced att, the extra namespaces appear at the top.
// Otherwise the appear everywhere. There must be a better way
$domcontainer
->setattributens(TAXONOMY_XML_RDFS_NS, 'rdfs:title', "Initializing namespace in PHP is hard");
$domcontainer
->setattributens(TAXONOMY_XML_OWL_NS, 'owl:hack', "Initializing namespace in PHP is hard");
// Note that one way to get namespaces to work right is by adding new
// elements to their context asap, not by waiting until after further bits are added.
return $domcontainer;
}
/**
* Create a vocabulary definition (just the def, not its terms) and insert it
* into the given document element.
*
* @param $domcontainer an XML dom document, modified by ref.
* @param $vocabulary a vocab object
*/
function taxonomy_xml_add_vocab_as_rdf(&$domcontainer, $vocabulary) {
$dom = $domcontainer->ownerDocument;
// Describe the vocabulary itself
$vocabnode = $dom
->createelementns(TAXONOMY_XML_OWL_NS, 'owl:Ontology');
$domcontainer
->appendchild($vocabnode);
// If this was a cannonic vocab, we would use a full URI as identifiers
$vocabnode
->setattributens(TAXONOMY_XML_RDF_NS, 'rdf:ID', 'vocabulary-' . $vocabulary->vid);
$vocabnode
->setattributens(TAXONOMY_XML_RDF_NS, 'rdf:about', url('taxonomy_xml/' . $vocabulary->vid . '/rdf', NULL, NULL, TRUE));
$vocabnode
->appendchild($dom
->createelementns(TAXONOMY_XML_RDFS_NS, 'rdfs:label', htmlentities($vocabulary->name)));
if ($vocabulary->description) {
$vocabnode
->appendchild($dom
->createelementns(TAXONOMY_XML_RDFS_NS, 'rdfs:comment', htmlentities($vocabulary->description)));
}
$vocabnode
->appendchild($dom
->createelementns(TAXONOMY_XML_OWL_NS, 'owl:versionInfo', htmlentities(format_date(time(), 'large'))));
}
/**
* Given a list of terms, append definitions of them to the passed DOM container
*
* Following w3c, SUMO and Wordnet examples (tho not any explicit instructions,
* taxonomy terms are modelled as rdfs:Class objects structured using rdfs:
* subClassOf statements.
*
* Sample from Wordnet:
*
* <Class rdf:about="http://xmlns.com/wordnet/1.6/Cat">
* <label>Cat [ 1 ]</label>
* <comment>feline mammal usually having thick soft fur and being unable
* to roar; domestic cats; wildcats</comment>
* <subClassOf>
* <Class rdf:about="http://xmlns.com/wordnet/1.6/Feline" />
* </subClassOf>
* </Class>
*
* I'm copying that syntax.
*
* @param $termlist a FLAT array of all terms, internally cross-referenced to
* each other defining the tree stucture
*/
function taxonomy_xml_add_terms_as_rdf(&$domcontainer, $termlist) {
if (!$termlist) {
return;
}
$dom = $domcontainer->ownerDocument;
foreach ($termlist as $term) {
$termnode = $dom
->createelementns(TAXONOMY_XML_RDFS_NS, 'rdfs:Class');
$termnode
->setattributens(TAXONOMY_XML_RDF_NS, 'rdf:ID', 'term-' . $term->tid);
$domcontainer
->appendchild($termnode);
$termnode
->appendchild($dom
->createelementns(TAXONOMY_XML_RDFS_NS, 'rdfs:label', htmlentities($term->name)));
if ($term->description) {
$termnode
->appendchild($dom
->createelementns(TAXONOMY_XML_RDFS_NS, 'rdfs:comment', htmlentities($term->description)));
}
$vocab_ref = $dom
->createelementns(TAXONOMY_XML_RDFS_NS, 'rdfs:isDefinedBy');
$vocab_ref
->setattributens(TAXONOMY_XML_RDF_NS, 'rdf:resource', '#vocabulary-' . $term->vid);
$termnode
->appendchild($vocab_ref);
foreach ((array) taxonomy_get_related($term->tid) as $relatedid => $relatedterm) {
$related_node = $dom
->createelementns(TAXONOMY_XML_RDFS_NS, 'rdfs:seeAlso', htmlentities($relatedterm->name));
$related_node
->setattributens(TAXONOMY_XML_RDF_NS, 'rdf:resource', '#term-' . $relatedid);
$termnode
->appendchild($related_node);
}
$synonyms = taxonomy_get_synonyms($term->tid);
// TODO - figure out the right syntax for synonym
// I'm using 'equivalentClass' ... although that's really intended for merging different vocabs.
foreach ((array) $synonyms as $synonymname) {
$synonymnode = $parent_node = $dom
->createelementns(TAXONOMY_XML_OWL_NS, 'owl:equivalentClass', htmlentities($synonymname));
$termnode
->appendchild($synonymnode);
}
foreach ((array) $term->parents as $parentid) {
$parentlist = array();
if ($parentid) {
$parentlist[$parentid] = $parent = taxonomy_get_term($parentid);
$parent_node = $dom
->createelementns(TAXONOMY_XML_RDFS_NS, 'rdfs:subClassOf', htmlentities($parent->name));
$parent_node
->setattributens(TAXONOMY_XML_RDF_NS, 'rdf:resource', '#term-' . $parentid);
$termnode
->appendchild($parent_node);
}
}
# dpm(array('adding term to rdf' => $term));
#$termnode->appendchild($dom->createcomment(print_r($term, 1)));
// workaround for large vocabs - extend runtime indefinately
set_time_limit(10);
}
// Done all terms in list
}
Functions
Name![]() |
Description |
---|---|
taxonomy_xml_add_terms_as_rdf | Given a list of terms, append definitions of them to the passed DOM container |
taxonomy_xml_add_vocab_as_rdf | Create a vocabulary definition (just the def, not its terms) and insert it into the given document element. |
taxonomy_xml_convert_triples_to_sorted_objects | Compile triple statements into information objects again. |
taxonomy_xml_get_literal_string | Choose a string from an array of language-tagged possibilities |
taxonomy_xml_rdf_create | Return an XML/RDF document representing this vocab |
taxonomy_xml_rdf_document | Set up an RDF document preamble. Returns a document, also sets the passed handle to the RDF node that content should land in |
taxonomy_xml_rdf_parse | Read in RDF taxonomies and vocabularies. Create vocabs and terms as needed. |
taxonomy_xml_rdf_shortname | Return the shorthand label of a potentially long RDF URI |
Constants
Name![]() |
Description |
---|---|
TAXONOMY_XML_CATEGORY | |
TAXONOMY_XML_CONTENTLABEL_NS | |
TAXONOMY_XML_OWL_NS | |
TAXONOMY_XML_RDFS_NS | |
TAXONOMY_XML_RDF_NS | @file Include routines for RDF parsing and taxonomy/term creation. |
TAXONOMY_XML_SKOS_NS | |
TAXONOMY_XML_TYPE | |
TAXONOMY_XML_W3C_WN | |
TAXONOMY_XML_W3C_WN_SCHEMA |