-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
, #111
- Loading branch information
1 parent
a0bd0d0
commit fa8e184
Showing
8 changed files
with
2,427 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
function DOMParser(options){ | ||
this.options = options ||{locator:{}}; | ||
} | ||
|
||
DOMParser.prototype.parseFromString = function(source,mimeType){ | ||
var options = this.options; | ||
var sax = new XMLReader(); | ||
var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler | ||
var errorHandler = options.errorHandler; | ||
var locator = options.locator; | ||
var defaultNSMap = options.xmlns||{}; | ||
var isHTML = /\/x?html?$/.test(mimeType);//mimeType.toLowerCase().indexOf('html') > -1; | ||
var entityMap = isHTML?htmlEntity.entityMap:{'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"}; | ||
if(locator){ | ||
domBuilder.setDocumentLocator(locator) | ||
} | ||
|
||
sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator); | ||
sax.domBuilder = options.domBuilder || domBuilder; | ||
if(isHTML){ | ||
defaultNSMap['']= 'http://www.w3.org/1999/xhtml'; | ||
} | ||
defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace'; | ||
if(source && typeof source === 'string'){ | ||
sax.parse(source,defaultNSMap,entityMap); | ||
}else{ | ||
sax.errorHandler.error("invalid doc source"); | ||
} | ||
return domBuilder.doc; | ||
} | ||
function buildErrorHandler(errorImpl,domBuilder,locator){ | ||
if(!errorImpl){ | ||
if(domBuilder instanceof DOMHandler){ | ||
return domBuilder; | ||
} | ||
errorImpl = domBuilder ; | ||
} | ||
var errorHandler = {} | ||
var isCallback = errorImpl instanceof Function; | ||
locator = locator||{} | ||
function build(key){ | ||
var fn = errorImpl[key]; | ||
if(!fn && isCallback){ | ||
fn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl; | ||
} | ||
errorHandler[key] = fn && function(msg){ | ||
fn('[xmldom '+key+']\t'+msg+_locator(locator)); | ||
}||function(){}; | ||
} | ||
build('warning'); | ||
build('error'); | ||
build('fatalError'); | ||
return errorHandler; | ||
} | ||
|
||
//console.log('#\n\n\n\n\n\n\n####') | ||
/** | ||
* +ContentHandler+ErrorHandler | ||
* +LexicalHandler+EntityResolver2 | ||
* -DeclHandler-DTDHandler | ||
* | ||
* DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler | ||
* DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2 | ||
* @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html | ||
*/ | ||
function DOMHandler() { | ||
this.cdata = false; | ||
} | ||
function position(locator,node){ | ||
node.lineNumber = locator.lineNumber; | ||
node.columnNumber = locator.columnNumber; | ||
} | ||
/** | ||
* @see org.xml.sax.ContentHandler#startDocument | ||
* @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html | ||
*/ | ||
DOMHandler.prototype = { | ||
startDocument : function() { | ||
this.doc = new DOMImplementation().createDocument(null, null, null); | ||
if (this.locator) { | ||
this.doc.documentURI = this.locator.systemId; | ||
} | ||
}, | ||
startElement:function(namespaceURI, localName, qName, attrs) { | ||
var doc = this.doc; | ||
var el = doc.createElementNS(namespaceURI, qName||localName); | ||
var len = attrs.length; | ||
appendElement(this, el); | ||
this.currentElement = el; | ||
|
||
this.locator && position(this.locator,el) | ||
for (var i = 0 ; i < len; i++) { | ||
var namespaceURI = attrs.getURI(i); | ||
var value = attrs.getValue(i); | ||
var qName = attrs.getQName(i); | ||
var attr = doc.createAttributeNS(namespaceURI, qName); | ||
this.locator &&position(attrs.getLocator(i),attr); | ||
attr.value = attr.nodeValue = value; | ||
el.setAttributeNode(attr) | ||
} | ||
}, | ||
endElement:function(namespaceURI, localName, qName) { | ||
var current = this.currentElement | ||
var tagName = current.tagName; | ||
this.currentElement = current.parentNode; | ||
}, | ||
startPrefixMapping:function(prefix, uri) { | ||
}, | ||
endPrefixMapping:function(prefix) { | ||
}, | ||
processingInstruction:function(target, data) { | ||
var ins = this.doc.createProcessingInstruction(target, data); | ||
this.locator && position(this.locator,ins) | ||
appendElement(this, ins); | ||
}, | ||
ignorableWhitespace:function(ch, start, length) { | ||
}, | ||
characters:function(chars, start, length) { | ||
chars = _toString.apply(this,arguments) | ||
//console.log(chars) | ||
if(chars){ | ||
if (this.cdata) { | ||
var charNode = this.doc.createCDATASection(chars); | ||
} else { | ||
var charNode = this.doc.createTextNode(chars); | ||
} | ||
if(this.currentElement){ | ||
this.currentElement.appendChild(charNode); | ||
}else if(/^\s*$/.test(chars)){ | ||
this.doc.appendChild(charNode); | ||
//process xml | ||
} | ||
this.locator && position(this.locator,charNode) | ||
} | ||
}, | ||
skippedEntity:function(name) { | ||
}, | ||
endDocument:function() { | ||
this.doc.normalize(); | ||
}, | ||
setDocumentLocator:function (locator) { | ||
if(this.locator = locator){// && !('lineNumber' in locator)){ | ||
locator.lineNumber = 0; | ||
} | ||
}, | ||
//LexicalHandler | ||
comment:function(chars, start, length) { | ||
chars = _toString.apply(this,arguments) | ||
var comm = this.doc.createComment(chars); | ||
this.locator && position(this.locator,comm) | ||
appendElement(this, comm); | ||
}, | ||
|
||
startCDATA:function() { | ||
//used in characters() methods | ||
this.cdata = true; | ||
}, | ||
endCDATA:function() { | ||
this.cdata = false; | ||
}, | ||
|
||
startDTD:function(name, publicId, systemId) { | ||
var impl = this.doc.implementation; | ||
if (impl && impl.createDocumentType) { | ||
var dt = impl.createDocumentType(name, publicId, systemId); | ||
this.locator && position(this.locator,dt) | ||
appendElement(this, dt); | ||
} | ||
}, | ||
/** | ||
* @see org.xml.sax.ErrorHandler | ||
* @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html | ||
*/ | ||
warning:function(error) { | ||
console.warn('[xmldom warning]\t'+error,_locator(this.locator)); | ||
}, | ||
error:function(error) { | ||
console.error('[xmldom error]\t'+error,_locator(this.locator)); | ||
}, | ||
fatalError:function(error) { | ||
throw new ParseError(error, this.locator); | ||
} | ||
} | ||
function _locator(l){ | ||
if(l){ | ||
return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']' | ||
} | ||
} | ||
function _toString(chars,start,length){ | ||
if(typeof chars == 'string'){ | ||
return chars.substr(start,length) | ||
}else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)") | ||
if(chars.length >= start+length || start){ | ||
return new java.lang.String(chars,start,length)+''; | ||
} | ||
return chars; | ||
} | ||
} | ||
|
||
/* | ||
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html | ||
* used method of org.xml.sax.ext.LexicalHandler: | ||
* #comment(chars, start, length) | ||
* #startCDATA() | ||
* #endCDATA() | ||
* #startDTD(name, publicId, systemId) | ||
* | ||
* | ||
* IGNORED method of org.xml.sax.ext.LexicalHandler: | ||
* #endDTD() | ||
* #startEntity(name) | ||
* #endEntity(name) | ||
* | ||
* | ||
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html | ||
* IGNORED method of org.xml.sax.ext.DeclHandler | ||
* #attributeDecl(eName, aName, type, mode, value) | ||
* #elementDecl(name, model) | ||
* #externalEntityDecl(name, publicId, systemId) | ||
* #internalEntityDecl(name, value) | ||
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html | ||
* IGNORED method of org.xml.sax.EntityResolver2 | ||
* #resolveEntity(String name,String publicId,String baseURI,String systemId) | ||
* #resolveEntity(publicId, systemId) | ||
* #getExternalSubset(name, baseURI) | ||
* @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html | ||
* IGNORED method of org.xml.sax.DTDHandler | ||
* #notationDecl(name, publicId, systemId) {}; | ||
* #unparsedEntityDecl(name, publicId, systemId, notationName) {}; | ||
*/ | ||
"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){ | ||
DOMHandler.prototype[key] = function(){return null} | ||
}) | ||
|
||
/* 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 */ | ||
function appendElement (hander,node) { | ||
if (!hander.currentElement) { | ||
hander.doc.appendChild(node); | ||
} else { | ||
hander.currentElement.appendChild(node); | ||
} | ||
}//appendChild and setAttributeNS are preformance key | ||
|
||
//if(typeof require == 'function'){ | ||
var htmlEntity = require('./entities'); | ||
var sax = require('./sax'); | ||
var XMLReader = sax.XMLReader; | ||
var ParseError = sax.ParseError; | ||
var DOMImplementation = exports.DOMImplementation = require('./dom').DOMImplementation; | ||
exports.XMLSerializer = require('./dom').XMLSerializer ; | ||
exports.DOMParser = DOMParser; | ||
exports.__DOMHandler = DOMHandler; | ||
//} |
Oops, something went wrong.