javascript和XML

一,浏览器对XML DOM的支持
1,DOM2级核心
  var xmldom = document.implementation.createDocument("","root",null);(命名空间,元素标签,文档类型)
  var child = xmldom.createElement("child");
  xmldom.documentElement.appendChild(child);
  检测浏览器支持情况
  var hasXmlDom = document.implementation.hasFeature("XML","2.0")
2,DOMParser类型
  解析XML之前,创建一个DOMParser类型,调用parserFormString(要解析的XML字符串,内容类型text/xml)方法
  解析发生错误时,parseFromString()返回一个document对象,这个对象的文档元素是<parsererror>

var parser = new DOMParser(),xmldom,errors;
try{
  xmldom = parser.parseFormString("<root>","text/xml");
  errors = xmldom.getElementsByTagName("parsererror");
  if(errors.length > 0){
    throw new Error("Parsing errot!");
  }
}catch(ex){
  alert("Parsing error!");
}

3,XMLSerializer类型
  XMLSerializer类型,将DOM文档序列化为XML字符串
  首先创建一个XMLSerializer实例,然后将文档传人其serializerToString()方法
  var serializer = new XMLSerializer();
  var xml = serializer.serializerToString(xmldom);
4,IE8及之前版本中的XML、
  IE是第一个支持XML的浏览器,通过ActiveX对象实现
  为了便于桌面应用程序开发人员处理XML,微软创建了MSXML库
  ActiveXObject类型,可以通过它创建ActiveX对象的实例,要创建一个XML文档的类型,要使用ActiveXObject构造函数,传人一个表示XML文档版本的字符串
  有六种不同的XML文档版本可以供选择
    Microsoft.XmlDom:最初随同IE发布,不建议使用
    MSXML2.DOMDocument:为方便脚本处理更新的版本,建议在特殊情况下作为后备版本
    MSXML2.DOMDocument.3.0:在Javascript中使用,是最低的建议版本
    MSXML2.DOMDocument.4.0:通过脚本处理时不可靠,可能导致安全警告
    MSXML2.DOMDocument.5.0:通过脚本处理时不可靠,可能导致安全警告
    MSXML2.DOMDocument.6.0:通过脚本能够可靠处理的最新版本

    function createDocument(){
      if(typeof argument.callee.activeXString != "String"){
        var versions = ["MSXML2.DOMDocument.6.0","MSXML2.DOMDocument.3.0","MSXML2.DOMDocument"],i,len;
        for(i=0,len=versions.length;i<len;i++){
          try{
            new ActiveXObject(versions[i]);
            argument.callee.activeXString = versions[i];
          }catch(ex){
            //跳过
          }
        }
      }  
      return new ActiveXObject(argument.callee.activeXString);
  }  

  要解析XML字符串,首先创建一个DOM文档,然后调用loadXML()方法,新创建的XML文档为空,不能操作,
  为loadXML()方法传人XML字符串解析之后会被填充到DOM文档中,
  var xmldom = createDocument();
  xmldom.loadXML("<root><child /></root>");
  如果解析过程出错,在parseError属性中找到错误消息,属性本身包含多个属性对象,如下
    errorCode:错误类型的数值编码,没有错误时为0,值可以为正负
    filePos:文件中导致错误发生的位置
    line:发生错误的行
    linepos:发生错误的行中的字符
    reason:对错误的文本解释
    srcText:导致错误的代码
    url:导致错误的文件的URL
    parseError的valueOf()返回errorCode的值
  在调用loadXML()之后,查询XML文档之前,检测是否发生了错误
1,序列化XML
  每个DOM节点都有一个xml属性,保存着表示该节点的XML字符串
2,加载XML文件
  IE中的XML文档对象也可以加载来自服务器的文件,指定加载文档的方式,asyns属性,true表示异步加载,false表示同步加载
  var xmldom = createDocument();
  xmldom.async = false;
  加载了XML文档之后,调用load()可以启动下载过程,接收一个参数即要加载的XML文件的URL,同步方式下,调用load后立即检测解析错误并执行相关XML处理
  var xmldoe = createDocument();
  xmldom.async = false;
  xmldom.load("example.xml");
  if(xmldom.parseError != 0){
    //处理错误
  }else{
    //处理xml外部文档
  }
  异步加载XML文件情况下,为XML DOM文档的onreadystatechange事件指定处理程序,4个就绪状态
    1,DOM正在加载数据,2DOM已经加载完数据,3DOM可以使用,但某些部分还无法访问,4DOM完全可以使用

  var xmldom = createDocument();
  xmldom.asyns = true;
  xmldom.onreadystatechange = function(){
    if(xmldom.readyState == 4){
      if(xmldom.parseError != 0 ){
        //处理xmldom文档中错误
      }else{
        //处理xmldom文档
      }
    }  
  };
  xmldom.onload("example.xml");

