3 * What to do on ?format=rdf What to do on ?format=owl
5 * Map relations on a wikipage to a RDF ressource to build a "Semantic Web"
6 * - a web ontology frontend compatible to OWL (web ontology language).
7 * http://www.w3.org/2001/sw/Activity
8 * Simple RDF ontologies contain facts and rules, expressed by RDF triples:
9 * Subject (page) -> Predicate (verb, relation) -> Object (links)
10 * OWL extents that to represent a typical OO framework.
14 * subClassOf, restrictedBy, onProperty, intersectionOf, allValuesFrom, ...
15 * someValuesFrom, unionOf, equivalentClass, disjointWith, ...
16 * plus the custom vocabulary (ontology): canRun, canBite, smellsGood, ...
17 * OWL Subjects: Class, Restriction, ...
18 * OWL Properties: type, label, comment, ...
19 * DAML should also be supported.
22 * - Another way to represent various KB models in various DL languages.
24 * - Frontend to various KB model reasoners and representations.
25 * - Generation/update of static wiki pages based on external OWL/DL/KB
26 * (=> ModelTest/Categories)
27 * KB Blackboard and Visualization.
28 * - OWL generation based on static wiki pages (ModelTest?format=owl)
30 * Facts: (may be represented by special links on a page)
31 * - Each page must be representable with an unique URL.
32 * - Each fact must be representable with an unique RDF triple.
33 * - A class is represented by a category page.
34 * - To represent more expressive description logic, "enriched"
35 * links will not be enough (? variable symbolic objects).
37 * Rules: (may be represented by special content on a page)
38 * - Syntax: reasoner backend specific, or common or ?
40 * RDF Triple: (representing facts)
41 * Subject (page) -> Predicate (verb, relation) -> Object (links)
44 * Special link qualifiers represent RDF triples, based on RDF standard notation.
45 * See RDF standard DTD's on daml.org and w3.org, plus your custom predicates.
47 * Example: page [Ape] isa:Animal, ...
48 * Object: special links on a page.
50 * Model: Basepage for a KB. (parametrizeable pages or copies of modified snapshots?)
52 * DL: Description Logic
56 * Of course *real* expert systems ("reasoners") will help/must be used in
57 * optimization and maintainance of the SemanticWeb KB (Knowledge
58 * Base). Hooks will be tested to KM (an interactive KB playground),
59 * LISA (standard unifier), FaCT, RACER, ...
60 * Maybe also ZEBU (parser generator) is needed to convert the wiki KB
61 * syntax to the KB reasoner backend (LISA, KM, CLIPS, JESS, FaCT,
63 * pOWL is a simple php backend with some very simple AI logic in PHP,
64 * though I strongly doubt the usefulness of reasoners not written in
67 * SEAL (omntoweb.org) is similar to that, just on top of the Zope CMF.
68 * FaCT uses e.g. this KB DTD:
69 <!ELEMENT KNOWLEDGEBASE (DEFCONCEPT|DEFROLE|IMPLIESC|EQUALC|IMPLIESR|EQUALR|TRANSITIVE|FUNCTIONAL)*>
70 <!ELEMENT CONCEPT (PRIMITIVE|TOP|BOTTOM|AND|OR|NOT|SOME|ALL|ATMOST|ATLEAST)>
71 <!ELEMENT ROLE (PRIMROLE|INVROLE)>
72 ... (facts and rules described in XML)
75 * http://phpwiki.org/SemanticWeb,
76 * http://en.wikipedia.org/wiki/Knowledge_representation
77 * http://www.ontoweb.org/
78 * http://www.semwebcentral.org/ (OWL on top of FusionForge)
81 * Author: Reini Urban <rurban@x-ray.at>
83 /*============================================================================*/
85 * Copyright 2004,2007 Reini Urban
87 * This file is part of PhpWiki.
89 * PhpWiki is free software; you can redistribute it and/or modify
90 * it under the terms of the GNU General Public License as published by
91 * the Free Software Foundation; either version 2 of the License, or
92 * (at your option) any later version.
94 * PhpWiki is distributed in the hope that it will be useful,
95 * but WITHOUT ANY WARRANTY; without even the implied warranty of
96 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
97 * GNU General Public License for more details.
99 * You should have received a copy of the GNU General Public License along
100 * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
101 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
104 require_once 'lib/RssWriter.php';
105 require_once 'lib/TextSearchQuery.php';
106 require_once 'lib/Units.php';
109 * RdfWriter - A class to represent the links of a list of wikipages as RDF.
110 * Supports ?format=rdf
112 * RdfWriter (unsorted)
113 * - RssWriter (timesorted)
114 * - RecentChanges (?action=RecentChanges&format=rdf) (filtered)
116 class RdfWriter extends RssWriter // in fact it should be rewritten to be other way round.
118 function RdfWriter(&$request, &$pagelist)
120 $this->_request =& $request;
121 $this->_pagelist =& $pagelist;
122 $this->XmlElement('rdf:RDF',
123 array('xmlns' => "http://purl.org/rss/1.0/",
124 'xmlns:rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'));
126 $this->_modules = array(
128 'content' => "http://purl.org/rss/1.0/modules/content/",
129 'dc' => "http://purl.org/dc/elements/1.1/",
132 $this->_uris_seen = array();
133 $this->_items = array();
135 $this->wiki_xmlns_xml = WikiURL(_("UriResolver") . "?", false, true);
136 $this->wiki_xmlns_url = PHPWIKI_BASE_URL;
138 $this->pre_ns_buffer =
139 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" .
140 "<!DOCTYPE rdf:RDF[\n" .
141 "\t" . "<!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n" .
142 "\t" . "<!ENTITY rdfs 'http://www.w3.org/2000/01/rdf-schema#'>\n" .
143 "\t" . "<!ENTITY owl 'http://www.w3.org/2002/07/owl#'>\n" .
144 "\t" . "<!ENTITY smw 'http://smw.ontoware.org/2005/smw#'>\n" .
145 "\t" . "<!ENTITY smwdt 'http://smw.ontoware.org/2005/smw-datatype#'>\n" .
146 // A note on "wiki": this namespace is crucial as a fallback when it would be illegal to start e.g. with a number. In this case, one can always use wiki:... followed by "_" and possibly some namespace, since _ is legal as a first character.
147 "\t" . "<!ENTITY wiki '" . $this->wiki_xmlns_xml . "'>\n" .
148 "\t" . "<!ENTITY relation '" . $this->wiki_xmlns_xml .
149 $this->makeXMLExportId(urlencode(str_replace(' ', '_', _("Relation") . ':'))) . "'>\n" .
150 "\t" . "<!ENTITY attribute '" . $this->wiki_xmlns_xml .
151 $this->makeXMLExportId(urlencode(str_replace(' ', '_', _("Attribute") . ':'))) . "'>\n" .
152 "\t" . "<!ENTITY wikiurl '" . $this->wiki_xmlns_url . "'>\n" .
155 "\t" . "xmlns:rdf=\"&rdf;\"\n" .
156 "\t" . "xmlns:rdfs=\"&rdfs;\"\n" .
157 "\t" . "xmlns:owl =\"&owl;\"\n" .
158 "\t" . "xmlns:smw=\"&smw;\"\n" .
159 "\t" . "xmlns:wiki=\"&wiki;\"\n" .
160 "\t" . "xmlns:relation=\"&relation;\"\n" .
161 "\t" . "xmlns:attribute=\"&attribute;\"";
162 $this->post_ns_buffer =
163 "\n\t<!-- reference to the Semantic MediaWiki schema -->\n" .
164 "\t" . "<owl:AnnotationProperty rdf:about=\"&smw;hasArticle\">\n" .
165 "\t\t" . "<rdfs:isDefinedBy rdf:resource=\"http://smw.ontoware.org/2005/smw\"/>\n" .
166 "\t" . "</owl:AnnotationProperty>\n" .
167 "\t" . "<owl:AnnotationProperty rdf:about=\"&smw;hasType\">\n" .
168 "\t\t" . "<rdfs:isDefinedBy rdf:resource=\"http://smw.ontoware.org/2005/smw\"/>\n" .
169 "\t" . "</owl:AnnotationProperty>\n" .
170 "\t" . "<owl:Class rdf:about=\"&smw;Thing\">\n" .
171 "\t\t" . "<rdfs:isDefinedBy rdf:resource=\"http://smw.ontoware.org/2005/smw\"/>\n" .
172 "\t" . "</owl:Class>\n" .
173 "\t<!-- exported page data -->\n";
178 header("Content-type: application/rdf+xml; charset=UTF-8");
179 echo $this->pre_ns_buffer;
183 $dbi = $this->_request->_dbi;
184 /* Elements per page:
185 out-links internal, out-links external
190 foreach ($this->_pagelist->_pages as $page) {
191 $relation = new TextSearchQuery("*");
192 foreach (array('linkto', 'linkfrom', 'relation', 'attribute') as $linktype) {
193 $linkiter = $dbi->linkSearch($pages, $search, $linktype, $relation);
195 while ($link = $linkiter->next()) {
196 if (mayAccessPage('view', $rev->_pagename)) {
197 $linkto->addItem($this->item_properties($rev),
198 $this->pageURI($rev));
200 $this->setValidators($rev);
206 echo $this->post_ns_buffer;
210 /** This function transforms a valid url-encoded URI into a string
211 * that can be used as an XML-ID. The mapping should be injective.
213 function makeXMLExportId($uri)
215 $uri = str_replace('-', '-2D', $uri);
216 //$uri = str_replace( ':', '-3A', $uri); //already done by PHP
217 //$uri = str_replace( '_', '-5F', $uri); //not necessary
218 $uri = str_replace(array('"', '#', '&', "'", '+', '=', '%'),
219 array('-22', '-23', '-26', '-27', '-2B', '-3D', '-'),
224 /** This function transforms an XML-ID string into a valid
225 * url-encoded URI. This is the inverse to makeXMLExportID.
227 function makeURIfromXMLExportId($id)
229 $id = str_replace(array('-22', '-23', '-26', '-27', '-2B', '-3D', '-'),
230 array('"', '#', '&', "'", '+', '=', '%'),
232 $id = str_replace('-2D', '-', $id);
239 class RdfsWriter extends RdfWriter
244 * OwlWriter - A class to represent a set of wiki pages (a DL model) as OWL.
245 * Requires an actionpage returning a pagelist.
246 * Supports ?format=owl
252 class OwlWriter extends RdfWriter
257 * ModelWriter - Export a KB as set of wiki pages.
258 * Requires an actionpage returning a pagelist.
259 * Probably based on some convenient DL expression syntax. (deffact, defrule, ...)
265 class ModelWriter extends OwlWriter
270 * NumericSearchQuery can do:
271 * ("population < 20000 and area > 1000000", array("population", "area"))
272 * ->match(array('population' => 100000, 'area' => 10000000))
273 * @see NumericSearchQuery
275 * SemanticAttributeSearchQuery can detect and unify units in numbers.
276 * ("population < 2million and area > 100km2", array("population", "area"))
277 * ->match(array('population' => 100000, 'area' => 10000000))
279 * Do we need a real parser or can we just regexp over some allowed unit
280 * suffixes to detect the numbers?
281 * See man units(1) and /usr/share/units.dat
282 * base units: $ units "1 million miles"
283 * Definition: 1.609344e+09 m
285 class SemanticAttributeSearchQuery
286 extends NumericSearchQuery
289 public $base_units = array('m' => explode(',','km,miles,cm,dm,mm,ft,inch,inches,meter'),
290 'm^2' => explode(',','km^2,ha,cm^2,mi^2'),
291 'm^3' => explode(',','km^3,lit,cm^3,dm^3,gallons'),
296 * We need to detect units from the freetext query:
297 * population > 1 million
299 function SemanticAttributeSearchQuery($search_query, $placeholders, $unit = '')
301 $this->NumericSearchQuery($search_query, $placeholders);
302 $this->_units = new Units();
307 * Strip non-numeric chars from the variable (as the groupseperator) and replace
308 * it in the symbolic query for evaluation.
309 * This version unifies the attribute values from the database to a
310 * numeric basevalue before comparison. (area:=963.6km^2 => 9.366e+08 m^2)
313 * @param $value number A numerical value: integer, float or string.
314 * @param $x string The variable name to be replaced in the query.
317 function _bind($value, $x)
320 $value = preg_replace("/,/", "", $value);
321 $this->_bound[] = array('linkname' => $x,
322 'linkvalue' => $value);
323 // We must ensure that the same baseunits are matched against.
324 // We cannot compare m^2 to m or ''
325 $val_base = $this->_units->basevalue($value);
326 if (!DISABLE_UNITS and $this->_units->baseunit($value) != $this->unit) {
327 // Poor user has selected an attribute, but no unit. assume he means the baseunit
328 if (count($this->getVars() == 1) and $this->unit == '') {
331 // non-matching units are silently ignored
332 $this->_workquery = '';
337 if (!is_numeric($value)) {
338 $this->_workquery = ''; //must return false
339 trigger_error("Cannot match against non-numeric attribute value $x := $ori_value",
344 $this->_workquery = preg_replace("/\b" . preg_quote($x, "/") . "\b/", $value, $this->_workquery);
345 return $this->_workquery;
351 * SemanticSearchQuery can do:
352 * (is_a::city and population < 20000) and (*::city and area > 1000000)
353 * ->match(array('is_a' => 'city', 'linkfrom' => array(),
354 * population' => 100000, 'area' => 10000000))
355 * @return array A list of found and bound matches
357 class SemanticSearchQuery
358 extends SemanticAttributeSearchQuery
360 function hasAttributes()
364 function hasRelations()
368 function getLinkNames()
374 * ReasonerBackend - hooks to reasoner backends.
375 * via http as with DIG,
378 class ReasonerBackend
380 function ReasonerBackend()
386 * transform to reasoner syntax
388 function transformTo()
394 * transform from reasoner syntax
396 function transformFrom()
410 class ReasonerBackend_LISA extends ReasonerBackend
414 class ReasonerBackend_Racer extends ReasonerBackend
418 class ReasonerBackend_KM extends ReasonerBackend
426 // c-hanging-comment-ender-p: nil
427 // indent-tabs-mode: nil