├── .gitignore
├── .npmignore
├── .project
├── .travis.yml
├── LICENSE
├── __package__.js
├── changelog
├── component.json
├── dom-parser.js
├── dom.js
├── entities.js
├── package.json
├── readme.md
├── sax.js
├── t
├── cover
├── dom
│ └── require.t.js
└── test
└── test
├── 3rd-cases
├── index.js
├── mock.js
└── o3xml.js
├── dom
├── attr.js
├── clone.js
├── element.js
├── fragment.js
├── index.js
├── level3.js
├── ns-test.js
└── serializer.js
├── error
├── error.js
├── index.js
└── xml-error.js
├── html
└── normalize.js
├── index.js
├── parse
├── big-file-performance.js
├── file-test.js
├── file-test1.result.xml
├── file-test1.xml
├── index.js
├── locator.js
├── namespace.js
├── node.js
├── parse-element.js
├── simple.js
├── test-define.js
├── test-doc-witespace.js
└── unclosedcomment.js
├── test.js
└── xss-test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /.proof.out
3 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | test
2 | t
3 | travis.yml
4 | .project
5 | changelog
6 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | xmldom
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - '0.10'
5 |
6 | branches:
7 | only:
8 | - master
9 | - proof
10 | - travis-ci
11 |
12 | # Not using `npm install --dev` because it is recursive. It will pull in the all
13 | # development dependencies for CoffeeScript. Way too much spew in the Travis CI
14 | # build output.
15 |
16 | before_install:
17 | - npm install
18 | - npm install istanbul coveralls
19 |
20 | env:
21 | global:
22 | - secure: "BxUHTsa1WVANLQoimilbZwa1MCWSdM9hOmPWBE/rsYb7uT/iiqkRXXwnWhKtN5CLvTvIQbiAzq4iyPID0S8UHrnxClYQrOuA6QkrtwgIEuDAmijao/bgxobPOremvkwXcpMGIwzYKyYQQtSEaEIQbqf6gSSKW9dBh/GZ/vfTsqo="
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | You can choose any one of those:
2 |
3 | The MIT License (MIT):
4 |
5 | link:http://opensource.org/licenses/MIT
6 |
7 | LGPL:
8 | http://www.gnu.org/licenses/lgpl.html
9 |
--------------------------------------------------------------------------------
/__package__.js:
--------------------------------------------------------------------------------
1 | this.addScript('dom.js',['DOMImplementation','XMLSerializer']);
2 | this.addScript('dom-parser.js',['DOMHandler','DOMParser'],
3 | ['DOMImplementation','XMLReader']);
4 | this.addScript('sax.js','XMLReader');
--------------------------------------------------------------------------------
/changelog:
--------------------------------------------------------------------------------
1 | ### Version 0.1.16
2 |
3 | Sat May 4 14:58:03 UTC 2013
4 |
5 | * Correctly handle multibyte Unicode greater than two byts. #57. #56.
6 | * Initial unit testing and test coverage. #53. #46. #19.
7 | * Create Bower `component.json` #52.
8 |
9 | ### Version 0.1.8
10 |
11 | * Add: some test case from node-o3-xml(excludes xpath support)
12 | * Fix: remove existed attribute before setting (bug introduced in v0.1.5)
13 | * Fix: index direct access for childNodes and any NodeList collection(not w3c standard)
14 | * Fix: remove last child bug
15 |
--------------------------------------------------------------------------------
/component.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "xmldom",
3 | "version": "0.1.15",
4 | "main": "dom-parser.js",
5 | "ignore": [
6 | "**/.*",
7 | "node_modules",
8 | "components"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/dom-parser.js:
--------------------------------------------------------------------------------
1 | function DOMParser(options){
2 | this.options = options ||{locator:{}};
3 |
4 | }
5 |
6 | DOMParser.prototype.parseFromString = function(source,mimeType){
7 | var options = this.options;
8 | var sax = new XMLReader();
9 | var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
10 | var errorHandler = options.errorHandler;
11 | var locator = options.locator;
12 | var defaultNSMap = options.xmlns||{};
13 | var isHTML = /\/x?html?$/.test(mimeType);//mimeType.toLowerCase().indexOf('html') > -1;
14 | var entityMap = isHTML?htmlEntity.entityMap:{'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"};
15 | if(locator){
16 | domBuilder.setDocumentLocator(locator)
17 | }
18 |
19 | sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
20 | sax.domBuilder = options.domBuilder || domBuilder;
21 | if(isHTML){
22 | defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
23 | }
24 | defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
25 | if(source){
26 | sax.parse(source,defaultNSMap,entityMap);
27 | }else{
28 | sax.errorHandler.error("invalid doc source");
29 | }
30 | return domBuilder.doc;
31 | }
32 | function buildErrorHandler(errorImpl,domBuilder,locator){
33 | if(!errorImpl){
34 | if(domBuilder instanceof DOMHandler){
35 | return domBuilder;
36 | }
37 | errorImpl = domBuilder ;
38 | }
39 | var errorHandler = {}
40 | var isCallback = errorImpl instanceof Function;
41 | locator = locator||{}
42 | function build(key){
43 | var fn = errorImpl[key];
44 | if(!fn && isCallback){
45 | fn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl;
46 | }
47 | errorHandler[key] = fn && function(msg){
48 | fn('[xmldom '+key+']\t'+msg+_locator(locator));
49 | }||function(){};
50 | }
51 | build('warning');
52 | build('error');
53 | build('fatalError');
54 | return errorHandler;
55 | }
56 |
57 | //console.log('#\n\n\n\n\n\n\n####')
58 | /**
59 | * +ContentHandler+ErrorHandler
60 | * +LexicalHandler+EntityResolver2
61 | * -DeclHandler-DTDHandler
62 | *
63 | * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
64 | * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
65 | * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
66 | */
67 | function DOMHandler() {
68 | this.cdata = false;
69 | }
70 | function position(locator,node){
71 | node.lineNumber = locator.lineNumber;
72 | node.columnNumber = locator.columnNumber;
73 | }
74 | /**
75 | * @see org.xml.sax.ContentHandler#startDocument
76 | * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
77 | */
78 | DOMHandler.prototype = {
79 | startDocument : function() {
80 | this.doc = new DOMImplementation().createDocument(null, null, null);
81 | if (this.locator) {
82 | this.doc.documentURI = this.locator.systemId;
83 | }
84 | },
85 | startElement:function(namespaceURI, localName, qName, attrs) {
86 | var doc = this.doc;
87 | var el = doc.createElementNS(namespaceURI, qName||localName);
88 | var len = attrs.length;
89 | appendElement(this, el);
90 | this.currentElement = el;
91 |
92 | this.locator && position(this.locator,el)
93 | for (var i = 0 ; i < len; i++) {
94 | var namespaceURI = attrs.getURI(i);
95 | var value = attrs.getValue(i);
96 | var qName = attrs.getQName(i);
97 | var attr = doc.createAttributeNS(namespaceURI, qName);
98 | this.locator &&position(attrs.getLocator(i),attr);
99 | attr.value = attr.nodeValue = value;
100 | el.setAttributeNode(attr)
101 | }
102 | },
103 | endElement:function(namespaceURI, localName, qName) {
104 | var current = this.currentElement
105 | var tagName = current.tagName;
106 | this.currentElement = current.parentNode;
107 | },
108 | startPrefixMapping:function(prefix, uri) {
109 | },
110 | endPrefixMapping:function(prefix) {
111 | },
112 | processingInstruction:function(target, data) {
113 | var ins = this.doc.createProcessingInstruction(target, data);
114 | this.locator && position(this.locator,ins)
115 | appendElement(this, ins);
116 | },
117 | ignorableWhitespace:function(ch, start, length) {
118 | },
119 | characters:function(chars, start, length) {
120 | chars = _toString.apply(this,arguments)
121 | //console.log(chars)
122 | if(chars){
123 | if (this.cdata) {
124 | var charNode = this.doc.createCDATASection(chars);
125 | } else {
126 | var charNode = this.doc.createTextNode(chars);
127 | }
128 | if(this.currentElement){
129 | this.currentElement.appendChild(charNode);
130 | }else if(/^\s*$/.test(chars)){
131 | this.doc.appendChild(charNode);
132 | //process xml
133 | }
134 | this.locator && position(this.locator,charNode)
135 | }
136 | },
137 | skippedEntity:function(name) {
138 | },
139 | endDocument:function() {
140 | this.doc.normalize();
141 | },
142 | setDocumentLocator:function (locator) {
143 | if(this.locator = locator){// && !('lineNumber' in locator)){
144 | locator.lineNumber = 0;
145 | }
146 | },
147 | //LexicalHandler
148 | comment:function(chars, start, length) {
149 | chars = _toString.apply(this,arguments)
150 | var comm = this.doc.createComment(chars);
151 | this.locator && position(this.locator,comm)
152 | appendElement(this, comm);
153 | },
154 |
155 | startCDATA:function() {
156 | //used in characters() methods
157 | this.cdata = true;
158 | },
159 | endCDATA:function() {
160 | this.cdata = false;
161 | },
162 |
163 | startDTD:function(name, publicId, systemId) {
164 | var impl = this.doc.implementation;
165 | if (impl && impl.createDocumentType) {
166 | var dt = impl.createDocumentType(name, publicId, systemId);
167 | this.locator && position(this.locator,dt)
168 | appendElement(this, dt);
169 | }
170 | },
171 | /**
172 | * @see org.xml.sax.ErrorHandler
173 | * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
174 | */
175 | warning:function(error) {
176 | console.warn('[xmldom warning]\t'+error,_locator(this.locator));
177 | },
178 | error:function(error) {
179 | console.error('[xmldom error]\t'+error,_locator(this.locator));
180 | },
181 | fatalError:function(error) {
182 | console.error('[xmldom fatalError]\t'+error,_locator(this.locator));
183 | throw error;
184 | }
185 | }
186 | function _locator(l){
187 | if(l){
188 | return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
189 | }
190 | }
191 | function _toString(chars,start,length){
192 | if(typeof chars == 'string'){
193 | return chars.substr(start,length)
194 | }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
195 | if(chars.length >= start+length || start){
196 | return new java.lang.String(chars,start,length)+'';
197 | }
198 | return chars;
199 | }
200 | }
201 |
202 | /*
203 | * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
204 | * used method of org.xml.sax.ext.LexicalHandler:
205 | * #comment(chars, start, length)
206 | * #startCDATA()
207 | * #endCDATA()
208 | * #startDTD(name, publicId, systemId)
209 | *
210 | *
211 | * IGNORED method of org.xml.sax.ext.LexicalHandler:
212 | * #endDTD()
213 | * #startEntity(name)
214 | * #endEntity(name)
215 | *
216 | *
217 | * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
218 | * IGNORED method of org.xml.sax.ext.DeclHandler
219 | * #attributeDecl(eName, aName, type, mode, value)
220 | * #elementDecl(name, model)
221 | * #externalEntityDecl(name, publicId, systemId)
222 | * #internalEntityDecl(name, value)
223 | * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
224 | * IGNORED method of org.xml.sax.EntityResolver2
225 | * #resolveEntity(String name,String publicId,String baseURI,String systemId)
226 | * #resolveEntity(publicId, systemId)
227 | * #getExternalSubset(name, baseURI)
228 | * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
229 | * IGNORED method of org.xml.sax.DTDHandler
230 | * #notationDecl(name, publicId, systemId) {};
231 | * #unparsedEntityDecl(name, publicId, systemId, notationName) {};
232 | */
233 | "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
234 | DOMHandler.prototype[key] = function(){return null}
235 | })
236 |
237 | /* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
238 | function appendElement (hander,node) {
239 | if (!hander.currentElement) {
240 | hander.doc.appendChild(node);
241 | } else {
242 | hander.currentElement.appendChild(node);
243 | }
244 | }//appendChild and setAttributeNS are preformance key
245 |
246 | //if(typeof require == 'function'){
247 | var htmlEntity = require('./entities');
248 | var XMLReader = require('./sax').XMLReader;
249 | var DOMImplementation = exports.DOMImplementation = require('./dom').DOMImplementation;
250 | exports.XMLSerializer = require('./dom').XMLSerializer ;
251 | exports.DOMParser = DOMParser;
252 | //}
253 |
--------------------------------------------------------------------------------
/dom.js:
--------------------------------------------------------------------------------
1 | /*
2 | * DOM Level 2
3 | * Object DOMException
4 | * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
5 | * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
6 | */
7 |
8 | function copy(src,dest){
9 | for(var p in src){
10 | dest[p] = src[p];
11 | }
12 | }
13 | /**
14 | ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
15 | ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
16 | */
17 | function _extends(Class,Super){
18 | var pt = Class.prototype;
19 | if(!(pt instanceof Super)){
20 | function t(){};
21 | t.prototype = Super.prototype;
22 | t = new t();
23 | copy(pt,t);
24 | Class.prototype = pt = t;
25 | }
26 | if(pt.constructor != Class){
27 | if(typeof Class != 'function'){
28 | console.error("unknow Class:"+Class)
29 | }
30 | pt.constructor = Class
31 | }
32 | }
33 | var htmlns = 'http://www.w3.org/1999/xhtml' ;
34 | // Node Types
35 | var NodeType = {}
36 | var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1;
37 | var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2;
38 | var TEXT_NODE = NodeType.TEXT_NODE = 3;
39 | var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4;
40 | var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5;
41 | var ENTITY_NODE = NodeType.ENTITY_NODE = 6;
42 | var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
43 | var COMMENT_NODE = NodeType.COMMENT_NODE = 8;
44 | var DOCUMENT_NODE = NodeType.DOCUMENT_NODE = 9;
45 | var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10;
46 | var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11;
47 | var NOTATION_NODE = NodeType.NOTATION_NODE = 12;
48 |
49 | // ExceptionCode
50 | var ExceptionCode = {}
51 | var ExceptionMessage = {};
52 | var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1]="Index size error"),1);
53 | var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2]="DOMString size error"),2);
54 | var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3]="Hierarchy request error"),3);
55 | var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4]="Wrong document"),4);
56 | var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5]="Invalid character"),5);
57 | var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6]="No data allowed"),6);
58 | var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
59 | var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8]="Not found"),8);
60 | var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9]="Not supported"),9);
61 | var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10]="Attribute in use"),10);
62 | //level2
63 | var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11]="Invalid state"),11);
64 | var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12]="Syntax error"),12);
65 | var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13]="Invalid modification"),13);
66 | var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14]="Invalid namespace"),14);
67 | var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15]="Invalid access"),15);
68 |
69 |
70 | function DOMException(code, message) {
71 | if(message instanceof Error){
72 | var error = message;
73 | }else{
74 | error = this;
75 | Error.call(this, ExceptionMessage[code]);
76 | this.message = ExceptionMessage[code];
77 | if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
78 | }
79 | error.code = code;
80 | if(message) this.message = this.message + ": " + message;
81 | return error;
82 | };
83 | DOMException.prototype = Error.prototype;
84 | copy(ExceptionCode,DOMException)
85 | /**
86 | * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
87 | * The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.
88 | * The items in the NodeList are accessible via an integral index, starting from 0.
89 | */
90 | function NodeList() {
91 | };
92 | NodeList.prototype = {
93 | /**
94 | * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
95 | * @standard level1
96 | */
97 | length:0,
98 | /**
99 | * Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
100 | * @standard level1
101 | * @param index unsigned long
102 | * Index into the collection.
103 | * @return Node
104 | * The node at the indexth position in the NodeList, or null if that is not a valid index.
105 | */
106 | item: function(index) {
107 | return this[index] || null;
108 | },
109 | toString:function(isHTML,nodeFilter){
110 | for(var buf = [], i = 0;i=0){
172 | var lastIndex = list.length-1
173 | while(i0 || key == 'xmlns'){
193 | // return null;
194 | // }
195 | //console.log()
196 | var i = this.length;
197 | while(i--){
198 | var attr = this[i];
199 | //console.log(attr.nodeName,key)
200 | if(attr.nodeName == key){
201 | return attr;
202 | }
203 | }
204 | },
205 | setNamedItem: function(attr) {
206 | var el = attr.ownerElement;
207 | if(el && el!=this._ownerElement){
208 | throw new DOMException(INUSE_ATTRIBUTE_ERR);
209 | }
210 | var oldAttr = this.getNamedItem(attr.nodeName);
211 | _addNamedNode(this._ownerElement,this,attr,oldAttr);
212 | return oldAttr;
213 | },
214 | /* returns Node */
215 | setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
216 | var el = attr.ownerElement, oldAttr;
217 | if(el && el!=this._ownerElement){
218 | throw new DOMException(INUSE_ATTRIBUTE_ERR);
219 | }
220 | oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
221 | _addNamedNode(this._ownerElement,this,attr,oldAttr);
222 | return oldAttr;
223 | },
224 |
225 | /* returns Node */
226 | removeNamedItem: function(key) {
227 | var attr = this.getNamedItem(key);
228 | _removeNamedNode(this._ownerElement,this,attr);
229 | return attr;
230 |
231 |
232 | },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
233 |
234 | //for level2
235 | removeNamedItemNS:function(namespaceURI,localName){
236 | var attr = this.getNamedItemNS(namespaceURI,localName);
237 | _removeNamedNode(this._ownerElement,this,attr);
238 | return attr;
239 | },
240 | getNamedItemNS: function(namespaceURI, localName) {
241 | var i = this.length;
242 | while(i--){
243 | var node = this[i];
244 | if(node.localName == localName && node.namespaceURI == namespaceURI){
245 | return node;
246 | }
247 | }
248 | return null;
249 | }
250 | };
251 | /**
252 | * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
253 | */
254 | function DOMImplementation(/* Object */ features) {
255 | this._features = {};
256 | if (features) {
257 | for (var feature in features) {
258 | this._features = features[feature];
259 | }
260 | }
261 | };
262 |
263 | DOMImplementation.prototype = {
264 | hasFeature: function(/* string */ feature, /* string */ version) {
265 | var versions = this._features[feature.toLowerCase()];
266 | if (versions && (!version || version in versions)) {
267 | return true;
268 | } else {
269 | return false;
270 | }
271 | },
272 | // Introduced in DOM Level 2:
273 | createDocument:function(namespaceURI, qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
274 | var doc = new Document();
275 | doc.implementation = this;
276 | doc.childNodes = new NodeList();
277 | doc.doctype = doctype;
278 | if(doctype){
279 | doc.appendChild(doctype);
280 | }
281 | if(qualifiedName){
282 | var root = doc.createElementNS(namespaceURI,qualifiedName);
283 | doc.appendChild(root);
284 | }
285 | return doc;
286 | },
287 | // Introduced in DOM Level 2:
288 | createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
289 | var node = new DocumentType();
290 | node.name = qualifiedName;
291 | node.nodeName = qualifiedName;
292 | node.publicId = publicId;
293 | node.systemId = systemId;
294 | // Introduced in DOM Level 2:
295 | //readonly attribute DOMString internalSubset;
296 |
297 | //TODO:..
298 | // readonly attribute NamedNodeMap entities;
299 | // readonly attribute NamedNodeMap notations;
300 | return node;
301 | }
302 | };
303 |
304 |
305 | /**
306 | * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
307 | */
308 |
309 | function Node() {
310 | };
311 |
312 | Node.prototype = {
313 | firstChild : null,
314 | lastChild : null,
315 | previousSibling : null,
316 | nextSibling : null,
317 | attributes : null,
318 | parentNode : null,
319 | childNodes : null,
320 | ownerDocument : null,
321 | nodeValue : null,
322 | namespaceURI : null,
323 | prefix : null,
324 | localName : null,
325 | // Modified in DOM Level 2:
326 | insertBefore:function(newChild, refChild){//raises
327 | return _insertBefore(this,newChild,refChild);
328 | },
329 | replaceChild:function(newChild, oldChild){//raises
330 | this.insertBefore(newChild,oldChild);
331 | if(oldChild){
332 | this.removeChild(oldChild);
333 | }
334 | },
335 | removeChild:function(oldChild){
336 | return _removeChild(this,oldChild);
337 | },
338 | appendChild:function(newChild){
339 | return this.insertBefore(newChild,null);
340 | },
341 | hasChildNodes:function(){
342 | return this.firstChild != null;
343 | },
344 | cloneNode:function(deep){
345 | return cloneNode(this.ownerDocument||this,this,deep);
346 | },
347 | // Modified in DOM Level 2:
348 | normalize:function(){
349 | var child = this.firstChild;
350 | while(child){
351 | var next = child.nextSibling;
352 | if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
353 | this.removeChild(next);
354 | child.appendData(next.data);
355 | }else{
356 | child.normalize();
357 | child = next;
358 | }
359 | }
360 | },
361 | // Introduced in DOM Level 2:
362 | isSupported:function(feature, version){
363 | return this.ownerDocument.implementation.hasFeature(feature,version);
364 | },
365 | // Introduced in DOM Level 2:
366 | hasAttributes:function(){
367 | return this.attributes.length>0;
368 | },
369 | lookupPrefix:function(namespaceURI){
370 | var el = this;
371 | while(el){
372 | var map = el._nsMap;
373 | //console.dir(map)
374 | if(map){
375 | for(var n in map){
376 | if(map[n] == namespaceURI){
377 | return n;
378 | }
379 | }
380 | }
381 | el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
382 | }
383 | return null;
384 | },
385 | // Introduced in DOM Level 3:
386 | lookupNamespaceURI:function(prefix){
387 | var el = this;
388 | while(el){
389 | var map = el._nsMap;
390 | //console.dir(map)
391 | if(map){
392 | if(prefix in map){
393 | return map[prefix] ;
394 | }
395 | }
396 | el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
397 | }
398 | return null;
399 | },
400 | // Introduced in DOM Level 3:
401 | isDefaultNamespace:function(namespaceURI){
402 | var prefix = this.lookupPrefix(namespaceURI);
403 | return prefix == null;
404 | }
405 | };
406 |
407 |
408 | function _xmlEncoder(c){
409 | return c == '<' && '<' ||
410 | c == '>' && '>' ||
411 | c == '&' && '&' ||
412 | c == '"' && '"' ||
413 | ''+c.charCodeAt()+';'
414 | }
415 |
416 |
417 | copy(NodeType,Node);
418 | copy(NodeType,Node.prototype);
419 |
420 | /**
421 | * @param callback return true for continue,false for break
422 | * @return boolean true: break visit;
423 | */
424 | function _visitNode(node,callback){
425 | if(callback(node)){
426 | return true;
427 | }
428 | if(node = node.firstChild){
429 | do{
430 | if(_visitNode(node,callback)){return true}
431 | }while(node=node.nextSibling)
432 | }
433 | }
434 |
435 |
436 |
437 | function Document(){
438 | }
439 | function _onAddAttribute(doc,el,newAttr){
440 | doc && doc._inc++;
441 | var ns = newAttr.namespaceURI ;
442 | if(ns == 'http://www.w3.org/2000/xmlns/'){
443 | //update namespace
444 | el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value
445 | }
446 | }
447 | function _onRemoveAttribute(doc,el,newAttr,remove){
448 | doc && doc._inc++;
449 | var ns = newAttr.namespaceURI ;
450 | if(ns == 'http://www.w3.org/2000/xmlns/'){
451 | //update namespace
452 | delete el._nsMap[newAttr.prefix?newAttr.localName:'']
453 | }
454 | }
455 | function _onUpdateChild(doc,el,newChild){
456 | if(doc && doc._inc){
457 | doc._inc++;
458 | //update childNodes
459 | var cs = el.childNodes;
460 | if(newChild){
461 | cs[cs.length++] = newChild;
462 | }else{
463 | //console.log(1)
464 | var child = el.firstChild;
465 | var i = 0;
466 | while(child){
467 | cs[i++] = child;
468 | child =child.nextSibling;
469 | }
470 | cs.length = i;
471 | }
472 | }
473 | }
474 |
475 | /**
476 | * attributes;
477 | * children;
478 | *
479 | * writeable properties:
480 | * nodeValue,Attr:value,CharacterData:data
481 | * prefix
482 | */
483 | function _removeChild(parentNode,child){
484 | var previous = child.previousSibling;
485 | var next = child.nextSibling;
486 | if(previous){
487 | previous.nextSibling = next;
488 | }else{
489 | parentNode.firstChild = next
490 | }
491 | if(next){
492 | next.previousSibling = previous;
493 | }else{
494 | parentNode.lastChild = previous;
495 | }
496 | _onUpdateChild(parentNode.ownerDocument,parentNode);
497 | return child;
498 | }
499 | /**
500 | * preformance key(refChild == null)
501 | */
502 | function _insertBefore(parentNode,newChild,nextChild){
503 | var cp = newChild.parentNode;
504 | if(cp){
505 | cp.removeChild(newChild);//remove and update
506 | }
507 | if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
508 | var newFirst = newChild.firstChild;
509 | if (newFirst == null) {
510 | return newChild;
511 | }
512 | var newLast = newChild.lastChild;
513 | }else{
514 | newFirst = newLast = newChild;
515 | }
516 | var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
517 |
518 | newFirst.previousSibling = pre;
519 | newLast.nextSibling = nextChild;
520 |
521 |
522 | if(pre){
523 | pre.nextSibling = newFirst;
524 | }else{
525 | parentNode.firstChild = newFirst;
526 | }
527 | if(nextChild == null){
528 | parentNode.lastChild = newLast;
529 | }else{
530 | nextChild.previousSibling = newLast;
531 | }
532 | do{
533 | newFirst.parentNode = parentNode;
534 | }while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
535 | _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
536 | //console.log(parentNode.lastChild.nextSibling == null)
537 | if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
538 | newChild.firstChild = newChild.lastChild = null;
539 | }
540 | return newChild;
541 | }
542 | function _appendSingleChild(parentNode,newChild){
543 | var cp = newChild.parentNode;
544 | if(cp){
545 | var pre = parentNode.lastChild;
546 | cp.removeChild(newChild);//remove and update
547 | var pre = parentNode.lastChild;
548 | }
549 | var pre = parentNode.lastChild;
550 | newChild.parentNode = parentNode;
551 | newChild.previousSibling = pre;
552 | newChild.nextSibling = null;
553 | if(pre){
554 | pre.nextSibling = newChild;
555 | }else{
556 | parentNode.firstChild = newChild;
557 | }
558 | parentNode.lastChild = newChild;
559 | _onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
560 | return newChild;
561 | //console.log("__aa",parentNode.lastChild.nextSibling == null)
562 | }
563 | Document.prototype = {
564 | //implementation : null,
565 | nodeName : '#document',
566 | nodeType : DOCUMENT_NODE,
567 | doctype : null,
568 | documentElement : null,
569 | _inc : 1,
570 |
571 | insertBefore : function(newChild, refChild){//raises
572 | if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
573 | var child = newChild.firstChild;
574 | while(child){
575 | var next = child.nextSibling;
576 | this.insertBefore(child,refChild);
577 | child = next;
578 | }
579 | return newChild;
580 | }
581 | if(this.documentElement == null && newChild.nodeType == ELEMENT_NODE){
582 | this.documentElement = newChild;
583 | }
584 |
585 | return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
586 | },
587 | removeChild : function(oldChild){
588 | if(this.documentElement == oldChild){
589 | this.documentElement = null;
590 | }
591 | return _removeChild(this,oldChild);
592 | },
593 | // Introduced in DOM Level 2:
594 | importNode : function(importedNode,deep){
595 | return importNode(this,importedNode,deep);
596 | },
597 | // Introduced in DOM Level 2:
598 | getElementById : function(id){
599 | var rtv = null;
600 | _visitNode(this.documentElement,function(node){
601 | if(node.nodeType == ELEMENT_NODE){
602 | if(node.getAttribute('id') == id){
603 | rtv = node;
604 | return true;
605 | }
606 | }
607 | })
608 | return rtv;
609 | },
610 |
611 | //document factory method:
612 | createElement : function(tagName){
613 | var node = new Element();
614 | node.ownerDocument = this;
615 | node.nodeName = tagName;
616 | node.tagName = tagName;
617 | node.childNodes = new NodeList();
618 | var attrs = node.attributes = new NamedNodeMap();
619 | attrs._ownerElement = node;
620 | return node;
621 | },
622 | createDocumentFragment : function(){
623 | var node = new DocumentFragment();
624 | node.ownerDocument = this;
625 | node.childNodes = new NodeList();
626 | return node;
627 | },
628 | createTextNode : function(data){
629 | var node = new Text();
630 | node.ownerDocument = this;
631 | node.appendData(data)
632 | return node;
633 | },
634 | createComment : function(data){
635 | var node = new Comment();
636 | node.ownerDocument = this;
637 | node.appendData(data)
638 | return node;
639 | },
640 | createCDATASection : function(data){
641 | var node = new CDATASection();
642 | node.ownerDocument = this;
643 | node.appendData(data)
644 | return node;
645 | },
646 | createProcessingInstruction : function(target,data){
647 | var node = new ProcessingInstruction();
648 | node.ownerDocument = this;
649 | node.tagName = node.target = target;
650 | node.nodeValue= node.data = data;
651 | return node;
652 | },
653 | createAttribute : function(name){
654 | var node = new Attr();
655 | node.ownerDocument = this;
656 | node.name = name;
657 | node.nodeName = name;
658 | node.localName = name;
659 | node.specified = true;
660 | return node;
661 | },
662 | createEntityReference : function(name){
663 | var node = new EntityReference();
664 | node.ownerDocument = this;
665 | node.nodeName = name;
666 | return node;
667 | },
668 | // Introduced in DOM Level 2:
669 | createElementNS : function(namespaceURI,qualifiedName){
670 | var node = new Element();
671 | var pl = qualifiedName.split(':');
672 | var attrs = node.attributes = new NamedNodeMap();
673 | node.childNodes = new NodeList();
674 | node.ownerDocument = this;
675 | node.nodeName = qualifiedName;
676 | node.tagName = qualifiedName;
677 | node.namespaceURI = namespaceURI;
678 | if(pl.length == 2){
679 | node.prefix = pl[0];
680 | node.localName = pl[1];
681 | }else{
682 | //el.prefix = null;
683 | node.localName = qualifiedName;
684 | }
685 | attrs._ownerElement = node;
686 | return node;
687 | },
688 | // Introduced in DOM Level 2:
689 | createAttributeNS : function(namespaceURI,qualifiedName){
690 | var node = new Attr();
691 | var pl = qualifiedName.split(':');
692 | node.ownerDocument = this;
693 | node.nodeName = qualifiedName;
694 | node.name = qualifiedName;
695 | node.namespaceURI = namespaceURI;
696 | node.specified = true;
697 | if(pl.length == 2){
698 | node.prefix = pl[0];
699 | node.localName = pl[1];
700 | }else{
701 | //el.prefix = null;
702 | node.localName = qualifiedName;
703 | }
704 | return node;
705 | }
706 | };
707 | _extends(Document,Node);
708 |
709 |
710 | function Element() {
711 | this._nsMap = {};
712 | };
713 | Element.prototype = {
714 | nodeType : ELEMENT_NODE,
715 | hasAttribute : function(name){
716 | return this.getAttributeNode(name)!=null;
717 | },
718 | getAttribute : function(name){
719 | var attr = this.getAttributeNode(name);
720 | return attr && attr.value || '';
721 | },
722 | getAttributeNode : function(name){
723 | return this.attributes.getNamedItem(name);
724 | },
725 | setAttribute : function(name, value){
726 | var attr = this.ownerDocument.createAttribute(name);
727 | attr.value = attr.nodeValue = "" + value;
728 | this.setAttributeNode(attr)
729 | },
730 | removeAttribute : function(name){
731 | var attr = this.getAttributeNode(name)
732 | attr && this.removeAttributeNode(attr);
733 | },
734 |
735 | //four real opeartion method
736 | appendChild:function(newChild){
737 | if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
738 | return this.insertBefore(newChild,null);
739 | }else{
740 | return _appendSingleChild(this,newChild);
741 | }
742 | },
743 | setAttributeNode : function(newAttr){
744 | return this.attributes.setNamedItem(newAttr);
745 | },
746 | setAttributeNodeNS : function(newAttr){
747 | return this.attributes.setNamedItemNS(newAttr);
748 | },
749 | removeAttributeNode : function(oldAttr){
750 | //console.log(this == oldAttr.ownerElement)
751 | return this.attributes.removeNamedItem(oldAttr.nodeName);
752 | },
753 | //get real attribute name,and remove it by removeAttributeNode
754 | removeAttributeNS : function(namespaceURI, localName){
755 | var old = this.getAttributeNodeNS(namespaceURI, localName);
756 | old && this.removeAttributeNode(old);
757 | },
758 |
759 | hasAttributeNS : function(namespaceURI, localName){
760 | return this.getAttributeNodeNS(namespaceURI, localName)!=null;
761 | },
762 | getAttributeNS : function(namespaceURI, localName){
763 | var attr = this.getAttributeNodeNS(namespaceURI, localName);
764 | return attr && attr.value || '';
765 | },
766 | setAttributeNS : function(namespaceURI, qualifiedName, value){
767 | var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
768 | attr.value = attr.nodeValue = "" + value;
769 | this.setAttributeNode(attr)
770 | },
771 | getAttributeNodeNS : function(namespaceURI, localName){
772 | return this.attributes.getNamedItemNS(namespaceURI, localName);
773 | },
774 |
775 | getElementsByTagName : function(tagName){
776 | return new LiveNodeList(this,function(base){
777 | var ls = [];
778 | _visitNode(base,function(node){
779 | if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
780 | ls.push(node);
781 | }
782 | });
783 | return ls;
784 | });
785 | },
786 | getElementsByTagNameNS : function(namespaceURI, localName){
787 | return new LiveNodeList(this,function(base){
788 | var ls = [];
789 | _visitNode(base,function(node){
790 | if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
791 | ls.push(node);
792 | }
793 | });
794 | return ls;
795 |
796 | });
797 | }
798 | };
799 | Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
800 | Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
801 |
802 |
803 | _extends(Element,Node);
804 | function Attr() {
805 | };
806 | Attr.prototype.nodeType = ATTRIBUTE_NODE;
807 | _extends(Attr,Node);
808 |
809 |
810 | function CharacterData() {
811 | };
812 | CharacterData.prototype = {
813 | data : '',
814 | substringData : function(offset, count) {
815 | return this.data.substring(offset, offset+count);
816 | },
817 | appendData: function(text) {
818 | text = this.data+text;
819 | this.nodeValue = this.data = text;
820 | this.length = text.length;
821 | },
822 | insertData: function(offset,text) {
823 | this.replaceData(offset,0,text);
824 |
825 | },
826 | appendChild:function(newChild){
827 | throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR])
828 | },
829 | deleteData: function(offset, count) {
830 | this.replaceData(offset,count,"");
831 | },
832 | replaceData: function(offset, count, text) {
833 | var start = this.data.substring(0,offset);
834 | var end = this.data.substring(offset+count);
835 | text = start + text + end;
836 | this.nodeValue = this.data = text;
837 | this.length = text.length;
838 | }
839 | }
840 | _extends(CharacterData,Node);
841 | function Text() {
842 | };
843 | Text.prototype = {
844 | nodeName : "#text",
845 | nodeType : TEXT_NODE,
846 | splitText : function(offset) {
847 | var text = this.data;
848 | var newText = text.substring(offset);
849 | text = text.substring(0, offset);
850 | this.data = this.nodeValue = text;
851 | this.length = text.length;
852 | var newNode = this.ownerDocument.createTextNode(newText);
853 | if(this.parentNode){
854 | this.parentNode.insertBefore(newNode, this.nextSibling);
855 | }
856 | return newNode;
857 | }
858 | }
859 | _extends(Text,CharacterData);
860 | function Comment() {
861 | };
862 | Comment.prototype = {
863 | nodeName : "#comment",
864 | nodeType : COMMENT_NODE
865 | }
866 | _extends(Comment,CharacterData);
867 |
868 | function CDATASection() {
869 | };
870 | CDATASection.prototype = {
871 | nodeName : "#cdata-section",
872 | nodeType : CDATA_SECTION_NODE
873 | }
874 | _extends(CDATASection,CharacterData);
875 |
876 |
877 | function DocumentType() {
878 | };
879 | DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
880 | _extends(DocumentType,Node);
881 |
882 | function Notation() {
883 | };
884 | Notation.prototype.nodeType = NOTATION_NODE;
885 | _extends(Notation,Node);
886 |
887 | function Entity() {
888 | };
889 | Entity.prototype.nodeType = ENTITY_NODE;
890 | _extends(Entity,Node);
891 |
892 | function EntityReference() {
893 | };
894 | EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
895 | _extends(EntityReference,Node);
896 |
897 | function DocumentFragment() {
898 | };
899 | DocumentFragment.prototype.nodeName = "#document-fragment";
900 | DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
901 | _extends(DocumentFragment,Node);
902 |
903 |
904 | function ProcessingInstruction() {
905 | }
906 | ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
907 | _extends(ProcessingInstruction,Node);
908 | function XMLSerializer(){}
909 | XMLSerializer.prototype.serializeToString = function(node,isHtml,nodeFilter){
910 | return nodeSerializeToString.call(node,isHtml,nodeFilter);
911 | }
912 | Node.prototype.toString = nodeSerializeToString;
913 | function nodeSerializeToString(isHtml,nodeFilter){
914 | var buf = [];
915 | var refNode = this.nodeType == 9 && this.documentElement || this;
916 | var prefix = refNode.prefix;
917 | var uri = refNode.namespaceURI;
918 |
919 | if(uri && prefix == null){
920 | //console.log(prefix)
921 | var prefix = refNode.lookupPrefix(uri);
922 | if(prefix == null){
923 | //isHTML = true;
924 | var visibleNamespaces=[
925 | {namespace:uri,prefix:null}
926 | //{namespace:uri,prefix:''}
927 | ]
928 | }
929 | }
930 | serializeToString(this,buf,isHtml,nodeFilter,visibleNamespaces);
931 | //console.log('###',this.nodeType,uri,prefix,buf.join(''))
932 | return buf.join('');
933 | }
934 | function needNamespaceDefine(node,isHTML, visibleNamespaces) {
935 | var prefix = node.prefix||'';
936 | var uri = node.namespaceURI;
937 | if (!prefix && !uri){
938 | return false;
939 | }
940 | if (prefix === "xml" && uri === "http://www.w3.org/XML/1998/namespace"
941 | || uri == 'http://www.w3.org/2000/xmlns/'){
942 | return false;
943 | }
944 |
945 | var i = visibleNamespaces.length
946 | //console.log('@@@@',node.tagName,prefix,uri,visibleNamespaces)
947 | while (i--) {
948 | var ns = visibleNamespaces[i];
949 | // get namespace prefix
950 | //console.log(node.nodeType,node.tagName,ns.prefix,prefix)
951 | if (ns.prefix == prefix){
952 | return ns.namespace != uri;
953 | }
954 | }
955 | //console.log(isHTML,uri,prefix=='')
956 | //if(isHTML && prefix ==null && uri == 'http://www.w3.org/1999/xhtml'){
957 | // return false;
958 | //}
959 | //node.flag = '11111'
960 | //console.error(3,true,node.flag,node.prefix,node.namespaceURI)
961 | return true;
962 | }
963 | function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
964 | if(nodeFilter){
965 | node = nodeFilter(node);
966 | if(node){
967 | if(typeof node == 'string'){
968 | buf.push(node);
969 | return;
970 | }
971 | }else{
972 | return;
973 | }
974 | //buf.sort.apply(attrs, attributeSorter);
975 | }
976 | switch(node.nodeType){
977 | case ELEMENT_NODE:
978 | if (!visibleNamespaces) visibleNamespaces = [];
979 | var startVisibleNamespaces = visibleNamespaces.length;
980 | var attrs = node.attributes;
981 | var len = attrs.length;
982 | var child = node.firstChild;
983 | var nodeName = node.tagName;
984 |
985 | isHTML = (htmlns === node.namespaceURI) ||isHTML
986 | buf.push('<',nodeName);
987 |
988 |
989 |
990 | for(var i=0;i');
1021 | //if is cdata child node
1022 | if(isHTML && /^script$/i.test(nodeName)){
1023 | while(child){
1024 | if(child.data){
1025 | buf.push(child.data);
1026 | }else{
1027 | serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
1028 | }
1029 | child = child.nextSibling;
1030 | }
1031 | }else
1032 | {
1033 | while(child){
1034 | serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
1035 | child = child.nextSibling;
1036 | }
1037 | }
1038 | buf.push('',nodeName,'>');
1039 | }else{
1040 | buf.push('/>');
1041 | }
1042 | // remove added visible namespaces
1043 | //visibleNamespaces.length = startVisibleNamespaces;
1044 | return;
1045 | case DOCUMENT_NODE:
1046 | case DOCUMENT_FRAGMENT_NODE:
1047 | var child = node.firstChild;
1048 | while(child){
1049 | serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
1050 | child = child.nextSibling;
1051 | }
1052 | return;
1053 | case ATTRIBUTE_NODE:
1054 | return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
1055 | case TEXT_NODE:
1056 | return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
1057 | case CDATA_SECTION_NODE:
1058 | return buf.push( '');
1059 | case COMMENT_NODE:
1060 | return buf.push( "");
1061 | case DOCUMENT_TYPE_NODE:
1062 | var pubid = node.publicId;
1063 | var sysid = node.systemId;
1064 | buf.push('');
1071 | }else if(sysid && sysid!='.'){
1072 | buf.push(' SYSTEM "',sysid,'">');
1073 | }else{
1074 | var sub = node.internalSubset;
1075 | if(sub){
1076 | buf.push(" [",sub,"]");
1077 | }
1078 | buf.push(">");
1079 | }
1080 | return;
1081 | case PROCESSING_INSTRUCTION_NODE:
1082 | return buf.push( "",node.target," ",node.data,"?>");
1083 | case ENTITY_REFERENCE_NODE:
1084 | return buf.push( '&',node.nodeName,';');
1085 | //case ENTITY_NODE:
1086 | //case NOTATION_NODE:
1087 | default:
1088 | buf.push('??',node.nodeName);
1089 | }
1090 | }
1091 | function importNode(doc,node,deep){
1092 | var node2;
1093 | switch (node.nodeType) {
1094 | case ELEMENT_NODE:
1095 | node2 = node.cloneNode(false);
1096 | node2.ownerDocument = doc;
1097 | //var attrs = node2.attributes;
1098 | //var len = attrs.length;
1099 | //for(var i=0;i',
4 | amp: '&',
5 | quot: '"',
6 | apos: "'",
7 | Agrave: "À",
8 | Aacute: "Á",
9 | Acirc: "Â",
10 | Atilde: "Ã",
11 | Auml: "Ä",
12 | Aring: "Å",
13 | AElig: "Æ",
14 | Ccedil: "Ç",
15 | Egrave: "È",
16 | Eacute: "É",
17 | Ecirc: "Ê",
18 | Euml: "Ë",
19 | Igrave: "Ì",
20 | Iacute: "Í",
21 | Icirc: "Î",
22 | Iuml: "Ï",
23 | ETH: "Ð",
24 | Ntilde: "Ñ",
25 | Ograve: "Ò",
26 | Oacute: "Ó",
27 | Ocirc: "Ô",
28 | Otilde: "Õ",
29 | Ouml: "Ö",
30 | Oslash: "Ø",
31 | Ugrave: "Ù",
32 | Uacute: "Ú",
33 | Ucirc: "Û",
34 | Uuml: "Ü",
35 | Yacute: "Ý",
36 | THORN: "Þ",
37 | szlig: "ß",
38 | agrave: "à",
39 | aacute: "á",
40 | acirc: "â",
41 | atilde: "ã",
42 | auml: "ä",
43 | aring: "å",
44 | aelig: "æ",
45 | ccedil: "ç",
46 | egrave: "è",
47 | eacute: "é",
48 | ecirc: "ê",
49 | euml: "ë",
50 | igrave: "ì",
51 | iacute: "í",
52 | icirc: "î",
53 | iuml: "ï",
54 | eth: "ð",
55 | ntilde: "ñ",
56 | ograve: "ò",
57 | oacute: "ó",
58 | ocirc: "ô",
59 | otilde: "õ",
60 | ouml: "ö",
61 | oslash: "ø",
62 | ugrave: "ù",
63 | uacute: "ú",
64 | ucirc: "û",
65 | uuml: "ü",
66 | yacute: "ý",
67 | thorn: "þ",
68 | yuml: "ÿ",
69 | nbsp: " ",
70 | iexcl: "¡",
71 | cent: "¢",
72 | pound: "£",
73 | curren: "¤",
74 | yen: "¥",
75 | brvbar: "¦",
76 | sect: "§",
77 | uml: "¨",
78 | copy: "©",
79 | ordf: "ª",
80 | laquo: "«",
81 | not: "¬",
82 | shy: "",
83 | reg: "®",
84 | macr: "¯",
85 | deg: "°",
86 | plusmn: "±",
87 | sup2: "²",
88 | sup3: "³",
89 | acute: "´",
90 | micro: "µ",
91 | para: "¶",
92 | middot: "·",
93 | cedil: "¸",
94 | sup1: "¹",
95 | ordm: "º",
96 | raquo: "»",
97 | frac14: "¼",
98 | frac12: "½",
99 | frac34: "¾",
100 | iquest: "¿",
101 | times: "×",
102 | divide: "÷",
103 | forall: "∀",
104 | part: "∂",
105 | exist: "∃",
106 | empty: "∅",
107 | nabla: "∇",
108 | isin: "∈",
109 | notin: "∉",
110 | ni: "∋",
111 | prod: "∏",
112 | sum: "∑",
113 | minus: "−",
114 | lowast: "∗",
115 | radic: "√",
116 | prop: "∝",
117 | infin: "∞",
118 | ang: "∠",
119 | and: "∧",
120 | or: "∨",
121 | cap: "∩",
122 | cup: "∪",
123 | 'int': "∫",
124 | there4: "∴",
125 | sim: "∼",
126 | cong: "≅",
127 | asymp: "≈",
128 | ne: "≠",
129 | equiv: "≡",
130 | le: "≤",
131 | ge: "≥",
132 | sub: "⊂",
133 | sup: "⊃",
134 | nsub: "⊄",
135 | sube: "⊆",
136 | supe: "⊇",
137 | oplus: "⊕",
138 | otimes: "⊗",
139 | perp: "⊥",
140 | sdot: "⋅",
141 | Alpha: "Α",
142 | Beta: "Β",
143 | Gamma: "Γ",
144 | Delta: "Δ",
145 | Epsilon: "Ε",
146 | Zeta: "Ζ",
147 | Eta: "Η",
148 | Theta: "Θ",
149 | Iota: "Ι",
150 | Kappa: "Κ",
151 | Lambda: "Λ",
152 | Mu: "Μ",
153 | Nu: "Ν",
154 | Xi: "Ξ",
155 | Omicron: "Ο",
156 | Pi: "Π",
157 | Rho: "Ρ",
158 | Sigma: "Σ",
159 | Tau: "Τ",
160 | Upsilon: "Υ",
161 | Phi: "Φ",
162 | Chi: "Χ",
163 | Psi: "Ψ",
164 | Omega: "Ω",
165 | alpha: "α",
166 | beta: "β",
167 | gamma: "γ",
168 | delta: "δ",
169 | epsilon: "ε",
170 | zeta: "ζ",
171 | eta: "η",
172 | theta: "θ",
173 | iota: "ι",
174 | kappa: "κ",
175 | lambda: "λ",
176 | mu: "μ",
177 | nu: "ν",
178 | xi: "ξ",
179 | omicron: "ο",
180 | pi: "π",
181 | rho: "ρ",
182 | sigmaf: "ς",
183 | sigma: "σ",
184 | tau: "τ",
185 | upsilon: "υ",
186 | phi: "φ",
187 | chi: "χ",
188 | psi: "ψ",
189 | omega: "ω",
190 | thetasym: "ϑ",
191 | upsih: "ϒ",
192 | piv: "ϖ",
193 | OElig: "Œ",
194 | oelig: "œ",
195 | Scaron: "Š",
196 | scaron: "š",
197 | Yuml: "Ÿ",
198 | fnof: "ƒ",
199 | circ: "ˆ",
200 | tilde: "˜",
201 | ensp: " ",
202 | emsp: " ",
203 | thinsp: " ",
204 | zwnj: "",
205 | zwj: "",
206 | lrm: "",
207 | rlm: "",
208 | ndash: "–",
209 | mdash: "—",
210 | lsquo: "‘",
211 | rsquo: "’",
212 | sbquo: "‚",
213 | ldquo: "“",
214 | rdquo: "”",
215 | bdquo: "„",
216 | dagger: "†",
217 | Dagger: "‡",
218 | bull: "•",
219 | hellip: "…",
220 | permil: "‰",
221 | prime: "′",
222 | Prime: "″",
223 | lsaquo: "‹",
224 | rsaquo: "›",
225 | oline: "‾",
226 | euro: "€",
227 | trade: "™",
228 | larr: "←",
229 | uarr: "↑",
230 | rarr: "→",
231 | darr: "↓",
232 | harr: "↔",
233 | crarr: "↵",
234 | lceil: "⌈",
235 | rceil: "⌉",
236 | lfloor: "⌊",
237 | rfloor: "⌋",
238 | loz: "◊",
239 | spades: "♠",
240 | clubs: "♣",
241 | hearts: "♥",
242 | diams: "♦"
243 | };
244 | //for(var n in exports.entityMap){console.log(exports.entityMap[n].charCodeAt())}
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "xmldom-alpha",
3 | "version": "0.1.28",
4 | "description": "A W3C Standard XML DOM(Level2 CORE) implementation and parser(DOMParser/XMLSerializer).",
5 | "keywords": ["w3c","dom","xml","parser","javascript","DOMParser","XMLSerializer"],
6 | "author": "jindw (http://www.xidea.org)",
7 | "homepage": "https://github.com/jindw/xmldom",
8 | "repository": {"type": "git","url": "git://github.com/jindw/xmldom.git"},
9 | "main": "./dom-parser.js",
10 | "scripts" : { "test": "proof platform win32 && proof test */*/*.t.js || t/test" },
11 | "engines": {"node": ">=0.1"},
12 | "dependencies": {},
13 | "devDependencies": { "proof": "0.0.28" },
14 | "maintainers": [{"name": "jindw","email": "jindw@xidea.org","url": "http://www.xidea.org"}],
15 | "contributors": [
16 | {"name" : "Yaron Naveh","email" : "yaronn01@gmail.com","web" : "http://webservices20.blogspot.com/"},
17 | {"name" : "Harutyun Amirjanyan","email" : "amirjanyan@gmail.com","web" : "https://github.com/nightwing"},
18 | {"name" : "Alan Gutierrez","email" : "alan@prettyrobots.com","web" : "http://www.prettyrobots.com/"}
19 | ],
20 | "bugs": {"email": "jindw@xidea.org","url": "http://github.com/jindw/xmldom/issues"},
21 | "license": "(LGPL-2.0 or MIT)"
22 | }
23 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # XMLDOM [](http://travis-ci.org/bigeasy/xmldom) [](https://coveralls.io/r/bigeasy/xmldom) [](http://badge.fury.io/js/xmldom)
2 |
3 | A JavaScript implementation of W3C DOM for Node.js, Rhino and the browser. Fully
4 | compatible with `W3C DOM level2`; and some compatible with `level3`. Supports
5 | `DOMParser` and `XMLSerializer` interface such as in browser.
6 |
7 | Install:
8 | -------
9 | >npm install xmldom
10 |
11 | Example:
12 | ====
13 | ```javascript
14 | var DOMParser = require('xmldom').DOMParser;
15 | var doc = new DOMParser().parseFromString(
16 | '\n'+
17 | '\ttest\n'+
18 | '\t\n'+
19 | '\t\n'+
20 | ''
21 | ,'text/xml');
22 | doc.documentElement.setAttribute('x','y');
23 | doc.documentElement.setAttributeNS('./lite','c:x','y2');
24 | var nsAttr = doc.documentElement.getAttributeNS('./lite','x')
25 | console.info(nsAttr)
26 | console.info(doc)
27 | ```
28 | API Reference
29 | =====
30 |
31 | * [DOMParser](https://developer.mozilla.org/en/DOMParser):
32 |
33 | ```javascript
34 | parseFromString(xmlsource,mimeType)
35 | ```
36 | * **options extension** _by xmldom_(not BOM standard!!)
37 |
38 | ```javascript
39 | //added the options argument
40 | new DOMParser(options)
41 |
42 | //errorHandler is supported
43 | new DOMParser({
44 | /**
45 | * locator is always need for error position info
46 | */
47 | locator:{},
48 | /**
49 | * you can override the errorHandler for xml parser
50 | * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
51 | */
52 | errorHandler:{warning:function(w){console.warn(w)},error:callback,fatalError:callback}
53 | //only callback model
54 | //errorHandler:function(level,msg){console.log(level,msg)}
55 | })
56 |
57 | ```
58 |
59 | * [XMLSerializer](https://developer.mozilla.org/en/XMLSerializer)
60 |
61 | ```javascript
62 | serializeToString(node)
63 | ```
64 | DOM level2 method and attribute:
65 | ------
66 |
67 | * [Node](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247)
68 |
69 | attribute:
70 | nodeValue|prefix
71 | readonly attribute:
72 | nodeName|nodeType|parentNode|childNodes|firstChild|lastChild|previousSibling|nextSibling|attributes|ownerDocument|namespaceURI|localName
73 | method:
74 | insertBefore(newChild, refChild)
75 | replaceChild(newChild, oldChild)
76 | removeChild(oldChild)
77 | appendChild(newChild)
78 | hasChildNodes()
79 | cloneNode(deep)
80 | normalize()
81 | isSupported(feature, version)
82 | hasAttributes()
83 |
84 | * [DOMImplementation](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-102161490)
85 |
86 | method:
87 | hasFeature(feature, version)
88 | createDocumentType(qualifiedName, publicId, systemId)
89 | createDocument(namespaceURI, qualifiedName, doctype)
90 |
91 | * [Document](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#i-Document) : Node
92 |
93 | readonly attribute:
94 | doctype|implementation|documentElement
95 | method:
96 | createElement(tagName)
97 | createDocumentFragment()
98 | createTextNode(data)
99 | createComment(data)
100 | createCDATASection(data)
101 | createProcessingInstruction(target, data)
102 | createAttribute(name)
103 | createEntityReference(name)
104 | getElementsByTagName(tagname)
105 | importNode(importedNode, deep)
106 | createElementNS(namespaceURI, qualifiedName)
107 | createAttributeNS(namespaceURI, qualifiedName)
108 | getElementsByTagNameNS(namespaceURI, localName)
109 | getElementById(elementId)
110 |
111 | * [DocumentFragment](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-B63ED1A3) : Node
112 | * [Element](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-745549614) : Node
113 |
114 | readonly attribute:
115 | tagName
116 | method:
117 | getAttribute(name)
118 | setAttribute(name, value)
119 | removeAttribute(name)
120 | getAttributeNode(name)
121 | setAttributeNode(newAttr)
122 | removeAttributeNode(oldAttr)
123 | getElementsByTagName(name)
124 | getAttributeNS(namespaceURI, localName)
125 | setAttributeNS(namespaceURI, qualifiedName, value)
126 | removeAttributeNS(namespaceURI, localName)
127 | getAttributeNodeNS(namespaceURI, localName)
128 | setAttributeNodeNS(newAttr)
129 | getElementsByTagNameNS(namespaceURI, localName)
130 | hasAttribute(name)
131 | hasAttributeNS(namespaceURI, localName)
132 |
133 | * [Attr](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-637646024) : Node
134 |
135 | attribute:
136 | value
137 | readonly attribute:
138 | name|specified|ownerElement
139 |
140 | * [NodeList](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177)
141 |
142 | readonly attribute:
143 | length
144 | method:
145 | item(index)
146 |
147 | * [NamedNodeMap](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1780488922)
148 |
149 | readonly attribute:
150 | length
151 | method:
152 | getNamedItem(name)
153 | setNamedItem(arg)
154 | removeNamedItem(name)
155 | item(index)
156 | getNamedItemNS(namespaceURI, localName)
157 | setNamedItemNS(arg)
158 | removeNamedItemNS(namespaceURI, localName)
159 |
160 | * [CharacterData](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-FF21A306) : Node
161 |
162 | method:
163 | substringData(offset, count)
164 | appendData(arg)
165 | insertData(offset, arg)
166 | deleteData(offset, count)
167 | replaceData(offset, count, arg)
168 |
169 | * [Text](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1312295772) : CharacterData
170 |
171 | method:
172 | splitText(offset)
173 |
174 | * [CDATASection](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-667469212)
175 | * [Comment](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1728279322) : CharacterData
176 |
177 | * [DocumentType](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-412266927)
178 |
179 | readonly attribute:
180 | name|entities|notations|publicId|systemId|internalSubset
181 |
182 | * Notation : Node
183 |
184 | readonly attribute:
185 | publicId|systemId
186 |
187 | * Entity : Node
188 |
189 | readonly attribute:
190 | publicId|systemId|notationName
191 |
192 | * EntityReference : Node
193 | * ProcessingInstruction : Node
194 |
195 | attribute:
196 | data
197 | readonly attribute:
198 | target
199 |
200 | DOM level 3 support:
201 | -----
202 |
203 | * [Node](http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-textContent)
204 |
205 | attribute:
206 | textContent
207 | method:
208 | isDefaultNamespace(namespaceURI){
209 | lookupNamespaceURI(prefix)
210 |
211 | DOM extension by xmldom
212 | ---
213 | * [Node] Source position extension;
214 |
215 | attribute:
216 | //Numbered starting from '1'
217 | lineNumber
218 | //Numbered starting from '1'
219 | columnNumber
220 |
--------------------------------------------------------------------------------
/sax.js:
--------------------------------------------------------------------------------
1 | //[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
2 | //[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
3 | //[5] Name ::= NameStartChar (NameChar)*
4 | var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF
5 | var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
6 | var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
7 | //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
8 | //var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
9 |
10 | //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
11 | //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
12 | var S_TAG = 0;//tag name offerring
13 | var S_ATTR = 1;//attr name offerring
14 | var S_ATTR_SPACE=2;//attr name end and space offer
15 | var S_EQ = 3;//=space?
16 | var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)
17 | var S_ATTR_END = 5;//attr value end and no space(quot end)
18 | var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
19 | var S_TAG_CLOSE = 7;//closed el
20 |
21 | function XMLReader(){
22 |
23 | }
24 |
25 | XMLReader.prototype = {
26 | parse:function(source,defaultNSMap,entityMap){
27 | var domBuilder = this.domBuilder;
28 | domBuilder.startDocument();
29 | _copy(defaultNSMap ,defaultNSMap = {})
30 | parse(source,defaultNSMap,entityMap,
31 | domBuilder,this.errorHandler);
32 | domBuilder.endDocument();
33 | }
34 | }
35 | function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
36 | function fixedFromCharCode(code) {
37 | // String.prototype.fromCharCode does not supports
38 | // > 2 bytes unicode chars directly
39 | if (code > 0xffff) {
40 | code -= 0x10000;
41 | var surrogate1 = 0xd800 + (code >> 10)
42 | , surrogate2 = 0xdc00 + (code & 0x3ff);
43 |
44 | return String.fromCharCode(surrogate1, surrogate2);
45 | } else {
46 | return String.fromCharCode(code);
47 | }
48 | }
49 | function entityReplacer(a){
50 | var k = a.slice(1,-1);
51 | if(k in entityMap){
52 | return entityMap[k];
53 | }else if(k.charAt(0) === '#'){
54 | return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
55 | }else{
56 | errorHandler.error('entity not found:'+a);
57 | return a;
58 | }
59 | }
60 | function appendText(end){//has some bugs
61 | if(end>start){
62 | var xt = source.substring(start,end).replace(/?\w+;/g,entityReplacer);
63 | locator&&position(start);
64 | domBuilder.characters(xt,0,end-start);
65 | start = end
66 | }
67 | }
68 | function position(p,m){
69 | while(p>=lineEnd && (m = linePattern.exec(source))){
70 | lineStart = m.index;
71 | lineEnd = lineStart + m[0].length;
72 | locator.lineNumber++;
73 | //console.log('line++:',locator,startPos,endPos)
74 | }
75 | locator.columnNumber = p-lineStart+1;
76 | }
77 | var lineStart = 0;
78 | var lineEnd = 0;
79 | var linePattern = /.*(?:\r\n?|\n)|.*$/g
80 | var locator = domBuilder.locator;
81 |
82 | var parseStack = [{currentNSMap:defaultNSMapCopy}]
83 | var closeMap = {};
84 | var start = 0;
85 | while(true){
86 | try{
87 | var tagStart = source.indexOf('<',start);
88 | if(tagStart<0){
89 | if(!source.substr(start).match(/^\s*$/)){
90 | var doc = domBuilder.doc;
91 | var text = doc.createTextNode(source.substr(start));
92 | doc.appendChild(text);
93 | domBuilder.currentElement = text;
94 | }
95 | return;
96 | }
97 | if(tagStart>start){
98 | appendText(tagStart);
99 | }
100 | switch(source.charAt(tagStart+1)){
101 | case '/':
102 | var end = source.indexOf('>',tagStart+3);
103 | var tagName = source.substring(tagStart+2,end);
104 | var config = parseStack.pop();
105 | if(end<0){
106 |
107 | tagName = source.substring(tagStart+2).replace(/[\s<].*/,'');
108 | //console.error('#@@@@@@'+tagName)
109 | errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName);
110 | end = tagStart+1+tagName.length;
111 | }else if(tagName.match(/\s)){
112 | tagName = tagName.replace(/[\s<].*/,'');
113 | errorHandler.error("end tag name: "+tagName+' maybe not complete');
114 | end = tagStart+1+tagName.length;
115 | }
116 | //console.error(parseStack.length,parseStack)
117 | //console.error(config);
118 | var localNSMap = config.localNSMap;
119 | var endMatch = config.tagName == tagName;
120 | var endIgnoreCaseMach = endMatch || config.tagName&&config.tagName.toLowerCase() == tagName.toLowerCase()
121 | if(endIgnoreCaseMach){
122 | domBuilder.endElement(config.uri,config.localName,tagName);
123 | if(localNSMap){
124 | for(var prefix in localNSMap){
125 | domBuilder.endPrefixMapping(prefix) ;
126 | }
127 | }
128 | if(!endMatch){
129 | errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
130 | }
131 | }else{
132 | parseStack.push(config)
133 | }
134 |
135 | end++;
136 | break;
137 | // end elment
138 | case '?':// ...?>
139 | locator&&position(tagStart);
140 | end = parseInstruction(source,tagStart,domBuilder);
141 | break;
142 | case '!':// start){
196 | start = end;
197 | }else{
198 | //TODO: 这里有可能sax回退,有位置错误风险
199 | appendText(Math.max(tagStart,start)+1);
200 | }
201 | }
202 | }
203 | function copyLocator(f,t){
204 | t.lineNumber = f.lineNumber;
205 | t.columnNumber = f.columnNumber;
206 | return t;
207 | }
208 |
209 | /**
210 | * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
211 | * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
212 | */
213 | function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){
214 | var attrName;
215 | var value;
216 | var p = ++start;
217 | var s = S_TAG;//status
218 | while(true){
219 | var c = source.charAt(p);
220 | switch(c){
221 | case '=':
222 | if(s === S_ATTR){//attrName
223 | attrName = source.slice(start,p);
224 | s = S_EQ;
225 | }else if(s === S_ATTR_SPACE){
226 | s = S_EQ;
227 | }else{
228 | //fatalError: equal must after attrName or space after attrName
229 | throw new Error('attribute equal must after attrName');
230 | }
231 | break;
232 | case '\'':
233 | case '"':
234 | if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
235 | ){//equal
236 | if(s === S_ATTR){
237 | errorHandler.warning('attribute value must after "="')
238 | attrName = source.slice(start,p)
239 | }
240 | start = p+1;
241 | p = source.indexOf(c,start)
242 | if(p>0){
243 | value = source.slice(start,p).replace(/?\w+;/g,entityReplacer);
244 | el.add(attrName,value,start-1);
245 | s = S_ATTR_END;
246 | }else{
247 | //fatalError: no end quot match
248 | throw new Error('attribute value no end \''+c+'\' match');
249 | }
250 | }else if(s == S_ATTR_NOQUOT_VALUE){
251 | value = source.slice(start,p).replace(/?\w+;/g,entityReplacer);
252 | //console.log(attrName,value,start,p)
253 | el.add(attrName,value,start);
254 | //console.dir(el)
255 | errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
256 | start = p+1;
257 | s = S_ATTR_END
258 | }else{
259 | //fatalError: no equal before
260 | throw new Error('attribute value must after "="');
261 | }
262 | break;
263 | case '/':
264 | switch(s){
265 | case S_TAG:
266 | el.setTagName(source.slice(start,p));
267 | case S_ATTR_END:
268 | case S_TAG_SPACE:
269 | case S_TAG_CLOSE:
270 | s =S_TAG_CLOSE;
271 | el.closed = true;
272 | case S_ATTR_NOQUOT_VALUE:
273 | case S_ATTR:
274 | case S_ATTR_SPACE:
275 | break;
276 | //case S_EQ:
277 | default:
278 | throw new Error("attribute invalid close char('/')")
279 | }
280 | break;
281 | case ''://end document
282 | //throw new Error('unexpected end of input')
283 | errorHandler.error('unexpected end of input');
284 | if(s == S_TAG){
285 | el.setTagName(source.slice(start,p));
286 | }
287 | return p;
288 | case '>':
289 | switch(s){
290 | case S_TAG:
291 | el.setTagName(source.slice(start,p));
292 | case S_ATTR_END:
293 | case S_TAG_SPACE:
294 | case S_TAG_CLOSE:
295 | break;//normal
296 | case S_ATTR_NOQUOT_VALUE://Compatible state
297 | case S_ATTR:
298 | value = source.slice(start,p);
299 | if(value.slice(-1) === '/'){
300 | el.closed = true;
301 | value = value.slice(0,-1)
302 | }
303 | case S_ATTR_SPACE:
304 | if(s === S_ATTR_SPACE){
305 | value = attrName;
306 | }
307 | if(s == S_ATTR_NOQUOT_VALUE){
308 | errorHandler.warning('attribute "'+value+'" missed quot(")!!');
309 | el.add(attrName,value.replace(/?\w+;/g,entityReplacer),start)
310 | }else{
311 | if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)){
312 | errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
313 | }
314 | el.add(value,value,start)
315 | }
316 | break;
317 | case S_EQ:
318 | throw new Error('attribute value missed!!');
319 | }
320 | // console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
321 | return p;
322 | /*xml space '\x20' | #x9 | #xD | #xA; */
323 | case '\u0080':
324 | c = ' ';
325 | default:
326 | if(c<= ' '){//space
327 | switch(s){
328 | case S_TAG:
329 | el.setTagName(source.slice(start,p));//tagName
330 | s = S_TAG_SPACE;
331 | break;
332 | case S_ATTR:
333 | attrName = source.slice(start,p)
334 | s = S_ATTR_SPACE;
335 | break;
336 | case S_ATTR_NOQUOT_VALUE:
337 | var value = source.slice(start,p).replace(/?\w+;/g,entityReplacer);
338 | errorHandler.warning('attribute "'+value+'" missed quot(")!!');
339 | el.add(attrName,value,start)
340 | case S_ATTR_END:
341 | s = S_TAG_SPACE;
342 | break;
343 | //case S_TAG_SPACE:
344 | //case S_EQ:
345 | //case S_ATTR_SPACE:
346 | // void();break;
347 | //case S_TAG_CLOSE:
348 | //ignore warning
349 | }
350 | }else{//not space
351 | //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
352 | //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
353 | switch(s){
354 | //case S_TAG:void();break;
355 | //case S_ATTR:void();break;
356 | //case S_ATTR_NOQUOT_VALUE:void();break;
357 | case S_ATTR_SPACE:
358 | var tagName = el.tagName;
359 | if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)){
360 | errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!')
361 | }
362 | el.add(attrName,attrName,start);
363 | start = p;
364 | s = S_ATTR;
365 | break;
366 | case S_ATTR_END:
367 | errorHandler.warning('attribute space is required"'+attrName+'"!!')
368 | case S_TAG_SPACE:
369 | s = S_ATTR;
370 | start = p;
371 | break;
372 | case S_EQ:
373 | s = S_ATTR_NOQUOT_VALUE;
374 | start = p;
375 | break;
376 | case S_TAG_CLOSE:
377 | throw new Error("elements closed character '/' and '>' must be connected to");
378 | }
379 | }
380 | }//end outer switch
381 | //console.log('p++',p)
382 | p++;
383 | }
384 | }
385 | /**
386 | * @return true if has new namespace define
387 | */
388 | function appendElement(el,domBuilder,currentNSMap){
389 | var tagName = el.tagName;
390 | var localNSMap = null;
391 | //var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
392 | var i = el.length;
393 | while(i--){
394 | var a = el[i];
395 | var qName = a.qName;
396 | var value = a.value;
397 | var nsp = qName.indexOf(':');
398 | if(nsp>0){
399 | var prefix = a.prefix = qName.slice(0,nsp);
400 | var localName = qName.slice(nsp+1);
401 | var nsPrefix = prefix === 'xmlns' && localName
402 | }else{
403 | localName = qName;
404 | prefix = null
405 | nsPrefix = qName === 'xmlns' && ''
406 | }
407 | //can not set prefix,because prefix !== ''
408 | a.localName = localName ;
409 | //prefix == null for no ns prefix attribute
410 | if(nsPrefix !== false){//hack!!
411 | if(localNSMap == null){
412 | localNSMap = {}
413 | //console.log(currentNSMap,0)
414 | _copy(currentNSMap,currentNSMap={})
415 | //console.log(currentNSMap,1)
416 | }
417 | currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
418 | a.uri = 'http://www.w3.org/2000/xmlns/'
419 | domBuilder.startPrefixMapping(nsPrefix, value)
420 | }
421 | }
422 | var i = el.length;
423 | while(i--){
424 | a = el[i];
425 | var prefix = a.prefix;
426 | if(prefix){//no prefix attribute has no namespace
427 | if(prefix === 'xml'){
428 | a.uri = 'http://www.w3.org/XML/1998/namespace';
429 | }if(prefix !== 'xmlns'){
430 | a.uri = currentNSMap[prefix || '']
431 |
432 | //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
433 | }
434 | }
435 | }
436 | var nsp = tagName.indexOf(':');
437 | if(nsp>0){
438 | prefix = el.prefix = tagName.slice(0,nsp);
439 | localName = el.localName = tagName.slice(nsp+1);
440 | }else{
441 | prefix = null;//important!!
442 | localName = el.localName = tagName;
443 | }
444 | //no prefix element has default namespace
445 | var ns = el.uri = currentNSMap[prefix || ''];
446 | domBuilder.startElement(ns,localName,tagName,el);
447 | //endPrefixMapping and startPrefixMapping have not any help for dom builder
448 | //localNSMap = null
449 | if(el.closed){
450 | domBuilder.endElement(ns,localName,tagName);
451 | if(localNSMap){
452 | for(prefix in localNSMap){
453 | domBuilder.endPrefixMapping(prefix)
454 | }
455 | }
456 | }else{
457 | el.currentNSMap = currentNSMap;
458 | el.localNSMap = localNSMap;
459 | //parseStack.push(el);
460 | return true;
461 | }
462 | }
463 | function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
464 | if(/^(?:script|textarea)$/i.test(tagName)){
465 | var elEndStart = source.indexOf(''+tagName+'>',elStartEnd);
466 | var text = source.substring(elStartEnd+1,elEndStart);
467 | if(/[&<]/.test(text)){
468 | if(/^script$/i.test(tagName)){
469 | //if(!/\]\]>/.test(text)){
470 | //lexHandler.startCDATA();
471 | domBuilder.characters(text,0,text.length);
472 | //lexHandler.endCDATA();
473 | return elEndStart;
474 | //}
475 | }//}else{//text area
476 | text = text.replace(/?\w+;/g,entityReplacer);
477 | domBuilder.characters(text,0,text.length);
478 | return elEndStart;
479 | //}
480 |
481 | }
482 | }
483 | return elStartEnd+1;
484 | }
485 | function fixSelfClosed(source,elStartEnd,tagName,closeMap){
486 | //if(tagName in closeMap){
487 | var pos = closeMap[tagName];
488 | if(pos == null){
489 | //console.log(tagName)
490 | pos = source.lastIndexOf(''+tagName+'>')
491 | if(pos',start+4);
508 | //append comment source.substring(4,end)//\n\
14 | \n\
15 | \n\
16 | \n\
17 | \n\
18 | \n\
19 | ';
20 | //console.log(xml)
21 | var error = []
22 | var parser = new DOMParser({
23 | locator:{},
24 | errorHandler:{
25 | error:function(msg){
26 | error.push(msg);
27 | //throw new Error(msg)
28 | }
29 | }
30 | });
31 | var doc = parser.parseFromString(xml, 'text/html');
32 | //console.log(doc.toString())
33 | var doc = parser.parseFromString('