5,跨浏览器处理XML
  解析XML而言

  function parseXml(xml){
    var xmldom = null;
    if(typeof DOMParser != "undefined"){
      xmldom = (new DOMParser()).parseFormString(xml,"text/xml");
      var errors = xmldom.getElementsByTagName("parsererror");
      if(errors.length){
        throw new Error("XML parseing error:" + errors[0].textContent);
      }
    }else if(typeof ActiveXObject != "undefined"){
      xmldom = createDocument();
      xmldom.loadXML(xml);
      if(xmldom.parseError !=0 ){
        throw new Error("XML parsing error:" + xmldom.parseError.reason);
      }
    }else{
      throw new Error("No xml parser available");
    }
    return xmldom;
  }

  使用函数解析XML字符串时,放在try-catch语句中,以防发生错误

  var xmldom = null;
  try{
    xmldom = parseXML("<root><child/></root>");
  }catch(ex){
    alert(ex.message);
  }

  对于序列化XML而言,

  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.");
    }
  }

二,浏览器对XPath的支持
1,DOM3级XPath
  XPath是设计用来在DOM文档中查找节点的一种手段
  DOM3定义了在DOM中对XPath表达式求值的接口
  var supportsXPath = document.implementation.hasFeature("XPath","3.0");
  XPathEvaluator类型,用于特定的上下文中对XPath表达式求值,有3个方法
    createExpression(expression,nsresolver)将XPath表达式及相应的命名空间信息转换成一个XPathExpression,多次使用同一个查询时有用
    createNSResolver(node),根据node的命名空间信息创建一个新的XPathNSResolver对象,基于使用命名空间XML文档求值时,需要使用                 XPathNSResolver对象
    evaluate(expression,context,nsresolver,type,result),给定的上下文中,基于特定的命名空间信息对XPath表达式求值,剩下的参数指定如何返回结果
    expression为XPath表达式,contenxt为上下文节点,nsresolver为命名空间求解器只在XML代码中使用了XML命名空间时有必要指定,没有命名空间          时指定为null,type为结果类型取值如下
      XPathResult.ANY_TYPE:返回与XPath表达式匹配的数据类型
      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:返回只包含一个节点的节点集合,包含的这个节点就是文档中第一个匹配的节点

  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();
    }
  }

  返回结果为XPathResult.ORDERED_NODE_ITERATOR_TYPE,是常用的返回类型,没有节点匹配XPath表达式,返回null,否则返回XPathResult对象
  返回的XPathResult对象带有属性和方法,如果节点时节点迭代器与次序无关,要使用iterateNext()从节点中取得匹配的节点,没有更多的匹配节点时,返回null
  如果指定的快照结果类型,使用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);
    }
  }
  1)单节点结果
  指定常量XPathResult.FIRST_ORDERED_NODE_TYPE:返回匹配的第一个节点
  通过singleNodeValue属性来访问该节点
  var result = xmldom.evaluate("employee/name",xmldom.documentElement,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
  if(result != null){
    alert(result.singliNodeValue.tagName);
  }
  2)简单类型结果
  通过XPathResult的布尔值,数值,和字符串值可以取得简单的非节点的数据类型
  对于XPathResult.BOOLEAN_TYPE,有返回值为true,无返回值为false
  对于XPathResult.NUMBER_TYPE,必须在XPath表达式参数的位置上指定一个能够返回数值的XPath函数,没有匹配返回NaN
    var Result = xmldom.evaluate("count(employee/name)",xmldom.documentElement,null,XPathResult.NUMBER_TYPE,null);
  对于字符串类型,查找与XPath表达式匹配的第一个节点,返回第一个子节点的值,没有匹配返回空字符串
  3)默认类型结果
  使用XPathResult.ANY_TYPE会自动返回结果的类型,确定返回的是什么结果,通过检测resultType属性
  4)命名空间支持
  对于利用了命名空间的XML,XPathEvaluator必须知道命名空间的信息
  处理命名空间的一种方法是通过createNSResolver()创建XPathNSResolver对象,接收一个参数就是包含命名空间定义的节点,传人到evaluate方法中
  处理命名空间的另一种方法是定义一个函数,让它接收一个命名空间前缀,返回关联的URL
  var nsresolver = function(prefix){
    switch(prefix){
      case "wrox":return "http://www.wrox.com/"
    }
  };
  传人evaluate方法中
2,IE中的XPath
  IE对XPath的支持是内置在基于ActiveX的XMLDOM文档对象中的,没有使用DOMParser返回的DOM对象
  使用XPath必须基于ActiveX的实现,这个接口在每个节点上额外定义了两个方法
  selectSingleNode(),接受一个XPath模式,在找到匹配节点时返回第一个匹配的节点,没有匹配返回null
  selectNodes(),接受一个XPath模式,返回与模式匹配的所有节点的NodeList,没有匹配,返回包含零项的NodeList
  IE中处理包含命名空间的XPath表达式,必须知道自己使用的命名空间,按照下列格式创建一个字符串
    "xmlns:prefix1='uri1' xmlns='uri2' xmlns='uri3'"
  将这个字符串传人到XMLDOM文档对象的特殊方法setProperty(属性名,属性值)中,属性名为SelectionNamespaces,属性值就是按照前面格式创建的字符串
    xmldom.setProperty("SelectionNamespaces","xmlns:wrox='http://www.wrox.com/'");
    var result = xmldom.documentElement.selectNodes("wrox:book/www:author");
