Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
if(!dojo._hasResource["dojox.xml.DomParser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2
dojo._hasResource["dojox.xml.DomParser"] = true;
3
dojo.provide("dojox.xml.DomParser");
4
 
5
dojox.xml.DomParser=new (function(){
6
	/**********************************************************
7
	 *	The DomParser is a close-to (but not entirely)
8
	 *	conforming XML parser based on regular
9
	 *	expressions.  It will take any XML fragment
10
	 *	and return a lightweight JS structure that is
11
	 *	similar to (but not exactly) the DOM specification.
12
	 *
13
	 *	Getter and setter methods are NOT available; the goal
14
	 *	was to keep the resulting object model entirely JS-like.
15
	 *
16
	 *	All node types but document fragments are supported;
17
	 *	all nodes support getElementsByTagName and
18
	 *	getElementsByTagNameNS (with short names byName and
19
	 *	byNameNS).  The document node supports getElementById
20
	 *	(byId), and all nodes support a supplimental
21
	 *	childrenByName/childrenByNameNS method as well.
22
	 *
23
	 *	The object model is intended to be a READONLY format;
24
	 *	mutation events are NOT supported, and though you
25
	 *	can change properties on a node-by-node basis, certain
26
	 *	operations are not supported (such as changing the ID
27
	 *	of an element).
28
	 **********************************************************/
29
 
30
	//	internal use only.
31
	var nodeTypes={ ELEMENT:1, ATTRIBUTE:2, TEXT:3, CDATA_SECTION:4, PROCESSING_INSTRUCTION:7, COMMENT:8, DOCUMENT:9 };
32
 
33
	//	compile the regular expressions once.
34
	var reTags=/<([^>\/\s+]*)([^>]*)>([^<]*)/g;
35
	var reAttr=/([^=]*)="([^"]*)"/g;
36
	var reEntity=/<!ENTITY\s+([^"]*)\s+"([^"]*)">/g;
37
	var reCData=/<!\[CDATA\[([\u0001-\uFFFF]*?)\]\]>/g;
38
	var reComments=/<!--([\u0001-\uFFFF]*?)-->/g;
39
	var trim=/^\s+|\s+$/g;
40
	var normalize=/\s+/g;
41
	var egt=/\&gt;/g;
42
	var elt=/\&lt;/g;
43
	var equot=/\&quot;/g;
44
	var eapos=/\&apos;/g;
45
	var eamp=/\&amp;/g;
46
	var dNs="_def_";
47
 
48
	//	create a root node.
49
	function _doc(){
50
		return new (function(){
51
			var all={};
52
			this.nodeType=nodeTypes.DOCUMENT;
53
			this.nodeName="#document";
54
			this.namespaces={};
55
			this._nsPaths={};
56
			this.childNodes=[];
57
			this.documentElement=null;
58
 
59
			//	any element with an ID attribute will be added to the internal hashtable.
60
			this._add=function(obj){
61
				if(typeof(obj.id)!="undefined"){ all[obj.id]=obj; }
62
			};
63
			this._remove=function(id){
64
				if(all[id]){ delete all[id]; }
65
			};
66
 
67
			this.byId=this.getElementById=function(id){ return keys[id]; };
68
			this.byName=this.getElementsByTagName=byName;
69
			this.byNameNS=this.getElementsByTagNameNS=byNameNS;
70
			this.childrenByName=childrenByName;
71
		})();
72
	}
73
 
74
	//	functions attached to element nodes
75
	function byName(name){
76
		//	return all descendants with name.  Fully qualified (i.e. svg:svg)
77
		function __(node, name, arr){
78
			dojo.forEach(node.childNodes, function(c){
79
				if(c.nodeType==nodeTypes.ELEMENT){
80
					if(name=="*"){ arr.push(c); }
81
					else if(c.nodeName==name){ arr.push(c); }
82
					__(c, name, arr);
83
				}
84
			});
85
		}
86
		var a=[];
87
		__(this, name, a);
88
		return a;
89
	}
90
	function byNameNS(name, ns){
91
		//	return all descendants with name by namespace.  If no namespace passed, the default is used.
92
		function __(node, name, ns, arr){
93
			dojo.forEach(node.childNodes, function(c){
94
				if(c.nodeType==nodeTypes.ELEMENT){
95
					if(name=="*"&&c.ownerDocument._nsPaths[ns]==c.namespace){ arr.push(c); }
96
					else if(c.localName==name&&c.ownerDocument._nsPaths[ns]==c.namespace){ arr.push(c); }
97
					__(c, name, ns, arr);
98
				}
99
			});
100
		}
101
		if(!ns){ ns=dNs; }
102
		var a=[];
103
		__(this, name, ns, a);
104
		return a;
105
	}
106
	//	Only child nodes with name.
107
	function childrenByName(name){
108
		var a=[];
109
		dojo.forEach(this.childNodes, function(c){
110
			if(c.nodeType==nodeTypes.ELEMENT){
111
				if(name=="*"){ a.push(c); }
112
				else if(c.nodeName==name){ a.push(c); }
113
			}
114
		});
115
		return a;
116
	}
117
 
118
	//	attribute functions
119
	function getAttr(name){
120
		for(var i=0; i<this.attributes.length; i++){
121
			if(this.attributes[i].nodeName==name){
122
				return this.attributes[i].nodeValue;
123
			}
124
		}
125
		return null;
126
	}
127
	function getAttrNS(name, ns){
128
		for(var i=0; i<this.attributes.length; i++){
129
			if(this.ownerDocument._nsPaths[ns]==this.attributes[i].namespace
130
				&&this.attributes[i].localName==name
131
			){
132
				return this.attributes[i].nodeValue;
133
			}
134
		}
135
		return null;
136
	}
137
	//	note that you can only swap IDs using setAttribute, NOT with setAttributeNS.
138
	function setAttr(name, val){
139
		var old=null;
140
		for(var i=0; i<this.attributes.length; i++){
141
			if(this.attributes[i].nodeName==name){
142
				old=this.attributes[i].nodeValue;
143
				this.attributes[i].nodeValue=val;
144
				break;
145
			}
146
		}
147
		if(name=="id"){
148
			if(old!=null){ this.ownerDocument._remove(old); }
149
			this.ownerDocument._add(this);
150
		}
151
	}
152
	function setAttrNS(name, val, ns){
153
		for(var i=0; i<this.attributes.length; i++){
154
			if(this.ownerDocument._nsPaths[ns]==this.attributes[i].namespace
155
				&&this.attributes[i].localName==name
156
			){
157
				this.attributes[i].nodeValue=val;
158
				return;
159
			}
160
		}
161
	}
162
 
163
	//	navigation
164
	function prev(){
165
		var p=this.parentNode;
166
		if(p){
167
			for(var i=0;i<p.childNodes.length;i++){
168
				if(p.childNodes[i]==this&&i>0){
169
					return p.childNodes[i-1];
170
				}
171
			}
172
		}
173
		return null;
174
	}
175
	function next(){
176
		var p=this.parentNode;
177
		if(p){
178
			for(var i=0;i<p.childNodes.length;i++){
179
				if(p.childNodes[i]==this&&(i+1)<p.childNodes.length){
180
					return p.childNodes[i+1];
181
				}
182
			}
183
		}
184
		return null;
185
	}
186
 
187
	//	the main method.
188
	this.parse=function(/* String */str){
189
		var root=_doc();
190
		if(str==null){ return root; }
191
		if(str.length==0){ return root; }
192
 
193
		//	preprocess custom entities
194
		if(str.indexOf("<!ENTITY")>0){
195
			var entity, eRe=[];
196
			if(reEntity.test(str)){
197
				reEntity.lastIndex=0;
198
				//	match entities
199
				while((entity=reEntity.exec(str))!=null){
200
					eRe.push({
201
						entity:"&"+entity[1].replace(trim,"")+";",
202
						expression:entity[2]
203
					});
204
				}
205
				//	replace instances in the document.
206
				for(var i=0; i<eRe.length; i++){
207
					str=str.replace(new RegExp(eRe[i].entity, "g"), eRe[i].expression);
208
				}
209
			}
210
		}
211
 
212
		//	pre-parse for CData, and tokenize.
213
		var cdSections=[], cdata;
214
		while((cdata=reCData.exec(str))!=null){ cdSections.push(cdata[1]); }
215
		for(var i=0; i<cdSections.length; i++){ str=str.replace(cdSections[i], i); }
216
 
217
		//	pre-parse for comments, and tokenize.
218
		var comments=[], comment;
219
		while((comment=reComments.exec(str))!=null){ comments.push(comment[1]); }
220
		for(i=0; i<comments.length; i++){ str=str.replace(comments[i], i); }
221
 
222
		//	parse the document
223
		var res, obj=root;
224
		while((res=reTags.exec(str))!=null){
225
			//	closing tags.
226
			if(res[2].charAt(0)=="/"){
227
				if(obj.parentNode){
228
					obj=obj.parentNode;
229
				}
230
				continue;
231
			}
232
 
233
			//	open tags.
234
			if(res[1].length>0){
235
				//	figure out the type of node.
236
				if(res[1].charAt(0)=="?"){
237
					//	processing instruction
238
					var name=res[1].substr(1);
239
					var target=res[2].substr(0,res[2].length-2);
240
					obj.childNodes.push({
241
						nodeType:nodeTypes.PROCESSING_INSTRUCTION,
242
						nodeName:name,
243
						nodeValue:target
244
					});
245
				}
246
				else if(res[1].charAt(0)=="!"){
247
					//	CDATA; skip over any declaration elements.
248
					if(res[1].indexOf("![CDATA[")==0){
249
						var val=parseInt(res[1].replace("![CDATA[","").replace("]]",""));
250
						obj.childNodes.push({
251
							nodeType:nodeTypes.CDATA_SECTION,
252
							nodeName:"#cdata-section",
253
							nodeValue:cdSections[val]
254
						});
255
					}
256
					//	Comments.
257
					else if(res[1].substr(0,3)=="!--"){
258
						var val=parseInt(res[1].replace("!--","").replace("--",""));
259
						obj.childNodes.push({
260
							nodeType:nodeTypes.COMMENT,
261
							nodeName:"#comment",
262
							nodeValue:comments[val]
263
						});
264
					}
265
				}
266
				else {
267
					//	Elements (with attribute and text)
268
					var name=res[1].replace(trim,"");
269
					var o={
270
						nodeType:nodeTypes.ELEMENT,
271
						nodeName:name,
272
						localName:name,
273
						namespace:dNs,
274
						ownerDocument:root,
275
						attributes:[],
276
						parentNode:null,
277
						childNodes:[]
278
					};
279
 
280
					//	check to see if it's namespaced.
281
					if(name.indexOf(":")>-1){
282
						var t=name.split(":");
283
						o.namespace=t[0];
284
						o.localName=t[1];
285
					}
286
 
287
					//	set the function references.
288
					o.byName=o.getElementsByTagName=byName;
289
					o.byNameNS=o.getElementsByTagNameNS=byNameNS;
290
					o.childrenByName=childrenByName;
291
					o.getAttribute=getAttr;
292
					o.getAttributeNS=getAttrNS;
293
					o.setAttribute=setAttr;
294
					o.setAttributeNS=setAttrNS;
295
					o.previous=o.previousSibling=prev;
296
					o.next=o.nextSibling=next;
297
 
298
					//	parse the attribute string.
299
					var attr;
300
					while((attr=reAttr.exec(res[2]))!=null){
301
						if(attr.length>0){
302
							var name=attr[1].replace(trim,"");
303
							var val=attr[2].replace(normalize," ")
304
								.replace(egt,">")
305
								.replace(elt,"<")
306
								.replace(eapos,"'")
307
								.replace(equot,'"')
308
								.replace(eamp,"&");
309
							if(name.indexOf("xmlns")==0){
310
								if(name.indexOf(":")>0){
311
									var ns=name.split(":");
312
									root.namespaces[ns[1]]=val;
313
									root._nsPaths[val]=ns[1];
314
								} else {
315
									root.namespaces[dNs]=val;
316
									root._nsPaths[val]=dNs;
317
								}
318
							} else {
319
								var ln=name;
320
								var ns=dNs;
321
								if(name.indexOf(":")>0){
322
									var t=name.split(":");
323
									ln=t[1];
324
									ns=t[0];
325
								}
326
								o.attributes.push({
327
									nodeType:nodeTypes.ATTRIBUTE,
328
									nodeName:name,
329
									localName:ln,
330
									namespace:ns,
331
									nodeValue:val
332
								});
333
 
334
								//	only add id as a property.
335
								if(ln=="id"){ o.id=val; }
336
							}
337
						}
338
					}
339
					root._add(o);
340
 
341
					var text=res[3].replace(trim,"");
342
					if(text.length>0)
343
						o.childNodes.push({
344
							nodeType:nodeTypes.TEXT,
345
							nodeName:"#text",
346
							nodeValue:text.replace(normalize," ").replace(egt,">").replace(elt,"<").replace(eapos,"'").replace(equot,'"').replace(eamp,"&")
347
						});
348
 
349
					if(obj){
350
						obj.childNodes.push(o);
351
						o.parentNode=obj;
352
						//	if it's not a self-closing node.
353
						if(res[2].charAt(res[2].length-1)!="/"){
354
							obj=o;
355
						}
356
					}
357
				}
358
			}
359
		}
360
 
361
		//	set the document element
362
		for(var i=0; i<root.childNodes.length; i++){
363
			var e=root.childNodes[i];
364
			if(e.nodeType==nodeTypes.ELEMENT){
365
				root.documentElement=e;
366
				break;
367
			}
368
		}
369
		return root;
370
	};
371
})();
372
 
373
}