7 * Copyright (c) 2009-2013 Nicholas J Humfrey. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
17 * promote products derived from this software without specific prior
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 * @copyright Copyright (c) 2009-2013 Nicholas J Humfrey
34 * @license http://www.opensource.org/licenses/bsd-license.php
38 * Class to serialise an EasyRdf_Graph to RDF/XML
39 * with no external dependancies.
42 * @copyright Copyright (c) 2009-2013 Nicholas J Humfrey
43 * @license http://www.opensource.org/licenses/bsd-license.php
45 class EasyRdf_Serialiser_RdfXml extends EasyRdf_Serialiser
47 private $outputtedResources = array();
49 /** A constant for the RDF Type property URI */
50 const RDF_XML_LITERAL = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral';
53 * Protected method to serialise an object node into an XML object
56 protected function rdfxmlObject($property, $obj, $depth)
58 $indent = str_repeat(' ', $depth);
60 if ($property[0] === ':') {
61 $property = substr($property, 1);
64 if (is_object($obj) and $obj instanceof EasyRdf_Resource) {
65 $pcount = count($obj->propertyUris());
66 $rpcount = $this->reversePropertyCount($obj);
67 $alreadyOutput = isset($this->outputtedResources[$obj->getUri()]);
69 $tag = "{$indent}<{$property}";
70 if ($obj->isBNode()) {
71 if ($alreadyOutput or $rpcount > 1 or $pcount == 0) {
72 $tag .= " rdf:nodeID=\"".htmlspecialchars($obj->getBNodeId()).'"';
75 if ($alreadyOutput or $rpcount != 1 or $pcount == 0) {
76 $tag .= " rdf:resource=\"".htmlspecialchars($obj->getURI()).'"';
80 if ($alreadyOutput == false and $rpcount == 1 and $pcount > 0) {
81 $xml = $this->rdfxmlResource($obj, false, $depth+1);
83 return "$tag>$xml$indent</$property>\n\n";
91 } elseif (is_object($obj) and $obj instanceof EasyRdf_Literal) {
93 $datatype = $obj->getDatatypeUri();
95 if ($datatype == self::RDF_XML_LITERAL) {
96 $atrributes .= " rdf:parseType=\"Literal\"";
97 $value = strval($obj);
99 $datatype = htmlspecialchars($datatype);
100 $atrributes .= " rdf:datatype=\"$datatype\"";
102 } elseif ($obj->getLang()) {
103 $atrributes .= ' xml:lang="'.
104 htmlspecialchars($obj->getLang()).'"';
108 if (!isset($value)) {
109 $value = htmlspecialchars(strval($obj));
112 return "{$indent}<{$property}{$atrributes}>{$value}</{$property}>\n";
114 throw new EasyRdf_Exception(
115 "Unable to serialise object to xml: ".getType($obj)
121 * Protected method to serialise a whole resource and its properties
124 protected function rdfxmlResource($res, $showNodeId, $depth = 1)
126 // Keep track of the resources we have already serialised
127 if (isset($this->outputtedResources[$res->getUri()])) {
130 $this->outputtedResources[$res->getUri()] = true;
133 // If the resource has no properties - don't serialise it
134 $properties = $res->propertyUris();
135 if (count($properties) == 0) {
139 $type = $res->type();
141 $this->addPrefix($type);
143 $type = 'rdf:Description';
146 $indent = str_repeat(' ', $depth);
147 $xml = "\n$indent<$type";
148 if ($res->isBNode()) {
150 $xml .= ' rdf:nodeID="'.htmlspecialchars($res->getBNodeId()).'"';
153 $xml .= ' rdf:about="'.htmlspecialchars($res->getUri()).'"';
157 if ($res instanceof EasyRdf_Container) {
158 foreach ($res as $item) {
159 $xml .= $this->rdfxmlObject('rdf:li', $item, $depth+1);
162 foreach ($properties as $property) {
163 $short = EasyRdf_Namespace::shorten($property, true);
165 $this->addPrefix($short);
166 $objects = $res->all("<$property>");
167 if ($short == 'rdf:type' && $type != 'rdf:Description') {
168 array_shift($objects);
170 foreach ($objects as $object) {
171 $xml .= $this->rdfxmlObject($short, $object, $depth+1);
174 throw new EasyRdf_Exception(
175 "It is not possible to serialse the property ".
176 "'$property' to RDF/XML."
181 $xml .= "$indent</$type>\n";
188 * Method to serialise an EasyRdf_Graph to RDF/XML
190 * @param EasyRdf_Graph $graph An EasyRdf_Graph object.
191 * @param string $format The name of the format to convert to.
192 * @param array $options
193 * @throws EasyRdf_Exception
194 * @return string The RDF in the new desired format.
196 public function serialise($graph, $format, array $options = array())
198 parent::checkSerialiseParams($graph, $format);
200 if ($format != 'rdfxml') {
201 throw new EasyRdf_Exception(
202 "EasyRdf_Serialiser_RdfXml does not support: $format"
206 // store of namespaces to be appended to the rdf:RDF tag
207 $this->prefixes = array('rdf' => true);
209 // store of the resource URIs we have serialised
210 $this->outputtedResources = array();
214 // Serialise URIs first
215 foreach ($graph->resources() as $resource) {
216 if (!$resource->isBnode()) {
217 $xml .= $this->rdfxmlResource($resource, true);
221 // Serialise bnodes afterwards
222 foreach ($graph->resources() as $resource) {
223 if ($resource->isBnode()) {
224 $xml .= $this->rdfxmlResource($resource, true);
228 // iterate through namepsaces array prefix and output a string.
230 foreach ($this->prefixes as $prefix => $count) {
231 $url = EasyRdf_Namespace::get($prefix);
233 if (strlen($namespaceStr)) {
234 $namespaceStr .= "\n ";
237 if (strlen($prefix) === 0) {
238 $namespaceStr .= ' xmlns="'.htmlspecialchars($url).'"';
240 $namespaceStr .= ' xmlns:'.$prefix.'="'.htmlspecialchars($url).'"';
244 return "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n".
245 "<rdf:RDF". $namespaceStr . ">\n" . $xml . "\n</rdf:RDF>\n";