3,跨浏览器使用XPath
  selectSingleNode(上下文节点,XPath表达式,命名空间对象)

  function selectSingNode(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.hasOwnerProperty(prefix)){
            ns += "xmlns:" + prefix + "= '" + namespaces[prefix] + "' ";
          }
        }
        doc.serProperty("SelectionNamespaces",ns);
      }
      return context.selectSingleNode(expression);
    }else{
      throw new Error("No XPath engine found.");
    }
  }

  selectNodes()函数,

  function selectNodes(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.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 namespace){
          if(namespace.hasOwnProperty(prefix)){
            ns += "xmlns:" + prefix + "=' + namespaces[prefix] + '" ";
          }
        }
        doc.serProperty("SelectionNamespaces",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.");
    }
  }

三,浏览器对XSLT的支持
1,IE中的XSLT
  1)简单的XSLT转换
  使用XSLT样式表转化XML文档的最简单的方法,是将他们分别放在一个DOM文档中,然后使用transformNode()方法
  这个方法存在于所有节点中,接收一个参数,包含XSLT样式表的文档,返回一个包含转换信息的字符串
  xmldom.load("employees.xml");
  xsltdom.load("employees.xslt");
  var result = xmldom.transformNode(xsltdom);
  可以在文档的任何级别上进行转换
  2)复杂的XSLT转换
  使用XSL模板和XML处理器,第一步是把XSLT样式表加载到一个线程安全的XML文档中,通过使用ActiveX对象MSXML2.FreeThreadedDOMDocument来做
  创建线程安全的XML DOM,即ActiveX对象,与常规的DOM支持相同的接口

  function createThreadSafeDocument(){
    if(typeof argument.callee.activeXString != "string"){
      var verions = ["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]);
          argument.callee.activeXString = versions[i];
          break;
        }catch(ex){
          //跳过
        }
      }
    }
    return new ActiveXObject(arguments.callee.activeXString);
  }
  var xsltdom = createThreadSafeDocument();
  xsltdom.async = false;
  xsltdom.load("employee.xslt");

  创建并加载了自由线程的DOM之后,必须将它指定给一个XSL模板,这也是一个ActiveX对象,这个模板用来创建XSL处理对象的,后者用来转换XML文档

  function createXSLTemplate(){
    if(typeof argument.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]);
          argument.callee.activeXString = version[i];
          break;
        }catch(ex){
        //跳过
        }
      }
    }
    return new ActiveXObject(arguments.callee.activeXString);
  }
  var template = createXSLTemplate();
  template.stylesheet = xsltdom;
  var proccessor = template.createProcessor();
  processor.input = xmldom;
  processor.transform();
  var result = processor.output;

  transform方法可执行转换并将结果作为字符串保存在output属性中
  XSLT样式表可以接受传人的参数,并将其用作局部变量
  processor.input = xmldom.documentElement;
  processor.addParameter("message","hello");
  processor.transform();
  XSL处理器能够设置一种操作模式,可是使用mode特性为模板定义一种模式,
  processor.input = xmldom;
  processor.addParameter("message","hellp");
  processor.setStartMode("title-first");
  processor.transform();
  如果打算使用同一样式表进行多次转换,可以在转换之后重置处理器,调用reset()方法
  会清除原先的输入和输出属性,启动模式以及其他指定的参数,
2,XSLTProcessor类型
  可以通过XSLTProcessor类型,使用XSLT转换XML文档
  与IE类似,第一步加载两个DOM文档,一个基于XML,一个基于XSLT,然后创建XSLTProcessor对象,
  指定importStyleSheet()方法为其指定一个XSLT,
  var processor = new XSLTProcessor();
  processpr.importStyleSheet(xsltdom);
  最后一步执行转换,想返回完整的DOM文档,使用transformToDocument(),想返回一个文档对象片段,使用transformToFragment(),将返回的结果添加     到另一个DOM文档中
  XSLT样式表在输出格式为XML或HTML时,没有问题,当格式为text时,浏览器支持情况不同,这时使用transformToFragment()
  var fragment = processpr.transformToFragment(xmldom,document);
  var text = fragment.firstChild.nodeValue;
  alert(text);
  1)使用参数
  XSLTProcessor类型通过serParameter()设置XSLT的参数,命名空间URL,参数内部名称,要设置的值
  要在调用transformToDocument(),transformToFragment()之前调用
  var processor = new XSLTProcessor();
  processor.importStyleSheet(xsltdom);
  processor.setParameter(null,"message",null);
  var result = processor.transformToDocument(xmldom);
  getParameter()取得当前参数的值,(命名空间(一般为null),参数的名称)
  removeParameter()移除当前参数的值(命名空间(一般为null),参数的名称)
  2)重置处理器
  processor.reset()
  移除所有参数和样式,可以再次调用importStyleSheet()
3,跨浏览器使用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");
    }
  }
  var result = transform(xmldom,xsltdom);

posted on 2014-04-11 21:45  哈哈李小博  阅读(211)  评论(0编辑  收藏  举报