Project

General

Profile

Download (31.4 KB) Statistics
| Branch: | Tag: | Revision:
1
/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
2
 * full list of contributors). Published under the 2-clause BSD license.
3
 * See license.txt in the OpenLayers distribution or repository for the
4
 * full text of the license. */
5

    
6
/**
7
 * @requires OpenLayers/Format.js
8
 */
9

    
10
/**
11
 * Class: OpenLayers.Format.XML
12
 * Read and write XML.  For cross-browser XML generation, use methods on an
13
 *     instance of the XML format class instead of on <code>document<end>.
14
 *     The DOM creation and traversing methods exposed here all mimic the
15
 *     W3C XML DOM methods.  Create a new parser with the
16
 *     <OpenLayers.Format.XML> constructor.
17
 *
18
 * Inherits from:
19
 *  - <OpenLayers.Format>
20
 */
21
OpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, {
22
    
23
    /**
24
     * Property: namespaces
25
     * {Object} Mapping of namespace aliases to namespace URIs.  Properties
26
     *     of this object should not be set individually.  Read-only.  All
27
     *     XML subclasses should have their own namespaces object.  Use
28
     *     <setNamespace> to add or set a namespace alias after construction.
29
     */
30
    namespaces: null,
31
    
32
    /**
33
     * Property: namespaceAlias
34
     * {Object} Mapping of namespace URI to namespace alias.  This object
35
     *     is read-only.  Use <setNamespace> to add or set a namespace alias.
36
     */
37
    namespaceAlias: null,
38
    
39
    /**
40
     * Property: defaultPrefix
41
     * {String} The default namespace alias for creating element nodes.
42
     */
43
    defaultPrefix: null,
44
    
45
    /**
46
     * Property: readers
47
     * Contains public functions, grouped by namespace prefix, that will
48
     *     be applied when a namespaced node is found matching the function
49
     *     name.  The function will be applied in the scope of this parser
50
     *     with two arguments: the node being read and a context object passed
51
     *     from the parent.
52
     */
53
    readers: {},
54
    
55
    /**
56
     * Property: writers
57
     * As a compliment to the <readers> property, this structure contains public
58
     *     writing functions grouped by namespace alias and named like the
59
     *     node names they produce.
60
     */
61
    writers: {},
62

    
63
    /**
64
     * Property: xmldom
65
     * {XMLDom} If this browser uses ActiveX, this will be set to a XMLDOM
66
     *     object.  It is not intended to be a browser sniffing property.
67
     *     Instead, the xmldom property is used instead of <code>document<end>
68
     *     where namespaced node creation methods are not supported. In all
69
     *     other browsers, this remains null.
70
     */
71
    xmldom: null,
72

    
73
    /**
74
     * Constructor: OpenLayers.Format.XML
75
     * Construct an XML parser.  The parser is used to read and write XML.
76
     *     Reading XML from a string returns a DOM element.  Writing XML from
77
     *     a DOM element returns a string.
78
     *
79
     * Parameters:
80
     * options - {Object} Optional object whose properties will be set on
81
     *     the object.
82
     */
83
    initialize: function(options) {
84
        if(window.ActiveXObject) {
85
            this.xmldom = new ActiveXObject("Microsoft.XMLDOM");
86
        }
87
        OpenLayers.Format.prototype.initialize.apply(this, [options]);
88
        // clone the namespace object and set all namespace aliases
89
        this.namespaces = OpenLayers.Util.extend({}, this.namespaces);
90
        this.namespaceAlias = {};
91
        for(var alias in this.namespaces) {
92
            this.namespaceAlias[this.namespaces[alias]] = alias;
93
        }
94
    },
95
    
96
    /**
97
     * APIMethod: destroy
98
     * Clean up.
99
     */
100
    destroy: function() {
101
        this.xmldom = null;
102
        OpenLayers.Format.prototype.destroy.apply(this, arguments);
103
    },
104
    
105
    /**
106
     * Method: setNamespace
107
     * Set a namespace alias and URI for the format.
108
     *
109
     * Parameters:
110
     * alias - {String} The namespace alias (prefix).
111
     * uri - {String} The namespace URI.
112
     */
113
    setNamespace: function(alias, uri) {
114
        this.namespaces[alias] = uri;
115
        this.namespaceAlias[uri] = alias;
116
    },
117

    
118
    /**
119
     * APIMethod: read
120
     * Deserialize a XML string and return a DOM node.
121
     *
122
     * Parameters:
123
     * text - {String} A XML string
124
     
125
     * Returns:
126
     * {DOMElement} A DOM node
127
     */
128
    read: function(text) {
129
        var index = text.indexOf('<');
130
        if(index > 0) {
131
            text = text.substring(index);
132
        }
133
        var node = OpenLayers.Util.Try(
134
            OpenLayers.Function.bind((
135
                function() {
136
                    var xmldom;
137
                    /**
138
                     * Since we want to be able to call this method on the prototype
139
                     * itself, this.xmldom may not exist even if in IE.
140
                     */
141
                    if(window.ActiveXObject && !this.xmldom) {
142
                        xmldom = new ActiveXObject("Microsoft.XMLDOM");
143
                    } else {
144
                        xmldom = this.xmldom;
145
                        
146
                    }
147
                    xmldom.loadXML(text);
148
                    return xmldom;
149
                }
150
            ), this),
151
            function() {
152
                return new DOMParser().parseFromString(text, 'text/xml');
153
            },
154
            function() {
155
                var req = new XMLHttpRequest();
156
                req.open("GET", "data:" + "text/xml" +
157
                         ";charset=utf-8," + encodeURIComponent(text), false);
158
                if(req.overrideMimeType) {
159
                    req.overrideMimeType("text/xml");
160
                }
161
                req.send(null);
162
                return req.responseXML;
163
            }
164
        );
165

    
166
        if(this.keepData) {
167
            this.data = node;
168
        }
169

    
170
        return node;
171
    },
172

    
173
    /**
174
     * APIMethod: write
175
     * Serialize a DOM node into a XML string.
176
     * 
177
     * Parameters:
178
     * node - {DOMElement} A DOM node.
179
     *
180
     * Returns:
181
     * {String} The XML string representation of the input node.
182
     */
183
    write: function(node) {
184
        var data;
185
        if(this.xmldom) {
186
            data = node.xml;
187
        } else {
188
            var serializer = new XMLSerializer();
189
            if (node.nodeType == 1) {
190
                // Add nodes to a document before serializing. Everything else
191
                // is serialized as is. This may need more work. See #1218 .
192
                var doc = document.implementation.createDocument("", "", null);
193
                if (doc.importNode) {
194
                    node = doc.importNode(node, true);
195
                }
196
                doc.appendChild(node);
197
                data = serializer.serializeToString(doc);
198
            } else {
199
                data = serializer.serializeToString(node);
200
            }
201
        }
202
        return data;
203
    },
204

    
205
    /**
206
     * APIMethod: createElementNS
207
     * Create a new element with namespace.  This node can be appended to
208
     *     another node with the standard node.appendChild method.  For
209
     *     cross-browser support, this method must be used instead of
210
     *     document.createElementNS.
211
     *
212
     * Parameters:
213
     * uri - {String} Namespace URI for the element.
214
     * name - {String} The qualified name of the element (prefix:localname).
215
     * 
216
     * Returns:
217
     * {Element} A DOM element with namespace.
218
     */
219
    createElementNS: function(uri, name) {
220
        var element;
221
        if(this.xmldom) {
222
            if(typeof uri == "string") {
223
                element = this.xmldom.createNode(1, name, uri);
224
            } else {
225
                element = this.xmldom.createNode(1, name, "");
226
            }
227
        } else {
228
            element = document.createElementNS(uri, name);
229
        }
230
        return element;
231
    },
232

    
233
    /**
234
     * APIMethod: createDocumentFragment
235
     * Create a document fragment node that can be appended to another node
236
     *     created by createElementNS.  This will call 
237
     *     document.createDocumentFragment outside of IE.  In IE, the ActiveX
238
     *     object's createDocumentFragment method is used.
239
     *
240
     * Returns:
241
     * {Element} A document fragment.
242
     */
243
    createDocumentFragment: function() {
244
        var element;
245
        if (this.xmldom) {
246
            element = this.xmldom.createDocumentFragment();
247
        } else {
248
            element = document.createDocumentFragment();
249
        }
250
        return element;
251
    },
252

    
253
    /**
254
     * APIMethod: createTextNode
255
     * Create a text node.  This node can be appended to another node with
256
     *     the standard node.appendChild method.  For cross-browser support,
257
     *     this method must be used instead of document.createTextNode.
258
     * 
259
     * Parameters:
260
     * text - {String} The text of the node.
261
     * 
262
     * Returns: 
263
     * {DOMElement} A DOM text node.
264
     */
265
    createTextNode: function(text) {
266
        var node;
267
        if (typeof text !== "string") {
268
            text = String(text);
269
        }
270
        if(this.xmldom) {
271
            node = this.xmldom.createTextNode(text);
272
        } else {
273
            node = document.createTextNode(text);
274
        }
275
        return node;
276
    },
277

    
278
    /**
279
     * APIMethod: getElementsByTagNameNS
280
     * Get a list of elements on a node given the namespace URI and local name.
281
     *     To return all nodes in a given namespace, use '*' for the name
282
     *     argument.  To return all nodes of a given (local) name, regardless
283
     *     of namespace, use '*' for the uri argument.
284
     * 
285
     * Parameters:
286
     * node - {Element} Node on which to search for other nodes.
287
     * uri - {String} Namespace URI.
288
     * name - {String} Local name of the tag (without the prefix).
289
     * 
290
     * Returns:
291
     * {NodeList} A node list or array of elements.
292
     */
293
    getElementsByTagNameNS: function(node, uri, name) {
294
        var elements = [];
295
        if(node.getElementsByTagNameNS) {
296
            elements = node.getElementsByTagNameNS(uri, name);
297
        } else {
298
            // brute force method
299
            var allNodes = node.getElementsByTagName("*");
300
            var potentialNode, fullName;
301
            for(var i=0, len=allNodes.length; i<len; ++i) {
302
                potentialNode = allNodes[i];
303
                fullName = (potentialNode.prefix) ?
304
                           (potentialNode.prefix + ":" + name) : name;
305
                if((name == "*") || (fullName == potentialNode.nodeName)) {
306
                    if((uri == "*") || (uri == potentialNode.namespaceURI)) {
307
                        elements.push(potentialNode);
308
                    }
309
                }
310
            }
311
        }
312
        return elements;
313
    },
314

    
315
    /**
316
     * APIMethod: getAttributeNodeNS
317
     * Get an attribute node given the namespace URI and local name.
318
     * 
319
     * Parameters:
320
     * node - {Element} Node on which to search for attribute nodes.
321
     * uri - {String} Namespace URI.
322
     * name - {String} Local name of the attribute (without the prefix).
323
     * 
324
     * Returns:
325
     * {DOMElement} An attribute node or null if none found.
326
     */
327
    getAttributeNodeNS: function(node, uri, name) {
328
        var attributeNode = null;
329
        if(node.getAttributeNodeNS) {
330
            attributeNode = node.getAttributeNodeNS(uri, name);
331
        } else {
332
            var attributes = node.attributes;
333
            var potentialNode, fullName;
334
            for(var i=0, len=attributes.length; i<len; ++i) {
335
                potentialNode = attributes[i];
336
                if(potentialNode.namespaceURI == uri) {
337
                    fullName = (potentialNode.prefix) ?
338
                               (potentialNode.prefix + ":" + name) : name;
339
                    if(fullName == potentialNode.nodeName) {
340
                        attributeNode = potentialNode;
341
                        break;
342
                    }
343
                }
344
            }
345
        }
346
        return attributeNode;
347
    },
348

    
349
    /**
350
     * APIMethod: getAttributeNS
351
     * Get an attribute value given the namespace URI and local name.
352
     * 
353
     * Parameters:
354
     * node - {Element} Node on which to search for an attribute.
355
     * uri - {String} Namespace URI.
356
     * name - {String} Local name of the attribute (without the prefix).
357
     * 
358
     * Returns:
359
     * {String} An attribute value or and empty string if none found.
360
     */
361
    getAttributeNS: function(node, uri, name) {
362
        var attributeValue = "";
363
        if(node.getAttributeNS) {
364
            attributeValue = node.getAttributeNS(uri, name) || "";
365
        } else {
366
            var attributeNode = this.getAttributeNodeNS(node, uri, name);
367
            if(attributeNode) {
368
                attributeValue = attributeNode.nodeValue;
369
            }
370
        }
371
        return attributeValue;
372
    },
373
    
374
    /**
375
     * APIMethod: getChildValue
376
     * Get the textual value of the node if it exists, or return an
377
     *     optional default string.  Returns an empty string if no first child
378
     *     exists and no default value is supplied.
379
     *
380
     * Parameters:
381
     * node - {DOMElement} The element used to look for a first child value.
382
     * def - {String} Optional string to return in the event that no
383
     *     first child value exists.
384
     *
385
     * Returns:
386
     * {String} The value of the first child of the given node.
387
     */
388
    getChildValue: function(node, def) {
389
        var value = def || "";
390
        if(node) {
391
            for(var child=node.firstChild; child; child=child.nextSibling) {
392
                switch(child.nodeType) {
393
                    case 3: // text node
394
                    case 4: // cdata section
395
                        value += child.nodeValue;
396
                }
397
            }
398
        }
399
        return value;
400
    },
401

    
402
    /**
403
     * APIMethod: isSimpleContent
404
     * Test if the given node has only simple content (i.e. no child element
405
     *     nodes).
406
     *
407
     * Parameters:
408
     * node - {DOMElement} An element node.
409
     *
410
     * Returns:
411
     * {Boolean} The node has no child element nodes (nodes of type 1). 
412
     */
413
    isSimpleContent: function(node) {
414
        var simple = true;
415
        for(var child=node.firstChild; child; child=child.nextSibling) {
416
            if(child.nodeType === 1) {
417
                simple = false;
418
                break;
419
            }
420
        }
421
        return simple;
422
    },
423
    
424
    /**
425
     * APIMethod: contentType
426
     * Determine the content type for a given node.
427
     *
428
     * Parameters:
429
     * node - {DOMElement}
430
     *
431
     * Returns:
432
     * {Integer} One of OpenLayers.Format.XML.CONTENT_TYPE.{EMPTY,SIMPLE,COMPLEX,MIXED}
433
     *     if the node has no, simple, complex, or mixed content.
434
     */
435
    contentType: function(node) {
436
        var simple = false,
437
            complex = false;
438
            
439
        var type = OpenLayers.Format.XML.CONTENT_TYPE.EMPTY;
440

    
441
        for(var child=node.firstChild; child; child=child.nextSibling) {
442
            switch(child.nodeType) {
443
                case 1: // element
444
                    complex = true;
445
                    break;
446
                case 8: // comment
447
                    break;
448
                default:
449
                    simple = true;
450
            }
451
            if(complex && simple) {
452
                break;
453
            }
454
        }
455
        
456
        if(complex && simple) {
457
            type = OpenLayers.Format.XML.CONTENT_TYPE.MIXED;
458
        } else if(complex) {
459
            return OpenLayers.Format.XML.CONTENT_TYPE.COMPLEX;
460
        } else if(simple) {
461
            return OpenLayers.Format.XML.CONTENT_TYPE.SIMPLE;
462
        }
463
        return type;
464
    },
465

    
466
    /**
467
     * APIMethod: hasAttributeNS
468
     * Determine whether a node has a particular attribute matching the given
469
     *     name and namespace.
470
     * 
471
     * Parameters:
472
     * node - {Element} Node on which to search for an attribute.
473
     * uri - {String} Namespace URI.
474
     * name - {String} Local name of the attribute (without the prefix).
475
     * 
476
     * Returns:
477
     * {Boolean} The node has an attribute matching the name and namespace.
478
     */
479
    hasAttributeNS: function(node, uri, name) {
480
        var found = false;
481
        if(node.hasAttributeNS) {
482
            found = node.hasAttributeNS(uri, name);
483
        } else {
484
            found = !!this.getAttributeNodeNS(node, uri, name);
485
        }
486
        return found;
487
    },
488
    
489
    /**
490
     * APIMethod: setAttributeNS
491
     * Adds a new attribute or changes the value of an attribute with the given
492
     *     namespace and name.
493
     *
494
     * Parameters:
495
     * node - {Element} Element node on which to set the attribute.
496
     * uri - {String} Namespace URI for the attribute.
497
     * name - {String} Qualified name (prefix:localname) for the attribute.
498
     * value - {String} Attribute value.
499
     */
500
    setAttributeNS: function(node, uri, name, value) {
501
        if(node.setAttributeNS) {
502
            node.setAttributeNS(uri, name, value);
503
        } else {
504
            if(this.xmldom) {
505
                if(uri) {
506
                    var attribute = node.ownerDocument.createNode(
507
                        2, name, uri
508
                    );
509
                    attribute.nodeValue = value;
510
                    node.setAttributeNode(attribute);
511
                } else {
512
                    node.setAttribute(name, value);
513
                }
514
            } else {
515
                throw "setAttributeNS not implemented";
516
            }
517
        }
518
    },
519

    
520
    /**
521
     * Method: createElementNSPlus
522
     * Shorthand for creating namespaced elements with optional attributes and
523
     *     child text nodes.
524
     *
525
     * Parameters:
526
     * name - {String} The qualified node name.
527
     * options - {Object} Optional object for node configuration.
528
     *
529
     * Valid options:
530
     * uri - {String} Optional namespace uri for the element - supply a prefix
531
     *     instead if the namespace uri is a property of the format's namespace
532
     *     object.
533
     * attributes - {Object} Optional attributes to be set using the
534
     *     <setAttributes> method.
535
     * value - {String} Optional text to be appended as a text node.
536
     *
537
     * Returns:
538
     * {Element} An element node.
539
     */
540
    createElementNSPlus: function(name, options) {
541
        options = options || {};
542
        // order of prefix preference
543
        // 1. in the uri option
544
        // 2. in the prefix option
545
        // 3. in the qualified name
546
        // 4. from the defaultPrefix
547
        var uri = options.uri || this.namespaces[options.prefix];
548
        if(!uri) {
549
            var loc = name.indexOf(":");
550
            uri = this.namespaces[name.substring(0, loc)];
551
        }
552
        if(!uri) {
553
            uri = this.namespaces[this.defaultPrefix];
554
        }
555
        var node = this.createElementNS(uri, name);
556
        if(options.attributes) {
557
            this.setAttributes(node, options.attributes);
558
        }
559
        var value = options.value;
560
        if(value != null) {
561
            node.appendChild(this.createTextNode(value));
562
        }
563
        return node;
564
    },
565
    
566
    /**
567
     * Method: setAttributes
568
     * Set multiple attributes given key value pairs from an object.
569
     *
570
     * Parameters:
571
     * node - {Element} An element node.
572
     * obj - {Object || Array} An object whose properties represent attribute
573
     *     names and values represent attribute values.  If an attribute name
574
     *     is a qualified name ("prefix:local"), the prefix will be looked up
575
     *     in the parsers {namespaces} object.  If the prefix is found,
576
     *     setAttributeNS will be used instead of setAttribute.
577
     */
578
    setAttributes: function(node, obj) {
579
        var value, uri;
580
        for(var name in obj) {
581
            if(obj[name] != null && obj[name].toString) {
582
                value = obj[name].toString();
583
                // check for qualified attribute name ("prefix:local")
584
                uri = this.namespaces[name.substring(0, name.indexOf(":"))] || null;
585
                this.setAttributeNS(node, uri, name, value);
586
            }
587
        }
588
    },
589

    
590
    /**
591
     * Method: readNode
592
     * Shorthand for applying one of the named readers given the node
593
     *     namespace and local name.  Readers take two args (node, obj) and
594
     *     generally extend or modify the second.
595
     *
596
     * Parameters:
597
     * node - {DOMElement} The node to be read (required).
598
     * obj - {Object} The object to be modified (optional).
599
     *
600
     * Returns:
601
     * {Object} The input object, modified (or a new one if none was provided).
602
     */
603
    readNode: function(node, obj) {
604
        if(!obj) {
605
            obj = {};
606
        }
607
        var group = this.readers[node.namespaceURI ? this.namespaceAlias[node.namespaceURI]: this.defaultPrefix];
608
        if(group) {
609
            var local = node.localName || node.nodeName.split(":").pop();
610
            var reader = group[local] || group["*"];
611
            if(reader) {
612
                reader.apply(this, [node, obj]);
613
            }
614
        }
615
        return obj;
616
    },
617

    
618
    /**
619
     * Method: readChildNodes
620
     * Shorthand for applying the named readers to all children of a node.
621
     *     For each child of type 1 (element), <readSelf> is called.
622
     *
623
     * Parameters:
624
     * node - {DOMElement} The node to be read (required).
625
     * obj - {Object} The object to be modified (optional).
626
     *
627
     * Returns:
628
     * {Object} The input object, modified.
629
     */
630
    readChildNodes: function(node, obj) {
631
        if(!obj) {
632
            obj = {};
633
        }
634
        var children = node.childNodes;
635
        var child;
636
        for(var i=0, len=children.length; i<len; ++i) {
637
            child = children[i];
638
            if(child.nodeType == 1) {
639
                this.readNode(child, obj);
640
            }
641
        }
642
        return obj;
643
    },
644

    
645
    /**
646
     * Method: writeNode
647
     * Shorthand for applying one of the named writers and appending the
648
     *     results to a node.  If a qualified name is not provided for the
649
     *     second argument (and a local name is used instead), the namespace
650
     *     of the parent node will be assumed.
651
     *
652
     * Parameters:
653
     * name - {String} The name of a node to generate.  If a qualified name
654
     *     (e.g. "pre:Name") is used, the namespace prefix is assumed to be
655
     *     in the <writers> group.  If a local name is used (e.g. "Name") then
656
     *     the namespace of the parent is assumed.  If a local name is used
657
     *     and no parent is supplied, then the default namespace is assumed.
658
     * obj - {Object} Structure containing data for the writer.
659
     * parent - {DOMElement} Result will be appended to this node.  If no parent
660
     *     is supplied, the node will not be appended to anything.
661
     *
662
     * Returns:
663
     * {DOMElement} The child node.
664
     */
665
    writeNode: function(name, obj, parent) {
666
        var prefix, local;
667
        var split = name.indexOf(":");
668
        if(split > 0) {
669
            prefix = name.substring(0, split);
670
            local = name.substring(split + 1);
671
        } else {
672
            if(parent) {
673
                prefix = this.namespaceAlias[parent.namespaceURI];
674
            } else {
675
                prefix = this.defaultPrefix;
676
            }
677
            local = name;
678
        }
679
        var child = this.writers[prefix][local].apply(this, [obj]);
680
        if(parent) {
681
            parent.appendChild(child);
682
        }
683
        return child;
684
    },
685

    
686
    /**
687
     * APIMethod: getChildEl
688
     * Get the first child element.  Optionally only return the first child
689
     *     if it matches the given name and namespace URI.
690
     *
691
     * Parameters:
692
     * node - {DOMElement} The parent node.
693
     * name - {String} Optional node name (local) to search for.
694
     * uri - {String} Optional namespace URI to search for.
695
     *
696
     * Returns:
697
     * {DOMElement} The first child.  Returns null if no element is found, if
698
     *     something significant besides an element is found, or if the element
699
     *     found does not match the optional name and uri.
700
     */
701
    getChildEl: function(node, name, uri) {
702
        return node && this.getThisOrNextEl(node.firstChild, name, uri);
703
    },
704
    
705
    /**
706
     * APIMethod: getNextEl
707
     * Get the next sibling element.  Optionally get the first sibling only
708
     *     if it matches the given local name and namespace URI.
709
     *
710
     * Parameters:
711
     * node - {DOMElement} The node.
712
     * name - {String} Optional local name of the sibling to search for.
713
     * uri - {String} Optional namespace URI of the sibling to search for.
714
     *
715
     * Returns:
716
     * {DOMElement} The next sibling element.  Returns null if no element is
717
     *     found, something significant besides an element is found, or the
718
     *     found element does not match the optional name and uri.
719
     */
720
    getNextEl: function(node, name, uri) {
721
        return node && this.getThisOrNextEl(node.nextSibling, name, uri);
722
    },
723
    
724
    /**
725
     * Method: getThisOrNextEl
726
     * Return this node or the next element node.  Optionally get the first
727
     *     sibling with the given local name or namespace URI.
728
     *
729
     * Parameters:
730
     * node - {DOMElement} The node.
731
     * name - {String} Optional local name of the sibling to search for.
732
     * uri - {String} Optional namespace URI of the sibling to search for.
733
     *
734
     * Returns:
735
     * {DOMElement} The next sibling element.  Returns null if no element is
736
     *     found, something significant besides an element is found, or the
737
     *     found element does not match the query.
738
     */
739
    getThisOrNextEl: function(node, name, uri) {
740
        outer: for(var sibling=node; sibling; sibling=sibling.nextSibling) {
741
            switch(sibling.nodeType) {
742
                case 1: // Element
743
                    if((!name || name === (sibling.localName || sibling.nodeName.split(":").pop())) &&
744
                       (!uri || uri === sibling.namespaceURI)) {
745
                        // matches
746
                        break outer;
747
                    }
748
                    sibling = null;
749
                    break outer;
750
                case 3: // Text
751
                    if(/^\s*$/.test(sibling.nodeValue)) {
752
                        break;
753
                    }
754
                case 4: // CDATA
755
                case 6: // ENTITY_NODE
756
                case 12: // NOTATION_NODE
757
                case 10: // DOCUMENT_TYPE_NODE
758
                case 11: // DOCUMENT_FRAGMENT_NODE
759
                    sibling = null;
760
                    break outer;
761
            } // ignore comments and processing instructions
762
        }
763
        return sibling || null;
764
    },
765
    
766
    /**
767
     * APIMethod: lookupNamespaceURI
768
     * Takes a prefix and returns the namespace URI associated with it on the given
769
     *     node if found (and null if not). Supplying null for the prefix will
770
     *     return the default namespace.
771
     *
772
     * For browsers that support it, this calls the native lookupNamesapceURI
773
     *     function.  In other browsers, this is an implementation of
774
     *     http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI.
775
     *
776
     * For browsers that don't support the attribute.ownerElement property, this
777
     *     method cannot be called on attribute nodes.
778
     *     
779
     * Parameters:
780
     * node - {DOMElement} The node from which to start looking.
781
     * prefix - {String} The prefix to lookup or null to lookup the default namespace.
782
     * 
783
     * Returns:
784
     * {String} The namespace URI for the given prefix.  Returns null if the prefix
785
     *     cannot be found or the node is the wrong type.
786
     */
787
    lookupNamespaceURI: function(node, prefix) {
788
        var uri = null;
789
        if(node) {
790
            if(node.lookupNamespaceURI) {
791
                uri = node.lookupNamespaceURI(prefix);
792
            } else {
793
                outer: switch(node.nodeType) {
794
                    case 1: // ELEMENT_NODE
795
                        if(node.namespaceURI !== null && node.prefix === prefix) {
796
                            uri = node.namespaceURI;
797
                            break outer;
798
                        }
799
                        var len = node.attributes.length;
800
                        if(len) {
801
                            var attr;
802
                            for(var i=0; i<len; ++i) {
803
                                attr = node.attributes[i];
804
                                if(attr.prefix === "xmlns" && attr.name === "xmlns:" + prefix) {
805
                                    uri = attr.value || null;
806
                                    break outer;
807
                                } else if(attr.name === "xmlns" && prefix === null) {
808
                                    uri = attr.value || null;
809
                                    break outer;
810
                                }
811
                            }
812
                        }
813
                        uri = this.lookupNamespaceURI(node.parentNode, prefix);
814
                        break outer;
815
                    case 2: // ATTRIBUTE_NODE
816
                        uri = this.lookupNamespaceURI(node.ownerElement, prefix);
817
                        break outer;
818
                    case 9: // DOCUMENT_NODE
819
                        uri = this.lookupNamespaceURI(node.documentElement, prefix);
820
                        break outer;
821
                    case 6: // ENTITY_NODE
822
                    case 12: // NOTATION_NODE
823
                    case 10: // DOCUMENT_TYPE_NODE
824
                    case 11: // DOCUMENT_FRAGMENT_NODE
825
                        break outer;
826
                    default: 
827
                        // TEXT_NODE (3), CDATA_SECTION_NODE (4), ENTITY_REFERENCE_NODE (5),
828
                        // PROCESSING_INSTRUCTION_NODE (7), COMMENT_NODE (8)
829
                        uri =  this.lookupNamespaceURI(node.parentNode, prefix);
830
                        break outer;
831
                }
832
            }
833
        }
834
        return uri;
835
    },
836
    
837
    /**
838
     * Method: getXMLDoc
839
     * Get an XML document for nodes that are not supported in HTML (e.g.
840
     * createCDATASection). On IE, this will either return an existing or
841
     * create a new <xmldom> on the instance. On other browsers, this will
842
     * either return an existing or create a new shared document (see
843
     * <OpenLayers.Format.XML.document>).
844
     *
845
     * Returns:
846
     * {XMLDocument}
847
     */
848
    getXMLDoc: function() {
849
        if (!OpenLayers.Format.XML.document && !this.xmldom) {
850
            if (document.implementation && document.implementation.createDocument) {
851
                OpenLayers.Format.XML.document =
852
                    document.implementation.createDocument("", "", null);
853
            } else if (!this.xmldom && window.ActiveXObject) {
854
                this.xmldom = new ActiveXObject("Microsoft.XMLDOM");
855
            }
856
        }
857
        return OpenLayers.Format.XML.document || this.xmldom;
858
    },
859

    
860
    CLASS_NAME: "OpenLayers.Format.XML" 
861

    
862
});     
863

    
864
OpenLayers.Format.XML.CONTENT_TYPE = {EMPTY: 0, SIMPLE: 1, COMPLEX: 2, MIXED: 3};
865

    
866
/**
867
 * APIFunction: OpenLayers.Format.XML.lookupNamespaceURI
868
 * Takes a prefix and returns the namespace URI associated with it on the given
869
 *     node if found (and null if not). Supplying null for the prefix will
870
 *     return the default namespace.
871
 *
872
 * For browsers that support it, this calls the native lookupNamesapceURI
873
 *     function.  In other browsers, this is an implementation of
874
 *     http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI.
875
 *
876
 * For browsers that don't support the attribute.ownerElement property, this
877
 *     method cannot be called on attribute nodes.
878
 *     
879
 * Parameters:
880
 * node - {DOMElement} The node from which to start looking.
881
 * prefix - {String} The prefix to lookup or null to lookup the default namespace.
882
 * 
883
 * Returns:
884
 * {String} The namespace URI for the given prefix.  Returns null if the prefix
885
 *     cannot be found or the node is the wrong type.
886
 */
887
OpenLayers.Format.XML.lookupNamespaceURI = OpenLayers.Function.bind(
888
    OpenLayers.Format.XML.prototype.lookupNamespaceURI,
889
    OpenLayers.Format.XML.prototype
890
);
891

    
892
/**
893
 * Property: OpenLayers.Format.XML.document
894
 * {XMLDocument} XML document to reuse for creating non-HTML compliant nodes,
895
 * like document.createCDATASection.
896
 */
897
OpenLayers.Format.XML.document = null;
(41-41/41)