浏览器对XML DOM的支持
主流浏览器
DOM2级核心
- XML DOM文档没有默认的命名空间
原型
var xmlDom=document.implementation.createDocument(namespaceUri,root,documentType);
创建新的,文档元素为的XMLDOM
var xmlDom=document.implementation.createDocument("","root",null);
console.log(xmlDom.documentElement.tagName);//root
//创建新元素
var xmlEle=xmlDom.createElement("child");
//xmlDom新元素加入
xmlDom.documentElement.appendChild(xmlEle);
console.log(xmlDom.getElementsByTagName("child").length);//1
判断是否支持DOM2级XML
var supportsXML=document.implementation.hasFeature("XML","2.0");//true
DOMParser类型
- 把XML解释为DOM文档
- DOMParser类型必须先创建实例
- parseFromString(XMLstr,”text.xml”)返回一个Document的实例
- 只能返回格式良好的XML字符串,拒绝HTML字符串
把XML解释为DOM
var parser=new DOMParser();
var xmlDom=parser.parseFromString("<root><child/><root>","text/xml");
console.log(xmlDom.documentElement.tagName);//root
console.log(xmlDom.getElementsByTagName("child").length);//1
解析错误时依然返回DOM对象(Docment对象)
safari和chrome的元素会出现在解析错误的地方
var parser=new DOMParser(),xmlDom,errors;
try{
xmlDom=parser.parseFromString("<root>","text/xml");
errors=xmlDom.getElementsByTagName("parsererror");
if(errors.length>0){throw new Error("Parsing error");}
}
catch(ex){alert(ex.message);}//Parsing error
XMLSerializer类型
- 把XMLDOM序列化为XML
- XMLSerializer类型,必须先创建实例
- 可以序列化任何有效的DOM对象(Docment对象),包括HTMLDOM
把XMLDOM序列化为XML
//创建XMLDON
var xmlDom=(new DOMParser()).parseFromString("<root><child/></root>","text/xml");
console.log(xmlDom);
//序列化XMLDOM
var xml=(new XMLSerializer()).serializeToString(xmlDom);
console.log(xml);
IE浏览器
IE8之前版本的XML
- 通过ActiveX对象实现
- 通过ActiveXObject类型创建ActiveX对象的实例
- MSXML库
- 创建XML实例,要使用ActiveXObject构造函数,并传入XML文档版本的字符串
创建XML实例的函数
function createDocument(){
if(typeof arguments.callee.activeXString!="string"){
var i,len,
versions=[
"MSXML2.DOMDocument.6.0",
"MSXML2.DOMDocument.3.0",
"MSXML2.DOMDocument"
];
for(i=0,len=versions.length;i<len;i++){
try{
new ActiveXObject(versions[i]);
arguments.callee.activeXString=versions[i];
break;
}catch(ex){}
}
}
return new ActiveXObject(arguments.callee.activeXString);
}
加载XML
var xmlDom=createDocument();
xmlDom.loadXML("<root><child/></root>");
console.log(xmlDom.documentElement.tagName);//root
console.log(xmlDom.documentElement.firstChild.tagName);//child
console.log(xmlDom.getElementsByTagName("child").length);//1
parseError属性记录解析的错误信息
- errorCode:错误类型的数值编码,没有发生错误时为0
- filePOS:文件中导致错误发生的位置
- line:发生错误的行
- linepos:发生错误的行中的字符
- reason:对错误的文本解析
- srcText:导致错误的代码
- url:导致错误文件的URL(如果有)
- valueOf():返回errorCode的值
在loadXML()之后,查询XML文档之前,检查是否发生了解析错误
if(xmlDom.parseError!=0){
alert("An error occurred:\nError Code:"
+xmlDom.parseError.errorCode+"\n"
+"Line:"+xmlDom.parseError.line+"\n"
+"Line Pos"+"xmlDom.parseError.linepos"+"\n"
+"Reason"+"xmlDom.parseError.reason");
}
序列化,每个节点都支持
console.log(xmlDom.xml);//"<root><child/></root>"
异步设置
加载XML文件,与DOM3级类似
同步加载下载时间长会导致缓慢
var xmlDom=createDocument();
//设置异步属性
xmlDom.async=false;
xmlDom.load("example.xml");//传入xml序列化字符串或者url字符串
异步加载事件
onreadystatechange事件,内部要使用文档变量名称(xmlDom),不能使用this
readyState属性的4个状态1234
readyState属性每一次改变都会触发onreadystatechance事件
var xmlDom=createDocument();
xmlDom.async=true;
xmlDom.onreadystatechance=function(){
if(xmlDom.readyState==4){
if (xmlDom.parseError!=0) {
alert("An error occurred:\nError Code:"
+xmlDom.parseError.errorCode+"\n"
+"Line:"+xmlDom.parseError.line+"\n"
+"Line Pos"+"xmlDom.parseError.linepos"+"\n"
+"Reason"+"xmlDom.parseError.reason");
}else{
console.log(xmlDom.documentElement.tagName);//root
console.log(xmlDom.documentElement.firstChild.tagName);//child
console.log(xmlDom.getElementsByTagName("child").length);//1
console.log(xmlDom.xml);//"<root><child/></root>"
}
}
};
xmlDom.load("example.xml");
跨浏览器处理XML
跨平台解析
function parseXML(xml){
var xmlDom=null;
if(typeof DOMParser != "undefined"){
xmlDom=(new DOMParser()).parseFromString(xml,"text/xml");
var errors=xmlDom.getElementsByTagName("parsererror");
if(errors.length){throw new Error("XML parsing error:"+error[0].textContent)};
}
else if(typeof ActiveXObject != "undfined"){
xmlDom=createDocument();
xmlDom.load(XML);
if(xmlDom.parseError!=0){
throw new Error("XML parsing error:"+"xmlDom.parseErroe,reason");
}
}
else{
throw new Error("No XML parser available")
}
return xmlDom
}
//用try-catch执行函数
var xmlDDom=null;
try{
xmlDom=parseXML("<root><child/></root>");
}catch(ex){
alert(ex.message);
}
跨平台序列化
function serializeXml(xmlDom){
if(typeof XMLSerializer != "undefined"){
return (new XMLSerializer()).serializeToString(xmlDom);
}else if(typeof xmlDom.xml != "undefined"){
return xmlDom.xml;
}else{
throw new Error("Could not serialize XML DOM");
}
}
//用try-catch执行函数
try{
var xml=serializeXml(xmlDom);
}
catch(ex){
alert(ex.massage);
}
小节概括
涉及函数
函数 | 作用 | 返回值 | 所属 |
---|---|---|---|
createDocument() | DOM2级创建XMLDOM对象 | XMLDOM | |
hasFeature() | 判断浏览器是否支持DOM2级 | Boolean | |
parseFromString() | 从字符串解析为XMLDOM | XMLDOM | |
serializeToString() | 把XMLDOM序列化问字符串 | String | |
ActiveXObject() | 创建ActiveX对象 | ActiveXObject | |
loadXML() | 读取XML字符串 |
涉及属性
属性 | 作用 | 类型 | 所属 |
---|---|---|---|
xml | 序列化字符串属性 | String | XMLDOM |
async | 异步属性 | Boolean | XMLDOM |
readyState | 异步状态 | Int | XMLDOM |
浏览器对XPath的支持
主流浏览器
DOM3级XPath
- DOM3级规范了定义在DOM中对XPath表达式的求值借口
判断是否支持DOM3级XPath
var supportsXPath=document.implementation.hasFeature("XPath,"3.0");
XPathEvaluator类型的三个方法
createExpression()
createNSResolver()
evaluate()
XPathResult类型里代表evaluate()返回类型的类型属性常数
- XPathResult.ANY_TYPE;自动匹配
- XPathResult.NUMBER_TYPE;
- XPathResult.STRING_TYPE;
- XPathResult.BOOLEAN_TYPE;
- XPathResult.UNORDERED_NODE_ITERATOR_TYPE;无序迭代器类型集合
- XPathResult.ORDERED_NODE_ITERATOR_TYPE;;有序迭代器类型集合
- XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE;无序快照类型集合
- XPathResult.ORDERED_NODE_SNAPSHOT_TYPE;有序快照类型集合
- XPathResult.ANY_UNORDERED_NODE_TYPE;返回匹配的无序节点集合
- XPathResult.FIRST_ORDERED_NODE_TYPE;返回第一个的节点集合
例子
ITERATOR_TYPE获取节点
- iterateNext()
var result=xmlDom.evaluate(
"employee/name",
xmlDom.documentElement,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE,
null);
if(result!==null){
var node=result.iterateNext();
while(node){
alert(node.tagName);
node=node.iterateNext();
}
}
SNAPSHOT_TYPE获取节点
- snapshotItem()
- snapshotLength()
var result=xmlDom.evaluate(
"employee/name",
xmlDom.documentElement,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null);
if(result!==null){
for(var i=0,len=result.snapshotLength;i<len;i++){
alert(result.snapshotItem(i).tagName);
}
}
FIREST_ONDERED_NODE_TYPE获取节点
var result=xmlDom.evaluate(
"employee/name",
xmlDom.documentElement,
null,
XPathResult.FIREST_ONDERED_NODE_TYPE,
null);
if(result!==null){
alert(result.singleNodeValue.tagName);
BOOLEAN_TYPE获取节点
- booleanValue
var result=xmlDom.evaluate(
"employee/name",
xmlDom.documentElement,
null,
XPathResult.BOOLEAN_TYPE,
null);
alert(result.booleanValue);
NUMBER_TYPE获取节点
- numberValue
var result=xmlDom.evaluate(
"count(employee/name)",
xmlDom.documentElement,
null,
XPathResult.NUMBER_TYPE,
null);
alert(result.numberValue);
STRING_TYPE获取节点
- stringValue
var result=xmlDom.evaluate(
"employee/name",
xmlDom.documentElement,
null,
XPathResult.STRING_TYPE,
null);
alter(result.stringValue);
ANY_TYPE获取节点
- resultType
var result=xmlDom.evaluate(
"employee/name",
xmlDom.documentElement,
null,
XPathResult.ANY_TYPE,
null);
if(result!==null){
switch(result.resultType){
case XPathResult.STRING_TYPE:
//expression
break;
case XPathResult.NUMBER_TYPE:
//expression
break;
case XPathResult.BOOLEAN_TYPE:
//expression
break;
case XPathResult.STRING_TYPE:
//expression
break;
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
//expression
break;
default:
//expression
}
}
命名空间支持
方法一 XPathNSResolver对象
通过createNSResolver()创建XPathNSResolver对象
var nsResolver=xmlDom.createNSResolver(xmlDom.documentElement);
var result=xmlDom.evaluate("wrox:book/wrox:author",
xmlDOm.documentElement,
nsResolver,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null);
alert(result.snapshotLength);
方法二 定义函数
定义一个函数,接受命名空间前缀,返回关联的URI
var nsResolver=function(prefix){
switch(prefix){
case "wrox":return "http://www.wrox.com/";
//其他前缀
}
};
var result=xmlDom.evaluate("count(wrox:book/wrox:author)",
xmlDOm.documentElement,
nsResolver,
XPathResult.NUMBER_TYPE,
null);
alert(result.numberValue);
IE浏览器
- IE对XPath的支持内置在基于ActiveX的XML DOM文档对象中
- 必须基于ActiveX实现
selectSingleNode()
获取匹配路径首个节点
var elements=xmlDom.documentElemnt.selectSingleNode("employee/name");
//没有匹配返回null
if(element!==null){
alert(element.xml);
}
selectNodes()
获取匹配路径节点集合
var elements=xmlDom.documentElemnt.selectNodes("employee/name");
//没有匹配返回零元素的NodeList类型
alert(elements.length);
IE对命名空间的支持
必须知道自己使用的命名空间
var str="xmlns:prefix1='uri1' xmlns:prefix2='uri2' xmlns:prefix3:'uri3'";
通过setProperty()设置命名空间
xmlDom.setProperty("SelectionNamespaces","xmlns:wrox='http://www.wrox.com/'");
var result=xmlDom.documentElement.selectNodes("wrox:book/wrox:author")
alert(result.length);
跨浏览器
创建selectSingleNode()
- nodeType
- ownerDocument
- singleNodeValue
var namespaces={prefix1:"uri1",prefix2:"uri2",prefix3:"uri3"};
function selectSingleNode(context,expression,namespaces){
var doc=(context.nodeType!=9?context.ownerDocument:context);
if(typeof doc.evaluate!="undefined"){
var nsResolver=null;
if(namespaces instanceof Object){
nsResolver=function(prefix){return namespaces[prefix];};
}
var result=doc.evaluate(expression,context,nsResolver,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
return (result!==null?result.singleNodeValue:null);
}else if(typeof context.selectSingleNode!="undefined"){
if(namespaces instanceof Object){
var ns="";
for(var prefix in namespaces){
if(namespaces.hasOwnProperty(prefix)){
ns+="xmlns:"+prefix+"='"+namespaces[prefix]+"' ";
}
}
doc.setProperty("SelectionNamespaces",ns);
}
return context.selectSingleNode(expression);
}else{
throw new Error("No XPath engine found.");
}
}
//使用
var result =selectSingleNode(
xmlDom.documentElement,
"wrox:book/wrox:autor",
{wrox:"http://www.wrox.com/"});
alert(serializeXml(result));
创建selectNodes()
function selectNodes(context,expression,namespaces){
var doc=(context.nodeType!=9?context.ownerDocument:context);
if(typeof doc.evaluate!="undefined"){
var nsResolver=null;
if(namespace instanceof Object){
nsResolver=function(prefix){return namespaces[prefix]};
}
var result=doc.evaluate(expression,context,nsResolver,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
var nodes=new Array();
if(result!==null){
for(var i=0,len=result.snapshotLength;i<len;i++){
nodes.push(result.snapshotItem(i));
}
}
return nodes;
}else if(typeof context.selectNodes!="undefined"){
if(namespaces instanceof Object){
var ns="";
for(var prefix in namespaces){
if(namespaces.hasOwnProperty(prefix)){
ns+="xmlns:"+prefix+"='"+namespaces[prefix]+"' ";
}
}
doc.setProperty("SelectiionNamespaces",ns);
}
var result=context.selectNodes(expression);
var nodes=new Array();
for(var i=0,len=result.length;i<len;i++){
nodes.push(result[i]);
}
return nodes;
}else{
throw new Error("no Xpath engine found");
}
}
//使用
var result =selectSingleNode(
xmlDom.documentElement,
"wrox:book/wrox:autor",
{wrox:"http://www.wrox.com/"});
alert(result.length);
涉及函数
函数 | 作用 | 返回值 | 所属 |
---|---|---|---|
tierateNext() | 返回下一个节点 | XPath | |
snapshotItem() | |||
selectNodes() | |||
selectSingleNode() |
涉及属性
属性 | 作用 | 类型 | 所属 |
---|---|---|---|
snapshotLength | |||
resultType | |||
nodeType | |||
ownerDocument | |||
singleNodeValue |
浏览器对XSLT的支持
- DOM中没有规范它的位置
- 靠浏览器开发商自己实现它
IE中的XSLT
- 把XML和XSLT加入到DOM文档中
transformNode()方法
xmlDom.load("employees.xml");
xsltDom.load("employees.xslt");
var result=xmlDom.transformNode(xsltDom);
XSLT转换可以再文档的任何级别上进行
result=xmlDom.documentElement.transformNode(xsltDom);
result=xmlDom.documentElement.childNodes[1].transformNode(xsltDom);
result=xmlDom.getElementsByTagName("name")[0].transformNode(xsltDom);
result=xmlDom.documentElement.firstChid.lastChid.transformNode(xsltDom);
复杂的XSLT转换
- 通过使用ActiveX对象MSXML2.FreeThreadedDOMDocument
- 速度更快
创建createThreadSafeDocument()
function createThreadSafeDocument(){
if(typeof arguments.callee.activeXString!="string"){
var versions=[
"MSXML2.FreeThreadedDOMDocument.6.0",
"MSXML2.FreeThreadedDOMDocument.3.0",
"MSXML2.FreeThreadedDOMDocument"],i,len;
for(i=0,len=versions.length;i<len;i++){
try{
new activeXObject(versions[i]);
arguments.callee.activeXString=versions[i];
break;
}catch(ex){}
}
}
return new activeXObject(arguments.callee.activeXString);
}
//使用
var xsltDom=createThreadSafeDocument();
xsltDom.async=false;
xsltDom.load("employee.xslt");
创建createThreadSafeDocument()
- [stylesheet]
- createProcessor()
- [input]
- [output]
- transform()
function createXSLTemplate(){
if(typeof arguments.callee.activeXString!="string"){
var versions=["MSXML2.XSLTemplate.6.0",
"MSXML2.XSLTemplate.3.0",
"MSXML2.XSLTemplate"],i,len;
for(i=0,len=versions.length;i<len;i++){
try{
new activeXObject(versions[i]);
arguments.callee.activeXString=versions[i];
break;
}catch(ex){}
}
}
return new activeXObject(arguments.callee.activeXString);
}
//使用
var template=createXSLTemplate();
template.stylesheet=xsltDom;
var processor=template.createProcessor();
processor.input=xmlDom;
processor.transform();
var result=processor.output;
用addParameter()设置message的值
processor.input=xsltDom.documentElement;
processor.addParameter("message","hello world!");
processor.transform();
用setStartMode()把模式设置为”title-first”
processor.input=xsltDom;
processor.addParameter("message","hello world!");
processor.setStartMode("title-first");
processor.transform();
用reset()重置
processor.reset();
主流浏览器
- 通过XSLTProcessor类型使用XSLT转换XML文档
加载两个DOM文档,基于XML和XSLT
- importStylesheet()指定一个XSLT
var processor=new XSLTProcessor();
processor.importStylrsheet(xsltDom);
文档转换
- transformToDocument()
var result=processor.transformToDocument(xmlDom);
alert(serializeXml(result));
var fragment=processor.transformToDocument(xmlDom,document);
var div=document.getElementById("divResult");
div.appendChild(fragment);
碎片转换
- transformToFragment()
var fragment=processor.transformToFragment(xmlDom,document);
var text=fragment.firstChild.nodeValue;
alert(text);
用setParameter()设置XSLT参数
var processor=new XSLTProcessor();
processor.importStylesheet(xsltDom);
processor.serParameter(null,"message","hello world");
var result=processor.transformToDocument(xmlDom);
getParameter()和removeParameter()
var processor=new XSLTProcessor();
processor.importStylesheet(xsltDom);
processor.serParameter(null,"message","hello world");
alert(processor.getParameter(null,"message"));
processor.removeParameter(null,"message");
var result=processor.transformToDocument(xmlDom);
用reset()重置
var processor=new XSLTProcessor();
processor.importStylesheet(xsltDom);
//执行转换
processor.reset();
processor.importStylesheet(xsltdom2);
跨浏览器使用XSLT
function transform(context,xslt){
if(typeof XSLTProcessor!="undefined"){
var processor=new XSLTProcessor();
processor.importStylesheet(xslt);
var result=processor.transformToDocument(context);
return (new XMLSerializer()).serializeToString(result);
}else if(typeof context.transformNode!="undefined"){
return context.transformNode(xslt);
}else{
throw new Error{"no XSLT processor available"};
}
}