|
/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for |
|
* full list of contributors). Published under the Clear BSD license. |
|
* See http://svn.openlayers.org/trunk/openlayers/license.txt for the |
|
* full text of the license. */ |
|
|
|
/** |
|
* @requires OpenLayers/Format/XML.js |
|
* @requires OpenLayers/Format/GML/v3.js |
|
* @requires OpenLayers/Feature/Vector.js |
|
*/ |
|
|
|
/** |
|
* Class: OpenLayers.Format.Atom |
|
* Read/write Atom feeds. Create a new instance with the |
|
* <OpenLayers.Format.AtomFeed> constructor. |
|
* |
|
* Inherits from: |
|
* - <OpenLayers.Format.XML> |
|
*/ |
|
OpenLayers.Format.Atom = OpenLayers.Class(OpenLayers.Format.XML, { |
|
|
|
/** |
|
* Property: namespaces |
|
* {Object} Mapping of namespace aliases to namespace URIs. Properties |
|
* of this object should not be set individually. Read-only. All |
|
* XML subclasses should have their own namespaces object. Use |
|
* <setNamespace> to add or set a namespace alias after construction. |
|
*/ |
|
namespaces: { |
|
atom: "http://www.w3.org/2005/Atom", |
|
georss: "http://www.georss.org/georss" |
|
}, |
|
|
|
/** |
|
* APIProperty: feedTitle |
|
* {String} Atom feed elements require a title. Default is "untitled". |
|
*/ |
|
feedTitle: "untitled", |
|
|
|
/** |
|
* APIProperty: defaultEntryTitle |
|
* {String} Atom entry elements require a title. In cases where one is |
|
* not provided in the feature attributes, this will be used. Default |
|
* is "untitled". |
|
*/ |
|
defaultEntryTitle: "untitled", |
|
|
|
/** |
|
* Property: gmlParse |
|
* {Object} GML Format object for parsing features |
|
* Non-API and only created if necessary |
|
*/ |
|
gmlParser: null, |
|
|
|
/** |
|
* APIProperty: xy |
|
* {Boolean} Order of the GML coordinate: true:(x,y) or false:(y,x) |
|
* For GeoRSS the default is (y,x), therefore: false |
|
*/ |
|
xy: false, |
|
|
|
/** |
|
* Constructor: OpenLayers.Format.AtomEntry |
|
* Create a new parser for Atom. |
|
* |
|
* Parameters: |
|
* options - {Object} An optional object whose properties will be set on |
|
* this instance. |
|
*/ |
|
initialize: function(options) { |
|
OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); |
|
}, |
|
|
|
/** |
|
* APIMethod: read |
|
* Return a list of features from an Atom feed or entry document. |
|
|
|
* Parameters: |
|
* doc - {Element} or {String} |
|
* |
|
* Returns: |
|
* An Array of <OpenLayers.Feature.Vector>s |
|
*/ |
|
read: function(doc) { |
|
if (typeof doc == "string") { |
|
doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]); |
|
} |
|
return this.parseFeatures(doc); |
|
}, |
|
|
|
/** |
|
* APIMethod: write |
|
* Serialize or more feature nodes to Atom documents. |
|
* |
|
* Parameters: |
|
* features - a single {<OpenLayers.Feature.Vector>} or an |
|
* Array({<OpenLayers.Feature.Vector>}). |
|
* |
|
* Returns: |
|
* {String} an Atom entry document if passed one feature node, or a feed |
|
* document if passed an array of feature nodes. |
|
*/ |
|
write: function(features) { |
|
var doc; |
|
if (features instanceof Array) { |
|
doc = this.createElementNSPlus("atom:feed"); |
|
doc.appendChild( |
|
this.createElementNSPlus("atom:title", { |
|
value: this.feedTitle |
|
}) |
|
); |
|
for (var i=0, ii=features.length; i<ii; i++) { |
|
doc.appendChild(this.buildEntryNode(features[i])); |
|
} |
|
} |
|
else { |
|
doc = this.buildEntryNode(features); |
|
} |
|
return OpenLayers.Format.XML.prototype.write.apply(this, [doc]); |
|
}, |
|
|
|
/** |
|
* Method: buildContentNode |
|
* |
|
* Parameters: |
|
* content - {Object} |
|
* |
|
* Returns: |
|
* {DOMElement} an Atom content node. |
|
* |
|
* TODO: types other than text. |
|
*/ |
|
buildContentNode: function(content) { |
|
var node = this.createElementNSPlus("atom:content", { |
|
attributes: { |
|
type: content.type || null |
|
} |
|
}); |
|
if (content.src) { |
|
node.setAttribute("src", content.src); |
|
} else { |
|
if (content.type == "text" || content.type == null) { |
|
node.appendChild( |
|
this.createTextNode(content.value) |
|
); |
|
} else if (content.type == "html") { |
|
if (typeof content.value != "string") { |
|
throw "HTML content must be in form of an escaped string"; |
|
} |
|
node.appendChild( |
|
this.createTextNode(content.value) |
|
); |
|
} else if (content.type == "xhtml") { |
|
node.appendChild(content.value); |
|
} else if (content.type == "xhtml" || |
|
content.type.match(/(\+|\/)xml$/)) { |
|
node.appendChild(content.value); |
|
} |
|
else { // MUST be a valid Base64 encoding |
|
node.appendChild( |
|
this.createTextNode(content.value) |
|
); |
|
} |
|
} |
|
return node; |
|
}, |
|
|
|
/** |
|
* Method: buildEntryNode |
|
* Build an Atom entry node from a feature object. |
|
* |
|
* Parameters: |
|
* feature - {<OpenLayers.Feature.Vector>} |
|
* |
|
* Returns: |
|
* {DOMElement} an Atom entry node. |
|
* |
|
* These entries are geared for publication using AtomPub. |
|
* |
|
* TODO: support extension elements |
|
*/ |
|
buildEntryNode: function(feature) { |
|
var attrib = feature.attributes; |
|
var atomAttrib = attrib.atom || {}; |
|
var entryNode = this.createElementNSPlus("atom:entry"); |
|
|
|
// atom:author |
|
if (atomAttrib.authors) { |
|
var authors = atomAttrib.authors instanceof Array ? |
|
atomAttrib.authors : [atomAttrib.authors]; |
|
for (var i=0, ii=authors.length; i<ii; i++) { |
|
entryNode.appendChild( |
|
this.buildPersonConstructNode( |
|
"author", authors[i] |
|
) |
|
); |
|
} |
|
} |
|
|
|
// atom:category |
|
if (atomAttrib.categories) { |
|
var categories = atomAttrib.categories instanceof Array ? |
|
atomAttrib.categories : [atomAttrib.categories]; |
|
var category; |
|
for (var i=0, ii=categories.length; i<ii; i++) { |
|
category = categories[i]; |
|
entryNode.appendChild( |
|
this.createElementNSPlus("atom:category", { |
|
attributes: { |
|
term: category.term, |
|
scheme: category.scheme || null, |
|
label: category.label || null |
|
} |
|
}) |
|
); |
|
} |
|
} |
|
|
|
// atom:content |
|
if (atomAttrib.content) { |
|
entryNode.appendChild(this.buildContentNode(atomAttrib.content)); |
|
} |
|
|
|
// atom:contributor |
|
if (atomAttrib.contributors) { |
|
var contributors = atomAttrib.contributors instanceof Array ? |
|
atomAttrib.contributors : [atomAttrib.contributors]; |
|
for (var i=0, ii=contributors.length; i<ii; i++) { |
|
entryNode.appendChild( |
|
this.buildPersonConstructNode( |
|
"contributor", |
|
contributors[i] |
|
) |
|
); |
|
} |
|
} |
|
|
|
// atom:id |
|
if (feature.fid) { |
|
entryNode.appendChild( |
|
this.createElementNSPlus("atom:id", { |
|
value: feature.fid |
|
}) |
|
); |
|
} |
|
|
|
// atom:link |
|
if (atomAttrib.links) { |
|
var links = atomAttrib.links instanceof Array ? |
|
atomAttrib.links : [atomAttrib.links]; |
|
var link; |
|
for (var i=0, ii=links.length; i<ii; i++) { |
|
link = links[i]; |
|
entryNode.appendChild( |
|
this.createElementNSPlus("atom:link", { |
|
attributes: { |
|
href: link.href, |
|
rel: link.rel || null, |
|
type: link.type || null, |
|
hreflang: link.hreflang || null, |
|
title: link.title || null, |
|
length: link.length || null |
|
} |
|
}) |
|
); |
|
} |
|
} |
|
|
|
// atom:published |
|
if (atomAttrib.published) { |
|
entryNode.appendChild( |
|
this.createElementNSPlus("atom:published", { |
|
value: atomAttrib.published |
|
}) |
|
); |
|
} |
|
|
|
// atom:rights |
|
if (atomAttrib.rights) { |
|
entryNode.appendChild( |
|
this.createElementNSPlus("atom:rights", { |
|
value: atomAttrib.rights |
|
}) |
|
); |
|
} |
|
|
|
// atom:source not implemented |
|
|
|
// atom:summary |
|
if (atomAttrib.summary || attrib.description) { |
|
entryNode.appendChild( |
|
this.createElementNSPlus("atom:summary", { |
|
value: atomAttrib.summary || attrib.description |
|
}) |
|
); |
|
} |
|
|
|
// atom:title |
|
entryNode.appendChild( |
|
this.createElementNSPlus("atom:title", { |
|
value: atomAttrib.title || attrib.title || this.defaultEntryTitle |
|
}) |
|
); |
|
|
|
// atom:updated |
|
if (atomAttrib.updated) { |
|
entryNode.appendChild( |
|
this.createElementNSPlus("atom:updated", { |
|
value: atomAttrib.updated |
|
}) |
|
); |
|
} |
|
|
|
// georss:where |
|
if (feature.geometry) { |
|
var whereNode = this.createElementNSPlus("georss:where"); |
|
whereNode.appendChild( |
|
this.buildGeometryNode(feature.geometry) |
|
); |
|
entryNode.appendChild(whereNode); |
|
} |
|
|
|
return entryNode; |
|
}, |
|
|
|
/** |
|
* Method: initGmlParser |
|
* Creates a GML parser. |
|
*/ |
|
initGmlParser: function() { |
|
this.gmlParser = new OpenLayers.Format.GML.v3({ |
|
xy: this.xy, |
|
featureNS: "http://example.com#feature", |
|
internalProjection: this.internalProjection, |
|
externalProjection: this.externalProjection |
|
}); |
|
}, |
|
|
|
/** |
|
* Method: buildGeometryNode |
|
* builds a GeoRSS node with a given geometry |
|
* |
|
* Parameters: |
|
* geometry - {<OpenLayers.Geometry>} |
|
* |
|
* Returns: |
|
* {DOMElement} A gml node. |
|
*/ |
|
buildGeometryNode: function(geometry) { |
|
if (!this.gmlParser) { |
|
this.initGmlParser(); |
|
} |
|
var node = this.gmlParser.writeNode("feature:_geometry", geometry); |
|
return node.firstChild; |
|
}, |
|
|
|
/** |
|
* Method: buildPersonConstructNode |
|
* |
|
* Parameters: |
|
* name - {String} |
|
* value - {Object} |
|
* |
|
* Returns: |
|
* {DOMElement} an Atom person construct node. |
|
* |
|
* Example: |
|
* >>> buildPersonConstructNode("author", {name: "John Smith"}) |
|
* {<author><name>John Smith</name></author>} |
|
* |
|
* TODO: how to specify extension elements? Add to the oNames array? |
|
*/ |
|
buildPersonConstructNode: function(name, value) { |
|
var oNames = ["uri", "email"]; |
|
var personNode = this.createElementNSPlus("atom:" + name); |
|
personNode.appendChild( |
|
this.createElementNSPlus("atom:name", { |
|
value: value.name |
|
}) |
|
); |