javaScript_XML(XPath,XSLT)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_39532362/article/details/77189015

浏览器对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);
}

小节概括

行为 DOM2级 IE
创建 -document.implementation.createDocument() -new ActiveXObject(versionXML)
加载(解析) -(new DOMParser()).parseFromString() -loadXML()
序列化 -(new XMLSerializer()).serializeToString() -序列化字符串保存于每个节点的[xml]属性
错误 -返回的DOM对象包含元素 -错误信息保存于[parseError]属性
异步 -设置[async]属性
事件 -根据就绪状态state指定触发事件程序onreadystatechange

涉及函数

函数 作用 返回值 所属
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"};
    }
}

目录

猜你喜欢

转载自blog.csdn.net/weixin_39532362/article/details/77189015