判断是否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 } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .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 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义