Project

General

Profile

1
/**
2
 * ====================================================================
3
 * About
4
 * ====================================================================
5
 * Sarissa cross browser XML library - IE XPath Emulation 
6
 * @version 0.9.7.6
7
 * @author: Manos Batsis, mailto: mbatsis at users full stop sourceforge full stop net
8
 *
9
 * This script emulates Internet Explorer's selectNodes and selectSingleNode
10
 * for Mozilla. Associating namespace prefixes with URIs for your XPath queries
11
 * is easy with IE's setProperty. 
12
 * USers may also map a namespace prefix to a default (unprefixed) namespace in the
13
 * source document with Sarissa.setXpathNamespaces
14
 *
15
 *
16
 * ====================================================================
17
 * Licence
18
 * ====================================================================
19
 * Sarissa is free software distributed under the GNU GPL version 2 (see <a href="gpl.txt">gpl.txt</a>) or higher, 
20
 * GNU LGPL version 2.1 (see <a href="lgpl.txt">lgpl.txt</a>) or higher and Apache Software License 2.0 or higher 
21
 * (see <a href="asl.txt">asl.txt</a>). This means you can choose one of the three and use that if you like. If 
22
 * you make modifications under the ASL, i would appreciate it if you submitted those.
23
 * In case your copy of Sarissa does not include the license texts, you may find
24
 * them online in various formats at <a href="http://www.gnu.org">http://www.gnu.org</a> and 
25
 * <a href="http://www.apache.org">http://www.apache.org</a>.
26
 *
27
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
28
 * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
29
 * WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE 
30
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
31
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
33
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
34
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 */
36
if(_SARISSA_HAS_DOM_FEATURE && document.implementation.hasFeature("XPath", "3.0")){
37
    /**
38
    * <p>SarissaNodeList behaves as a NodeList but is only used as a result to <code>selectNodes</code>,
39
    * so it also has some properties IEs proprietery object features.</p>
40
    * @private
41
    * @constructor
42
    * @argument i the (initial) list size
43
    */
44
    function SarissaNodeList(i){
45
        this.length = i;
46
    };
47
    /** <p>Set an Array as the prototype object</p> */
48
    SarissaNodeList.prototype = new Array(0);
49
    /** <p>Inherit the Array constructor </p> */
50
    SarissaNodeList.prototype.constructor = Array;
51
    /**
52
    * <p>Returns the node at the specified index or null if the given index
53
    * is greater than the list size or less than zero </p>
54
    * <p><b>Note</b> that in ECMAScript you can also use the square-bracket
55
    * array notation instead of calling <code>item</code>
56
    * @argument i the index of the member to return
57
    * @returns the member corresponding to the given index
58
    */
59
    SarissaNodeList.prototype.item = function(i) {
60
        return (i < 0 || i >= this.length)?null:this[i];
61
    };
62
    /**
63
    * <p>Emulate IE's expr property
64
    * (Here the SarissaNodeList object is given as the result of selectNodes).</p>
65
    * @returns the XPath expression passed to selectNodes that resulted in
66
    *          this SarissaNodeList
67
    */
68
    SarissaNodeList.prototype.expr = "";
69
    /** dummy, used to accept IE's stuff without throwing errors */
70
    if(window.XMLDocument && (!XMLDocument.prototype.setProperty)){
71
        XMLDocument.prototype.setProperty  = function(x,y){};
72
    };
73
    /**
74
    * <p>Programmatically control namespace URI/prefix mappings for XPath
75
    * queries.</p>
76
    * <p>This method comes especially handy when used to apply XPath queries
77
    * on XML documents with a default namespace, as there is no other way
78
    * of mapping that to a prefix.</p>
79
    * <p>Using no namespace prefix in DOM Level 3 XPath queries, implies you
80
    * are looking for elements in the null namespace. If you need to look
81
    * for nodes in the default namespace, you need to map a prefix to it
82
    * first like:</p>
83
    * <pre>Sarissa.setXpathNamespaces(oDoc, &quot;xmlns:myprefix=&amp;aposhttp://mynsURI&amp;apos&quot;);</pre>
84
    * <p><b>Note 1 </b>: Use this method only if the source document features
85
    * a default namespace (without a prefix), otherwise just use IE's setProperty
86
    * (moz will rezolve non-default namespaces by itself). You will need to map that
87
    * namespace to a prefix for queries to work.</p>
88
    * <p><b>Note 2 </b>: This method calls IE's setProperty method to set the
89
    * appropriate namespace-prefix mappings, so you dont have to do that.</p>
90
    * @param oDoc The target XMLDocument to set the namespace mappings for.
91
    * @param sNsSet A whilespace-seperated list of namespace declarations as
92
    *            those would appear in an XML document. E.g.:
93
    *            <code>&quot;xmlns:xhtml=&apos;http://www.w3.org/1999/xhtml&apos;
94
    * xmlns:&apos;http://www.w3.org/1999/XSL/Transform&apos;&quot;</code>
95
    * @throws An error if the format of the given namespace declarations is bad.
96
    */
97
    Sarissa.setXpathNamespaces = function(oDoc, sNsSet) {
98
        //oDoc._sarissa_setXpathNamespaces(sNsSet);
99
        oDoc._sarissa_useCustomResolver = true;
100
        var namespaces = sNsSet.indexOf(" ")>-1?sNsSet.split(" "):new Array(sNsSet);
101
        oDoc._sarissa_xpathNamespaces = new Array(namespaces.length);
102
        for(var i=0;i < namespaces.length;i++){
103
            var ns = namespaces[i];
104
            var colonPos = ns.indexOf(":");
105
            var assignPos = ns.indexOf("=");
106
            if(colonPos > 0 && assignPos > colonPos+1){
107
                var prefix = ns.substring(colonPos+1, assignPos);
108
                var uri = ns.substring(assignPos+2, ns.length-1);
109
                oDoc._sarissa_xpathNamespaces[prefix] = uri;
110
            }else{
111
                throw "Bad format on namespace declaration(s) given";
112
            };
113
        };
114
    };
115
    /**
116
    * @private Flag to control whether a custom namespace resolver should
117
    *          be used, set to true by Sarissa.setXpathNamespaces
118
    */
119
    XMLDocument.prototype._sarissa_useCustomResolver = false;
120
    /** @private */
121
    XMLDocument.prototype._sarissa_xpathNamespaces = new Array();
122
    /**
123
    * <p>Extends the XMLDocument to emulate IE's selectNodes.</p>
124
    * @argument sExpr the XPath expression to use
125
    * @argument contextNode this is for internal use only by the same
126
    *           method when called on Elements
127
    * @returns the result of the XPath search as a SarissaNodeList
128
    * @throws An error if no namespace URI is found for the given prefix.
129
    */
130
    XMLDocument.prototype.selectNodes = function(sExpr, contextNode, returnSingle){
131
        var nsDoc = this;
132
        var nsresolver = this._sarissa_useCustomResolver
133
        ? function(prefix){
134
            var s = nsDoc._sarissa_xpathNamespaces[prefix];
135
            if(s)return s;
136
            else throw "No namespace URI found for prefix: '" + prefix+"'";
137
            }
138
        : this.createNSResolver(this.documentElement);
139
        var result = null;
140
        if(!returnSingle){
141
            var oResult = this.evaluate(sExpr,
142
                (contextNode?contextNode:this),
143
                nsresolver,
144
                XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
145
            var nodeList = new SarissaNodeList(oResult.snapshotLength);
146
            nodeList.expr = sExpr;
147
            for(var i=0;i<nodeList.length;i++)
148
                nodeList[i] = oResult.snapshotItem(i);
149
            result = nodeList;
150
        }
151
        else {
152
            result = oResult = this.evaluate(sExpr,
153
                (contextNode?contextNode:this),
154
                nsresolver,
155
                XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
156
        };
157
        return result;      
158
    };
159
    /**
160
    * <p>Extends the Element to emulate IE's selectNodes</p>
161
    * @argument sExpr the XPath expression to use
162
    * @returns the result of the XPath search as an (Sarissa)NodeList
163
    * @throws An
164
    *             error if invoked on an HTML Element as this is only be
165
    *             available to XML Elements.
166
    */
167
    Element.prototype.selectNodes = function(sExpr){
168
        var doc = this.ownerDocument;
169
        if(doc.selectNodes)
170
            return doc.selectNodes(sExpr, this);
171
        else
172
            throw "Method selectNodes is only supported by XML Elements";
173
    };
174
    /**
175
    * <p>Extends the XMLDocument to emulate IE's selectSingleNode.</p>
176
    * @argument sExpr the XPath expression to use
177
    * @argument contextNode this is for internal use only by the same
178
    *           method when called on Elements
179
    * @returns the result of the XPath search as an (Sarissa)NodeList
180
    */
181
    XMLDocument.prototype.selectSingleNode = function(sExpr, contextNode){
182
        var ctx = contextNode?contextNode:null;
183
        return this.selectNodes(sExpr, ctx, true);
184
    };
185
    /**
186
    * <p>Extends the Element to emulate IE's selectSingleNode.</p>
187
    * @argument sExpr the XPath expression to use
188
    * @returns the result of the XPath search as an (Sarissa)NodeList
189
    * @throws An error if invoked on an HTML Element as this is only be
190
    *             available to XML Elements.
191
    */
192
    Element.prototype.selectSingleNode = function(sExpr){
193
        var doc = this.ownerDocument;
194
        if(doc.selectSingleNode)
195
            return doc.selectSingleNode(sExpr, this);
196
        else
197
            throw "Method selectNodes is only supported by XML Elements";
198
    };
199
    Sarissa.IS_ENABLED_SELECT_NODES = true;
200
};
(6-6/7)