2016-02-01 21:28:52 +00:00
function DOMParser ( options ) {
this . options = options || { locator : { } } ;
}
2017-02-07 18:20:30 +00:00
DOMParser . prototype . parseFromString = function ( source , mimeType ) {
2016-02-01 21:28:52 +00:00
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 || { } ;
2017-02-07 18:20:30 +00:00
var isHTML = /\/x?html?$/ . test ( mimeType ) ; //mimeType.toLowerCase().indexOf('html') > -1;
var entityMap = isHTML ? require ( './entities' ) . entityMap : { 'lt' : '<' , 'gt' : '>' , 'amp' : '&' , 'quot' : '"' , 'apos' : "'" } ;
2016-02-01 21:28:52 +00:00
if ( locator ) {
domBuilder . setDocumentLocator ( locator )
}
sax . errorHandler = buildErrorHandler ( errorHandler , domBuilder , locator ) ;
sax . domBuilder = options . domBuilder || domBuilder ;
2017-02-07 18:20:30 +00:00
if ( isHTML ) {
2016-02-01 21:28:52 +00:00
defaultNSMap [ '' ] = 'http://www.w3.org/1999/xhtml' ;
}
defaultNSMap . xml = defaultNSMap . xml || 'http://www.w3.org/XML/1998/namespace' ;
if ( source ) {
sax . parse ( source , defaultNSMap , entityMap ) ;
} else {
2017-02-07 18:20:30 +00:00
sax . errorHandler . error ( "invalid doc source" ) ;
2016-02-01 21:28:52 +00:00
}
2017-02-07 18:20:30 +00:00
return domBuilder . doc ;
2016-02-01 21:28:52 +00:00
}
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 ] ;
2017-02-07 18:20:30 +00:00
if ( ! fn && isCallback ) {
fn = errorImpl . length == 2 ? function ( msg ) { errorImpl ( key , msg ) } : errorImpl ;
2016-02-01 21:28:52 +00:00
}
errorHandler [ key ] = fn && function ( msg ) {
2017-02-07 18:20:30 +00:00
fn ( '[xmldom ' + key + ']\t' + msg + _locator ( locator ) ) ;
2016-02-01 21:28:52 +00:00
} || function ( ) { } ;
}
2017-02-07 18:20:30 +00:00
build ( 'warning' ) ;
build ( 'error' ) ;
build ( 'fatalError' ) ;
2016-02-01 21:28:52 +00:00
return errorHandler ;
}
2017-02-07 18:20:30 +00:00
//console.log('#\n\n\n\n\n\n\n####')
2016-02-01 21:28:52 +00:00
/ * *
* + 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 ( ) {
2017-02-07 18:20:30 +00:00
this . doc = new DOMImplementation ( ) . createDocument ( null , null , null ) ;
2016-02-01 21:28:52 +00:00
if ( this . locator ) {
2017-02-07 18:20:30 +00:00
this . doc . documentURI = this . locator . systemId ;
2016-02-01 21:28:52 +00:00
}
} ,
startElement : function ( namespaceURI , localName , qName , attrs ) {
2017-02-07 18:20:30 +00:00
var doc = this . doc ;
2016-02-01 21:28:52 +00:00
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 ) ;
2017-02-07 18:20:30 +00:00
this . locator && position ( attrs . getLocator ( i ) , attr ) ;
2016-02-01 21:28:52 +00:00
attr . value = attr . nodeValue = value ;
el . setAttributeNode ( attr )
}
} ,
endElement : function ( namespaceURI , localName , qName ) {
var current = this . currentElement
2017-02-07 18:20:30 +00:00
var tagName = current . tagName ;
this . currentElement = current . parentNode ;
2016-02-01 21:28:52 +00:00
} ,
startPrefixMapping : function ( prefix , uri ) {
} ,
endPrefixMapping : function ( prefix ) {
} ,
processingInstruction : function ( target , data ) {
2017-02-07 18:20:30 +00:00
var ins = this . doc . createProcessingInstruction ( target , data ) ;
2016-02-01 21:28:52 +00:00
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)
2017-02-07 18:20:30 +00:00
if ( chars ) {
2016-02-01 21:28:52 +00:00
if ( this . cdata ) {
2017-02-07 18:20:30 +00:00
var charNode = this . doc . createCDATASection ( chars ) ;
2016-02-01 21:28:52 +00:00
} else {
2017-02-07 18:20:30 +00:00
var charNode = this . doc . createTextNode ( chars ) ;
}
if ( this . currentElement ) {
2016-02-01 21:28:52 +00:00
this . currentElement . appendChild ( charNode ) ;
2017-02-07 18:20:30 +00:00
} else if ( /^\s*$/ . test ( chars ) ) {
this . doc . appendChild ( charNode ) ;
//process xml
2016-02-01 21:28:52 +00:00
}
this . locator && position ( this . locator , charNode )
}
} ,
skippedEntity : function ( name ) {
} ,
endDocument : function ( ) {
2017-02-07 18:20:30 +00:00
this . doc . normalize ( ) ;
2016-02-01 21:28:52 +00:00
} ,
setDocumentLocator : function ( locator ) {
if ( this . locator = locator ) { // && !('lineNumber' in locator)){
locator . lineNumber = 0 ;
}
} ,
//LexicalHandler
comment : function ( chars , start , length ) {
chars = _toString . apply ( this , arguments )
2017-02-07 18:20:30 +00:00
var comm = this . doc . createComment ( chars ) ;
2016-02-01 21:28:52 +00:00
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 ) {
2017-02-07 18:20:30 +00:00
var impl = this . doc . implementation ;
2016-02-01 21:28:52 +00:00
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 ) {
2017-02-07 18:20:30 +00:00
console . warn ( '[xmldom warning]\t' + error , _locator ( this . locator ) ) ;
2016-02-01 21:28:52 +00:00
} ,
error : function ( error ) {
2017-02-07 18:20:30 +00:00
console . error ( '[xmldom error]\t' + error , _locator ( this . locator ) ) ;
2016-02-01 21:28:52 +00:00
} ,
fatalError : function ( error ) {
2017-02-07 18:20:30 +00:00
console . error ( '[xmldom fatalError]\t' + error , _locator ( this . locator ) ) ;
2016-02-01 21:28:52 +00:00
throw error ;
}
}
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 ) {
2017-02-07 18:20:30 +00:00
hander . doc . appendChild ( node ) ;
2016-02-01 21:28:52 +00:00
} else {
hander . currentElement . appendChild ( node ) ;
}
} //appendChild and setAttributeNS are preformance key
2017-02-07 18:20:30 +00:00
//if(typeof require == 'function'){
2016-02-01 21:28:52 +00:00
var XMLReader = require ( './sax' ) . XMLReader ;
var DOMImplementation = exports . DOMImplementation = require ( './dom' ) . DOMImplementation ;
exports . XMLSerializer = require ( './dom' ) . XMLSerializer ;
exports . DOMParser = DOMParser ;
2017-02-07 18:20:30 +00:00
//}