Ruby's Louvre

每天学习一点点算法

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

判断是否XML文档

xhtml的昙花一现带来不少问题,它的目的是让html表现得更像xml,所以才叫xhtml。但是出师未捷身先死,我们讨论一下如何判定文档是XML吧。

印象中jQuery对此方法重复实现了许多次,应该比较权威,也说明这判定比较难搞。看jQuery1.42的实现:

var isXML = function(elem){
       // documentElement is verified for cases where it doesn't yet exist
       // (such as loading iframes in IE - #4833)
       var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
       return documentElement ? documentElement.nodeName !== "HTML" : false;
   };

好,做一个实验:

window.onload = function(){
      try{
        var doc = document.implementation.createDocument(null, 'HTML', null);//只限标准浏览器,创建一个XML文档
        alert(doc.documentElement)
        alert(isXML(doc))//应该返回true
      }catch(e){
        alert("不支持creatDocument方法")
      }
  }

另一个实验:

评测结果,它能判定XHTML文档,但无法判定第一个元素为HTML的XML文档。

看来我们需要一些更可靠的特征侦探。我们知道IE的HTML不支持xpath,而XML支持,这个可以利用。对于标准浏览器,参见我另一篇博文《javascript 跨文档调用技术》提到的一系列方法。既然有createHTMLDocument,应该拥有HTMLDocument这个对象,标准浏览器向来比较慷慨,暴露了许多比较底层的方法供我们扩展,如__proto__, Node,Window, Element, HTMLElement什么的。测试一下,真的有这东西

在火狐官网还看到这样一个判定,这是基于XUL的,仅对火狐有效。

//https://developer.mozilla.org/En/XML/Identifying_XML_elements_and_documents
function isXMLDoc (doc) {
    var Ci = Components.interfaces;
    // Remove the second condition if only wish to test for XML, not XUL
    return (doc instanceof Ci.nsIDOMXMLDocument)||
           (doc instanceof Ci.nsIDOMXULDocument);
}

不管怎么样,既然获知HTMLDocument这个类,就简单了。下面是我的实现:

var isXML = (function(){
  if(-[1,]){
    return function(doc){
      return  !(doc instanceof HTMLDocument)
    }
  }else{
    return function(doc){
      return "selectNodes" in doc
    }
  }
})();

下面是测试代码:

var createXML = function (str) {
  if (typeof DOMParser !== "undefined") {
    return (new DOMParser()).parseFromString(str, "application/xml");
  }else if (ActiveXObject) {
    var xml = new ActiveXObject("Microsoft.XMLDOM");
    xml.async="false";
    xml.loadXML(str);
    return xml
  }
}
 
window.onload = function(){
  var xml = createXML('<HTML><body><book><title>司徒正美</title></book></body></HTML>');  
  alert(isXML(xml))
}

可能有人会问,为什么不用XMLDocumet?好问题,因为XMLDocumet在opera中支持得比较晚。大抵是opera9.6才支持,这是我以前在日本博客看到的数据。不过opera是个小众的浏览器,你大可以不管它比较旧的版本,而直接用XMLDocument。

补充一下,我以前是使用以下判定的,一样可行,但是要创建两个元素对象。在IE7中,没有加入DOM树的元素节点不会被回收,需要特殊处理一下,比较麻烦,遂放弃之。

var isXML =  function (doc) {
     return doc.createElement("p").nodeName !== doc.createElement("P").nodeName;
   };
     // Safari 2 missing document.compatMode property
// makes harder to detect Quirks vs. Strict mode
var isQuirks =
  function(document) {
    return (document.compatMode ?
      (document.compatMode.indexOf('CSS') < 0) :
      (function() {
        var div = document.createElement('div'),
          isStrict = div.style &&
            (div.style.width = 1) &&
            div.style.width != '1px';
        div = null;
        return !isStrict;
      })());
  },
 
// XML is functional in W3C browsers
isXML = 'xmlVersion' in doc ?
  function(document) {
    return !!document.xmlVersion ||
      (/xml$/).test(document.contentType) ||
      !(/html/i).test(document.documentElement.nodeName);
  } :
  function(document) {
    return document.firstChild.nodeType == 7 &&
      (/xml/i).test(document.firstChild.nodeName) ||
      !(/html/i).test(document.documentElement.nodeName);
  };
 
// reset and reused dynamically for each selection
isQuirksMode = isQuirks(doc),
 
// reset and reused dynamically for each selection
isXMLDocument = isXML(doc),
function isXML(context) {
      context = context.ownerDocument || document;
      return context.createElement("p").nodeName !== context.createElement("P").nodeName
    }

如果您觉得此文有帮助,可以打赏点钱给我支付宝1669866773@qq.com ,或扫描二维码

posted on   司徒正美  阅读(3253)  评论(1编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示