git-svn-id: http://svn.openlayers.org/trunk/openlayers@9180 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
881 lines
31 KiB
JavaScript
881 lines
31 KiB
JavaScript
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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.js
|
|
*/
|
|
|
|
/**
|
|
* Class: OpenLayers.Format.XML
|
|
* Read and write XML. For cross-browser XML generation, use methods on an
|
|
* instance of the XML format class instead of on <code>document<end>.
|
|
* The DOM creation and traversing methods exposed here all mimic the
|
|
* W3C XML DOM methods. Create a new parser with the
|
|
* <OpenLayers.Format.XML> constructor.
|
|
*
|
|
* Inherits from:
|
|
* - <OpenLayers.Format>
|
|
*/
|
|
OpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, {
|
|
|
|
/**
|
|
* 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: null,
|
|
|
|
/**
|
|
* Property: namespaceAlias
|
|
* {Object} Mapping of namespace URI to namespace alias. This object
|
|
* is read-only. Use <setNamespace> to add or set a namespace alias.
|
|
*/
|
|
namespaceAlias: null,
|
|
|
|
/**
|
|
* Property: defaultPrefix
|
|
* {String} The default namespace alias for creating element nodes.
|
|
*/
|
|
defaultPrefix: null,
|
|
|
|
/**
|
|
* Property: readers
|
|
* Contains public functions, grouped by namespace prefix, that will
|
|
* be applied when a namespaced node is found matching the function
|
|
* name. The function will be applied in the scope of this parser
|
|
* with two arguments: the node being read and a context object passed
|
|
* from the parent.
|
|
*/
|
|
readers: {},
|
|
|
|
/**
|
|
* Property: writers
|
|
* As a compliment to the <readers> property, this structure contains public
|
|
* writing functions grouped by namespace alias and named like the
|
|
* node names they produce.
|
|
*/
|
|
writers: {},
|
|
|
|
/**
|
|
* Property: xmldom
|
|
* {XMLDom} If this browser uses ActiveX, this will be set to a XMLDOM
|
|
* object. It is not intended to be a browser sniffing property.
|
|
* Instead, the xmldom property is used instead of <code>document<end>
|
|
* where namespaced node creation methods are not supported. In all
|
|
* other browsers, this remains null.
|
|
*/
|
|
xmldom: null,
|
|
|
|
/**
|
|
* Constructor: OpenLayers.Format.XML
|
|
* Construct an XML parser. The parser is used to read and write XML.
|
|
* Reading XML from a string returns a DOM element. Writing XML from
|
|
* a DOM element returns a string.
|
|
*
|
|
* Parameters:
|
|
* options - {Object} Optional object whose properties will be set on
|
|
* the object.
|
|
*/
|
|
initialize: function(options) {
|
|
if(window.ActiveXObject) {
|
|
this.xmldom = new ActiveXObject("Microsoft.XMLDOM");
|
|
}
|
|
OpenLayers.Format.prototype.initialize.apply(this, [options]);
|
|
// clone the namespace object and set all namespace aliases
|
|
this.namespaces = OpenLayers.Util.extend({}, this.namespaces);
|
|
this.namespaceAlias = {};
|
|
for(var alias in this.namespaces) {
|
|
this.namespaceAlias[this.namespaces[alias]] = alias;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* APIMethod: destroy
|
|
* Clean up.
|
|
*/
|
|
destroy: function() {
|
|
this.xmldom = null;
|
|
OpenLayers.Format.prototype.destroy.apply(this, arguments);
|
|
},
|
|
|
|
/**
|
|
* Method: setNamespace
|
|
* Set a namespace alias and URI for the format.
|
|
*
|
|
* Parameters:
|
|
* alias - {String} The namespace alias (prefix).
|
|
* uri - {String} The namespace URI.
|
|
*/
|
|
setNamespace: function(alias, uri) {
|
|
this.namespaces[alias] = uri;
|
|
this.namespaceAlias[uri] = alias;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: read
|
|
* Deserialize a XML string and return a DOM node.
|
|
*
|
|
* Parameters:
|
|
* text - {String} A XML string
|
|
|
|
* Returns:
|
|
* {DOMElement} A DOM node
|
|
*/
|
|
read: function(text) {
|
|
var index = text.indexOf('<');
|
|
if(index > 0) {
|
|
text = text.substring(index);
|
|
}
|
|
var node = OpenLayers.Util.Try(
|
|
OpenLayers.Function.bind((
|
|
function() {
|
|
var xmldom;
|
|
/**
|
|
* Since we want to be able to call this method on the prototype
|
|
* itself, this.xmldom may not exist even if in IE.
|
|
*/
|
|
if(window.ActiveXObject && !this.xmldom) {
|
|
xmldom = new ActiveXObject("Microsoft.XMLDOM");
|
|
} else {
|
|
xmldom = this.xmldom;
|
|
|
|
}
|
|
xmldom.loadXML(text);
|
|
return xmldom;
|
|
}
|
|
), this),
|
|
function() {
|
|
return new DOMParser().parseFromString(text, 'text/xml');
|
|
},
|
|
function() {
|
|
var req = new XMLHttpRequest();
|
|
req.open("GET", "data:" + "text/xml" +
|
|
";charset=utf-8," + encodeURIComponent(text), false);
|
|
if(req.overrideMimeType) {
|
|
req.overrideMimeType("text/xml");
|
|
}
|
|
req.send(null);
|
|
return req.responseXML;
|
|
}
|
|
);
|
|
|
|
if(this.keepData) {
|
|
this.data = node;
|
|
}
|
|
|
|
return node;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: write
|
|
* Serialize a DOM node into a XML string.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} A DOM node.
|
|
*
|
|
* Returns:
|
|
* {String} The XML string representation of the input node.
|
|
*/
|
|
write: function(node) {
|
|
var data;
|
|
if(this.xmldom) {
|
|
data = node.xml;
|
|
} else {
|
|
var serializer = new XMLSerializer();
|
|
if (node.nodeType == 1) {
|
|
// Add nodes to a document before serializing. Everything else
|
|
// is serialized as is. This may need more work. See #1218 .
|
|
var doc = document.implementation.createDocument("", "", null);
|
|
if (doc.importNode) {
|
|
node = doc.importNode(node, true);
|
|
}
|
|
doc.appendChild(node);
|
|
data = serializer.serializeToString(doc);
|
|
} else {
|
|
data = serializer.serializeToString(node);
|
|
}
|
|
}
|
|
return data;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: createElementNS
|
|
* Create a new element with namespace. This node can be appended to
|
|
* another node with the standard node.appendChild method. For
|
|
* cross-browser support, this method must be used instead of
|
|
* document.createElementNS.
|
|
*
|
|
* Parameters:
|
|
* uri - {String} Namespace URI for the element.
|
|
* name - {String} The qualified name of the element (prefix:localname).
|
|
*
|
|
* Returns:
|
|
* {Element} A DOM element with namespace.
|
|
*/
|
|
createElementNS: function(uri, name) {
|
|
var element;
|
|
if(this.xmldom) {
|
|
if(typeof uri == "string") {
|
|
element = this.xmldom.createNode(1, name, uri);
|
|
} else {
|
|
element = this.xmldom.createNode(1, name, "");
|
|
}
|
|
} else {
|
|
element = document.createElementNS(uri, name);
|
|
}
|
|
return element;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: createTextNode
|
|
* Create a text node. This node can be appended to another node with
|
|
* the standard node.appendChild method. For cross-browser support,
|
|
* this method must be used instead of document.createTextNode.
|
|
*
|
|
* Parameters:
|
|
* text - {String} The text of the node.
|
|
*
|
|
* Returns:
|
|
* {DOMElement} A DOM text node.
|
|
*/
|
|
createTextNode: function(text) {
|
|
var node;
|
|
if(this.xmldom) {
|
|
node = this.xmldom.createTextNode(text);
|
|
} else {
|
|
node = document.createTextNode(text);
|
|
}
|
|
return node;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: getElementsByTagNameNS
|
|
* Get a list of elements on a node given the namespace URI and local name.
|
|
* To return all nodes in a given namespace, use '*' for the name
|
|
* argument. To return all nodes of a given (local) name, regardless
|
|
* of namespace, use '*' for the uri argument.
|
|
*
|
|
* Parameters:
|
|
* node - {Element} Node on which to search for other nodes.
|
|
* uri - {String} Namespace URI.
|
|
* name - {String} Local name of the tag (without the prefix).
|
|
*
|
|
* Returns:
|
|
* {NodeList} A node list or array of elements.
|
|
*/
|
|
getElementsByTagNameNS: function(node, uri, name) {
|
|
var elements = [];
|
|
if(node.getElementsByTagNameNS) {
|
|
elements = node.getElementsByTagNameNS(uri, name);
|
|
} else {
|
|
// brute force method
|
|
var allNodes = node.getElementsByTagName("*");
|
|
var potentialNode, fullName;
|
|
for(var i=0, len=allNodes.length; i<len; ++i) {
|
|
potentialNode = allNodes[i];
|
|
fullName = (potentialNode.prefix) ?
|
|
(potentialNode.prefix + ":" + name) : name;
|
|
if((name == "*") || (fullName == potentialNode.nodeName)) {
|
|
if((uri == "*") || (uri == potentialNode.namespaceURI)) {
|
|
elements.push(potentialNode);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return elements;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: getAttributeNodeNS
|
|
* Get an attribute node given the namespace URI and local name.
|
|
*
|
|
* Parameters:
|
|
* node - {Element} Node on which to search for attribute nodes.
|
|
* uri - {String} Namespace URI.
|
|
* name - {String} Local name of the attribute (without the prefix).
|
|
*
|
|
* Returns:
|
|
* {DOMElement} An attribute node or null if none found.
|
|
*/
|
|
getAttributeNodeNS: function(node, uri, name) {
|
|
var attributeNode = null;
|
|
if(node.getAttributeNodeNS) {
|
|
attributeNode = node.getAttributeNodeNS(uri, name);
|
|
} else {
|
|
var attributes = node.attributes;
|
|
var potentialNode, fullName;
|
|
for(var i=0, len=attributes.length; i<len; ++i) {
|
|
potentialNode = attributes[i];
|
|
if(potentialNode.namespaceURI == uri) {
|
|
fullName = (potentialNode.prefix) ?
|
|
(potentialNode.prefix + ":" + name) : name;
|
|
if(fullName == potentialNode.nodeName) {
|
|
attributeNode = potentialNode;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return attributeNode;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: getAttributeNS
|
|
* Get an attribute value given the namespace URI and local name.
|
|
*
|
|
* Parameters:
|
|
* node - {Element} Node on which to search for an attribute.
|
|
* uri - {String} Namespace URI.
|
|
* name - {String} Local name of the attribute (without the prefix).
|
|
*
|
|
* Returns:
|
|
* {String} An attribute value or and empty string if none found.
|
|
*/
|
|
getAttributeNS: function(node, uri, name) {
|
|
var attributeValue = "";
|
|
if(node.getAttributeNS) {
|
|
attributeValue = node.getAttributeNS(uri, name) || "";
|
|
} else {
|
|
var attributeNode = this.getAttributeNodeNS(node, uri, name);
|
|
if(attributeNode) {
|
|
attributeValue = attributeNode.nodeValue;
|
|
}
|
|
}
|
|
return attributeValue;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: getChildValue
|
|
* Get the textual value of the node if it exists, or return an
|
|
* optional default string. Returns an empty string if no first child
|
|
* exists and no default value is supplied.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} The element used to look for a first child value.
|
|
* def - {String} Optional string to return in the event that no
|
|
* first child value exists.
|
|
*
|
|
* Returns:
|
|
* {String} The value of the first child of the given node.
|
|
*/
|
|
getChildValue: function(node, def) {
|
|
var value = def || "";
|
|
if(node) {
|
|
for(var child=node.firstChild; child; child=child.nextSibling) {
|
|
switch(child.nodeType) {
|
|
case 3: // text node
|
|
case 4: // cdata section
|
|
value += child.nodeValue;
|
|
}
|
|
}
|
|
}
|
|
return value;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: concatChildValues
|
|
* *Deprecated*. Use <getChildValue> instead.
|
|
*
|
|
* Concatenate the value of all child nodes if any exist, or return an
|
|
* optional default string. Returns an empty string if no children
|
|
* exist and no default value is supplied. Not optimized for large
|
|
* numbers of child nodes.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} The element used to look for child values.
|
|
* def - {String} Optional string to return in the event that no
|
|
* child exist.
|
|
*
|
|
* Returns:
|
|
* {String} The concatenated value of all child nodes of the given node.
|
|
*/
|
|
concatChildValues: function(node, def) {
|
|
var value = "";
|
|
var child = node.firstChild;
|
|
var childValue;
|
|
while(child) {
|
|
childValue = child.nodeValue;
|
|
if(childValue) {
|
|
value += childValue;
|
|
}
|
|
child = child.nextSibling;
|
|
}
|
|
if(value == "" && def != undefined) {
|
|
value = def;
|
|
}
|
|
return value;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: isSimpleContent
|
|
* Test if the given node has only simple content (i.e. no child element
|
|
* nodes).
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} An element node.
|
|
*
|
|
* Returns:
|
|
* {Boolean} The node has no child element nodes (nodes of type 1).
|
|
*/
|
|
isSimpleContent: function(node) {
|
|
var simple = true;
|
|
for(var child=node.firstChild; child; child=child.nextSibling) {
|
|
if(child.nodeType === 1) {
|
|
simple = false;
|
|
break;
|
|
}
|
|
}
|
|
return simple;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: contentType
|
|
* Determine the content type for a given node.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement}
|
|
*
|
|
* Returns:
|
|
* {Integer} One of OpenLayers.Format.XML.CONTENT_TYPE.{EMPTY,SIMPLE,COMPLEX,MIXED}
|
|
* if the node has no, simple, complex, or mixed content.
|
|
*/
|
|
contentType: function(node) {
|
|
var simple = false,
|
|
complex = false;
|
|
|
|
var type = OpenLayers.Format.XML.CONTENT_TYPE.EMPTY;
|
|
|
|
for(var child=node.firstChild; child; child=child.nextSibling) {
|
|
switch(child.nodeType) {
|
|
case 1: // element
|
|
complex = true;
|
|
break;
|
|
case 8: // comment
|
|
break;
|
|
default:
|
|
simple = true;
|
|
}
|
|
if(complex && simple) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(complex && simple) {
|
|
type = OpenLayers.Format.XML.CONTENT_TYPE.MIXED;
|
|
} else if(complex) {
|
|
return OpenLayers.Format.XML.CONTENT_TYPE.COMPLEX;
|
|
} else if(simple) {
|
|
return OpenLayers.Format.XML.CONTENT_TYPE.SIMPLE;
|
|
}
|
|
return type;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: hasAttributeNS
|
|
* Determine whether a node has a particular attribute matching the given
|
|
* name and namespace.
|
|
*
|
|
* Parameters:
|
|
* node - {Element} Node on which to search for an attribute.
|
|
* uri - {String} Namespace URI.
|
|
* name - {String} Local name of the attribute (without the prefix).
|
|
*
|
|
* Returns:
|
|
* {Boolean} The node has an attribute matching the name and namespace.
|
|
*/
|
|
hasAttributeNS: function(node, uri, name) {
|
|
var found = false;
|
|
if(node.hasAttributeNS) {
|
|
found = node.hasAttributeNS(uri, name);
|
|
} else {
|
|
found = !!this.getAttributeNodeNS(node, uri, name);
|
|
}
|
|
return found;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: setAttributeNS
|
|
* Adds a new attribute or changes the value of an attribute with the given
|
|
* namespace and name.
|
|
*
|
|
* Parameters:
|
|
* node - {Element} Element node on which to set the attribute.
|
|
* uri - {String} Namespace URI for the attribute.
|
|
* name - {String} Qualified name (prefix:localname) for the attribute.
|
|
* value - {String} Attribute value.
|
|
*/
|
|
setAttributeNS: function(node, uri, name, value) {
|
|
if(node.setAttributeNS) {
|
|
node.setAttributeNS(uri, name, value);
|
|
} else {
|
|
if(this.xmldom) {
|
|
if(uri) {
|
|
var attribute = node.ownerDocument.createNode(
|
|
2, name, uri
|
|
);
|
|
attribute.nodeValue = value;
|
|
node.setAttributeNode(attribute);
|
|
} else {
|
|
node.setAttribute(name, value);
|
|
}
|
|
} else {
|
|
throw "setAttributeNS not implemented";
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Method: createElementNSPlus
|
|
* Shorthand for creating namespaced elements with optional attributes and
|
|
* child text nodes.
|
|
*
|
|
* Parameters:
|
|
* name - {String} The qualified node name.
|
|
* options - {Object} Optional object for node configuration.
|
|
*
|
|
* Valid options:
|
|
* uri - {String} Optional namespace uri for the element - supply a prefix
|
|
* instead if the namespace uri is a property of the format's namespace
|
|
* object.
|
|
* attributes - {Object} Optional attributes to be set using the
|
|
* <setAttributes> method.
|
|
* value - {String} Optional text to be appended as a text node.
|
|
*
|
|
* Returns:
|
|
* {Element} An element node.
|
|
*/
|
|
createElementNSPlus: function(name, options) {
|
|
options = options || {};
|
|
// order of prefix preference
|
|
// 1. in the uri option
|
|
// 2. in the prefix option
|
|
// 3. in the qualified name
|
|
// 4. from the defaultPrefix
|
|
var uri = options.uri || this.namespaces[options.prefix];
|
|
if(!uri) {
|
|
var loc = name.indexOf(":");
|
|
uri = this.namespaces[name.substring(0, loc)];
|
|
}
|
|
if(!uri) {
|
|
uri = this.namespaces[this.defaultPrefix];
|
|
}
|
|
var node = this.createElementNS(uri, name);
|
|
if(options.attributes) {
|
|
this.setAttributes(node, options.attributes);
|
|
}
|
|
var value = options.value;
|
|
if(value != null) {
|
|
if(typeof value == "boolean") {
|
|
value = String(value);
|
|
}
|
|
node.appendChild(this.createTextNode(value));
|
|
}
|
|
return node;
|
|
},
|
|
|
|
/**
|
|
* Method: setAttributes
|
|
* Set multiple attributes given key value pairs from an object.
|
|
*
|
|
* Parameters:
|
|
* node - {Element} An element node.
|
|
* obj - {Object || Array} An object whose properties represent attribute
|
|
* names and values represent attribute values. If an attribute name
|
|
* is a qualified name ("prefix:local"), the prefix will be looked up
|
|
* in the parsers {namespaces} object. If the prefix is found,
|
|
* setAttributeNS will be used instead of setAttribute.
|
|
*/
|
|
setAttributes: function(node, obj) {
|
|
var value, uri;
|
|
for(var name in obj) {
|
|
if(obj[name] != null && obj[name].toString) {
|
|
value = obj[name].toString();
|
|
// check for qualified attribute name ("prefix:local")
|
|
uri = this.namespaces[name.substring(0, name.indexOf(":"))] || null;
|
|
this.setAttributeNS(node, uri, name, value);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Method: readNode
|
|
* Shorthand for applying one of the named readers given the node
|
|
* namespace and local name. Readers take two args (node, obj) and
|
|
* generally extend or modify the second.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} The node to be read (required).
|
|
* obj - {Object} The object to be modified (optional).
|
|
*
|
|
* Returns:
|
|
* {Object} The input object, modified (or a new one if none was provided).
|
|
*/
|
|
readNode: function(node, obj) {
|
|
if(!obj) {
|
|
obj = {};
|
|
}
|
|
var group = this.readers[this.namespaceAlias[node.namespaceURI]];
|
|
if(group) {
|
|
var local = node.localName || node.nodeName.split(":").pop();
|
|
var reader = group[local] || group["*"];
|
|
if(reader) {
|
|
reader.apply(this, [node, obj]);
|
|
}
|
|
}
|
|
return obj;
|
|
},
|
|
|
|
/**
|
|
* Method: readChildNodes
|
|
* Shorthand for applying the named readers to all children of a node.
|
|
* For each child of type 1 (element), <readSelf> is called.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} The node to be read (required).
|
|
* obj - {Object} The object to be modified (optional).
|
|
*
|
|
* Returns:
|
|
* {Object} The input object, modified.
|
|
*/
|
|
readChildNodes: function(node, obj) {
|
|
if(!obj) {
|
|
obj = {};
|
|
}
|
|
var children = node.childNodes;
|
|
var child;
|
|
for(var i=0, len=children.length; i<len; ++i) {
|
|
child = children[i];
|
|
if(child.nodeType == 1) {
|
|
this.readNode(child, obj);
|
|
}
|
|
}
|
|
return obj;
|
|
},
|
|
|
|
/**
|
|
* Method: writeNode
|
|
* Shorthand for applying one of the named writers and appending the
|
|
* results to a node. If a qualified name is not provided for the
|
|
* second argument (and a local name is used instead), the namespace
|
|
* of the parent node will be assumed.
|
|
*
|
|
* Parameters:
|
|
* name - {String} The name of a node to generate. If a qualified name
|
|
* (e.g. "pre:Name") is used, the namespace prefix is assumed to be
|
|
* in the <writers> group. If a local name is used (e.g. "Name") then
|
|
* the namespace of the parent is assumed. If a local name is used
|
|
* and no parent is supplied, then the default namespace is assumed.
|
|
* obj - {Object} Structure containing data for the writer.
|
|
* parent - {DOMElement} Result will be appended to this node. If no parent
|
|
* is supplied, the node will not be appended to anything.
|
|
*
|
|
* Returns:
|
|
* {DOMElement} The child node.
|
|
*/
|
|
writeNode: function(name, obj, parent) {
|
|
var prefix, local;
|
|
var split = name.indexOf(":");
|
|
if(split > 0) {
|
|
prefix = name.substring(0, split);
|
|
local = name.substring(split + 1);
|
|
} else {
|
|
if(parent) {
|
|
prefix = this.namespaceAlias[parent.namespaceURI];
|
|
} else {
|
|
prefix = this.defaultPrefix;
|
|
}
|
|
local = name;
|
|
}
|
|
var child = this.writers[prefix][local].apply(this, [obj]);
|
|
if(parent) {
|
|
parent.appendChild(child);
|
|
}
|
|
return child;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: getChildEl
|
|
* Get the first child element. Optionally only return the first child
|
|
* if it matches the given name and namespace URI.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} The parent node.
|
|
* name - {String} Optional node name (local) to search for.
|
|
* uri - {String} Optional namespace URI to search for.
|
|
*
|
|
* Returns:
|
|
* {DOMElement} The first child. Returns null if no element is found, if
|
|
* something significant besides an element is found, or if the element
|
|
* found does not match the optional name and uri.
|
|
*/
|
|
getChildEl: function(node, name, uri) {
|
|
return node && this.getThisOrNextEl(node.firstChild, name, uri);
|
|
},
|
|
|
|
/**
|
|
* APIMethod: getNextEl
|
|
* Get the next sibling element. Optionally get the first sibling only
|
|
* if it matches the given local name and namespace URI.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} The node.
|
|
* name - {String} Optional local name of the sibling to search for.
|
|
* uri - {String} Optional namespace URI of the sibling to search for.
|
|
*
|
|
* Returns:
|
|
* {DOMElement} The next sibling element. Returns null if no element is
|
|
* found, something significant besides an element is found, or the
|
|
* found element does not match the optional name and uri.
|
|
*/
|
|
getNextEl: function(node, name, uri) {
|
|
return node && this.getThisOrNextEl(node.nextSibling, name, uri);
|
|
},
|
|
|
|
/**
|
|
* Method: getThisOrNextEl
|
|
* Return this node or the next element node. Optionally get the first
|
|
* sibling with the given local name or namespace URI.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} The node.
|
|
* name - {String} Optional local name of the sibling to search for.
|
|
* uri - {String} Optional namespace URI of the sibling to search for.
|
|
*
|
|
* Returns:
|
|
* {DOMElement} The next sibling element. Returns null if no element is
|
|
* found, something significant besides an element is found, or the
|
|
* found element does not match the query.
|
|
*/
|
|
getThisOrNextEl: function(node, name, uri) {
|
|
outer: for(var sibling=node; sibling; sibling=sibling.nextSibling) {
|
|
switch(sibling.nodeType) {
|
|
case 1: // Element
|
|
if((!name || name === (sibling.localName || sibling.nodeName.split(":").pop())) &&
|
|
(!uri || uri === sibling.namespaceURI)) {
|
|
// matches
|
|
break outer;
|
|
}
|
|
sibling = null;
|
|
break outer;
|
|
case 3: // Text
|
|
if(/^\s*$/.test(sibling.nodeValue)) {
|
|
break;
|
|
}
|
|
case 4: // CDATA
|
|
case 6: // ENTITY_NODE
|
|
case 12: // NOTATION_NODE
|
|
case 10: // DOCUMENT_TYPE_NODE
|
|
case 11: // DOCUMENT_FRAGMENT_NODE
|
|
sibling = null;
|
|
break outer;
|
|
} // ignore comments and processing instructions
|
|
}
|
|
return sibling || null;
|
|
},
|
|
|
|
/**
|
|
* APIMethod: lookupNamespaceURI
|
|
* Takes a prefix and returns the namespace URI associated with it on the given
|
|
* node if found (and null if not). Supplying null for the prefix will
|
|
* return the default namespace.
|
|
*
|
|
* For browsers that support it, this calls the native lookupNamesapceURI
|
|
* function. In other browsers, this is an implementation of
|
|
* http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI.
|
|
*
|
|
* For browsers that don't support the attribute.ownerElement property, this
|
|
* method cannot be called on attribute nodes.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} The node from which to start looking.
|
|
* prefix - {String} The prefix to lookup or null to lookup the default namespace.
|
|
*
|
|
* Returns:
|
|
* {String} The namespace URI for the given prefix. Returns null if the prefix
|
|
* cannot be found or the node is the wrong type.
|
|
*/
|
|
lookupNamespaceURI: function(node, prefix) {
|
|
var uri = null;
|
|
if(node) {
|
|
if(node.lookupNamespaceURI) {
|
|
uri = node.lookupNamespaceURI(prefix);
|
|
} else {
|
|
outer: switch(node.nodeType) {
|
|
case 1: // ELEMENT_NODE
|
|
if(node.namespaceURI !== null && node.prefix === prefix) {
|
|
uri = node.namespaceURI;
|
|
break outer;
|
|
}
|
|
var len = node.attributes.length;
|
|
if(len) {
|
|
var attr;
|
|
for(var i=0; i<len; ++i) {
|
|
attr = node.attributes[i];
|
|
if(attr.prefix === "xmlns" && attr.name === "xmlns:" + prefix) {
|
|
uri = attr.value || null;
|
|
break outer;
|
|
} else if(attr.name === "xmlns" && prefix === null) {
|
|
uri = attr.value || null;
|
|
break outer;
|
|
}
|
|
}
|
|
}
|
|
uri = this.lookupNamespaceURI(node.parentNode, prefix);
|
|
break outer;
|
|
case 2: // ATTRIBUTE_NODE
|
|
uri = this.lookupNamespaceURI(node.ownerElement, prefix);
|
|
break outer;
|
|
case 9: // DOCUMENT_NODE
|
|
uri = this.lookupNamespaceURI(node.documentElement, prefix);
|
|
break outer;
|
|
case 6: // ENTITY_NODE
|
|
case 12: // NOTATION_NODE
|
|
case 10: // DOCUMENT_TYPE_NODE
|
|
case 11: // DOCUMENT_FRAGMENT_NODE
|
|
break outer;
|
|
default:
|
|
// TEXT_NODE (3), CDATA_SECTION_NODE (4), ENTITY_REFERENCE_NODE (5),
|
|
// PROCESSING_INSTRUCTION_NODE (7), COMMENT_NODE (8)
|
|
uri = this.lookupNamespaceURI(node.parentNode, prefix);
|
|
break outer;
|
|
}
|
|
}
|
|
}
|
|
return uri;
|
|
},
|
|
|
|
CLASS_NAME: "OpenLayers.Format.XML"
|
|
|
|
});
|
|
|
|
OpenLayers.Format.XML.CONTENT_TYPE = {EMPTY: 0, SIMPLE: 1, COMPLEX: 2, MIXED: 3};
|
|
|
|
/**
|
|
* APIFunction: OpenLayers.Format.XML.lookupNamespaceURI
|
|
* Takes a prefix and returns the namespace URI associated with it on the given
|
|
* node if found (and null if not). Supplying null for the prefix will
|
|
* return the default namespace.
|
|
*
|
|
* For browsers that support it, this calls the native lookupNamesapceURI
|
|
* function. In other browsers, this is an implementation of
|
|
* http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI.
|
|
*
|
|
* For browsers that don't support the attribute.ownerElement property, this
|
|
* method cannot be called on attribute nodes.
|
|
*
|
|
* Parameters:
|
|
* node - {DOMElement} The node from which to start looking.
|
|
* prefix - {String} The prefix to lookup or null to lookup the default namespace.
|
|
*
|
|
* Returns:
|
|
* {String} The namespace URI for the given prefix. Returns null if the prefix
|
|
* cannot be found or the node is the wrong type.
|
|
*/
|
|
OpenLayers.Format.XML.lookupNamespaceURI = OpenLayers.Function.bind(
|
|
OpenLayers.Format.XML.prototype.lookupNamespaceURI,
|
|
OpenLayers.Format.XML.prototype
|
|
);
|