《Javascript 高级程序设计(第三版)》笔记0x1F JavaScript 与 XML

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

目录

浏览器对 XML DOM 的支持

    DOM2 级核心

    DOMParser类型

    XMLSerializer类型

    IE8 及之前版本中的XML

        序列化 XML

        加载 XML 文件

    跨浏览器处理XML

浏览器对 XPath 的支持

    DOM3 级XPath

        单节点结果

        简单类型结果

        默认类型结果

        命名空间支持

    IE中的XPath

        IE 对命名空间的支持

    跨浏览器使用XPath

 浏览器对 XSLT 的支持

    IE中的XSLT

        简单的 XSLT 转换

        复杂的 XSLT 转换

    XSLTProcessor类型

    跨浏览器使用XSLT


浏览器对 XML DOM 的支持

    DOM2 级核心

//检测浏览器是否支持 DOM2 级 XML
var hasXmlDom = document.implementation.hasFeature("XML", "2.0");
//创建一个新的、文档元素为<root>的 XML 文档
var xmldom = document.implementation.createDocument("", "root", null);
alert(xmldom.documentElement.tagName); //"root"
var child = xmldom.createElement("child");
xmldom.documentElement.appendChild(child);

    DOMParser类型

    将XML解析为DOM文档,在解析XML之前,先必须创建一个DOMParser的实例,再调用parseFromString()方法。这个方法接受两个参数:要解析的XML字符串和内容类型(内容类型始终都应该是"text/xml")。返回的值是一个Document的实例。

var parser = new DOMParser();
var xmldom = parser.parseFromString("<root><child/></root>", "text/xml");
alert(xmldom.documentElement.tagName); //"root"
alert(xmldom.documentElement.firstChild.tagName); //"child"
var anotherChild = xmldom.createElement("child");
xmldom.documentElement.appendChild(anotherChild);
var children = xmldom.getElementsByTagName("child");
alert(children.length); //2

    XMLSerializer类型

    将 DOM 文档序列化为 XML 字符串。要序列化 DOM 文档,首先必须创建 XMLSerializer 的实例,然后将文档传入其 serializeToString ()方法,该方法返回的字符串并不适合打印,因此看起来会显得乱糟糟的。

var serializer = new XMLSerializer();
var xml = serializer.serializeToString(xmldom);
alert(xml)

    IE8 及之前版本中的XML

    IE 是第一个原生支持 XML 的浏览器,而这一支持是通过 ActiveX 对象实现的。要创建一个 XML 文档的实例,也要使用ActiveXObject 构造函数并为其传入一个表示XML 文档版本的字符串。

//尝试创建每个版本的实例并观察是否有错误发生,可以确定哪个版本可用
function createDocument(){
	if (typeof arguments.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]);
				arguments.callee.activeXString = versions[i];
				break;
			} catch (ex){
				//跳过
			}
		}
	}
	return new ActiveXObject(arguments.callee.activeXString);
}

    要解析 XML 字符串,首先必须创建一个 DOM 文档,然后调用 loadXML()方法。新创建的 XML文档完全是一个空文档,因而不能对其执行任何操作。为 loadXML()方法传入的 XML 字符串经解析之后会被填充到 DOM 文档中。

var xmldom = createDocument();
xmldom.loadXML("<root><child/></root>");
alert(xmldom.documentElement.tagName); //"root"
alert(xmldom.documentElement.firstChild.tagName); //"child"
var anotherChild = xmldom.createElement("child");
xmldom.documentElement.appendChild(anotherChild);
var children = xmldom.getElementsByTagName("child");
alert(children.length); //2

        序列化 XML

    IE 将序列化 XML 的能力内置在了 DOM 文档中。每个 DOM 节点都有一个 xml 属性,其中保存着表示该节点的 XML 字符串。

        加载 XML 文件

    与 DOM3 级中的功能类似,要加载的 XML文档必须与页面中运行的 JavaScript 代码来自同一台服务器。同样与 DOM3 级规范类似,加载文档的方式也可以分为同步和异步两种。要指定加载文档的方式,可以设置 async 属性, true 表示异步, false表示同步(默认值为 true)。 

var xmldom = createDocument();
xmldom.async = false;
xmldom.load("example.xml");
if (xmldom.parseError != 0){
	//处理错误
} else {
	alert(xmldom.documentElement.tagName); //"root"
	alert(xmldom.documentElement.firstChild.tagName); //"child"
	var anotherChild = xmldom.createElement("child");
	xmldom.documentElement.appendChild(anotherChild);
	var children = xmldom.getElementsByTagName("child");
	alert(children.length); //2
	alert(xmldom.xml);
}

    由于是以同步方式处理 XML 文件,因此在解析完成之前,代码不会继续执行,这样的编程工作要简单一点。虽然同步方式比较方便,但如果下载时间太长,会导致程序反应很慢。因此,在加载 XML文档时,通常都使用异步方式。

var xmldom = createDocument();
xmldom.async = true;
xmldom.onreadystatechange = 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 {
			alert(xmldom.documentElement.tagName); //"root"
			alert(xmldom.documentElement.firstChild.tagName); //"child"
			var anotherChild = xmldom.createElement("child");
			xmldom.documentElement.appendChild(anotherChild);
			var children = xmldom.getElementsByTagName("child");
			alert(children.length); //2
			alert(xmldom.xml);
		}
	}
};
xmldom.load("example.xml");

    跨浏览器处理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:" + 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
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 的支持

    DOM3 级XPath

        单节点结果

//指定常量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.singleNodeValue.tagName);
}
DomXPathExample03.ht

        简单类型结果

//如果有节点匹配"employee/name",则 booleanValue 属性的值就是 true
var result = xmldom.evaluate("employee/name", xmldom.documentElement, null,XPathResult.BOOLEAN_TYPE, null);
alert(result.booleanValue);

//计算与给定模式匹配的所有节点数量的 count()
var result = xmldom.evaluate("count(employee/name)", xmldom.documentElement,null, XPathResult.NUMBER_TYPE, null);
alert(result.numberValue);

//对于字符串类型,evaluate()方法会查找与 XPath 表达式匹配的第一个节点,然后返回其第一个子节点的值
var result = xmldom.evaluate("employee/name", xmldom.documentElement, null,XPathResult.STRING_TYPE, null);
alert(result.stringValue);

        默认类型结果

var result = xmldom.evaluate("employee/name", xmldom.documentElement, null,XPathResult.ANY_TYPE, null);
if (result !== null) {
	switch(result.resultType) {
		case XPathResult.STRING_TYPE:
			//处理字符串类型
			break;
		case XPathResult.NUMBER_TYPE:
			//处理数值类型
			break;
		case XPathResult.BOOLEAN_TYPE:
			//处理布尔值类型
			break;
		case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
			//处理次序不一致的节点迭代器类型
			break;
		default:
			//处理其他可能的结果类型
	}
}

        命名空间支持

    对于利用了命名空间的 XML 文档, XPathEvaluator 必须知道命名空间信息,然后才能正确地进行求值。

<?xml version="1.0" ?>
<wrox:books xmlns:wrox="http://www.wrox.com/">
	<wrox:book>
		<wrox:title>Professional JavaScript for Web Developers</wrox:title>
		<wrox:author>Nicholas C. Zakas</wrox:author>
	</wrox:book>
	<wrox:book>
		<wrox:title>Professional Ajax</wrox:title>
		<wrox:author>Nicholas C. Zakas</wrox:author>
		<wrox:author>Jeremy McPeak</wrox:author>
		<wrox:author>Joe Fawcett</wrox:author>
	</wrox:book>
</wrox:books>
//通过 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中的XPath

    在 IE9 及之前的版本中使用 XPath,必须使用基于 ActiveX 的实现。这个接口在每个节点上额外定义了两个的方法: selectSingleNode()和 selectNodes()。其中,selectSingleNode()方法接受一个 XPath 模式,在找到匹配节点时返回第一个匹配的节点,如果没有找到匹配的节点就返回 null。

var element = xmldom.documentElement.selectSingleNode("employee/name");
if (element !== null){
  alert(element.xml);
}

var elements = xmldom.documentElement.selectNodes("employee/name");
alert(elements.length);

        IE 对命名空间的支持

//要在 IE 中处理包含命名空间的 XPath 表达式,你必须知道自己使用的命名空间,并按照下列格式创建一个字符串
//"xmlns:prefix1='uri1' xmlns:prefix2='uri2' xmlns:prefix3='uri3'"
xmldom.setProperty("SelectionNamespaces", "xmlns:wrox=’http://www.wrox.com/’");
var result = xmldom.documentElement.selectNodes("wrox:book/wrox:author");
alert(result.length);

    跨浏览器使用XPath

   selectSingleNode(),它接收三个参数:上下文节点、 XPath表达式和可选的命名空间对象

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:author",{ wrox: "http://www.wrox.com/" });
alert(serializeXml(result));

    selectNodes()函数接收与 selectSingleNode()相同的三个参数,而且大部分逻辑都相似。

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

var result = selectNodes(xmldom.documentElement, "wrox:book/wrox:author",{ wrox: "http://www.wrox.com/" });
alert(result.length);

 浏览器对 XSLT 的支持

    XSLT 是与 XML 相关的一种技术,它利用 XPath 将文档从一种表现形式转换成另一种表现形式。与XML 和 XPath 不同, XSLT 没有正式的 API,在正式的 DOM 规范中也没有它的位置。结果,只能依靠浏览器开发商以自己的方式来实现它。 IE 是第一个支持通过 JavaScript 处理 XSLT 的浏览器。

    IE中的XSLT

        简单的 XSLT 转换

result = xmldom.documentElement.transformNode(xsltdom);
result = xmldom.documentElement.childNodes[1].transformNode(xsltdom);
result = xmldom.getElementsByTagName("name")[0].transformNode(xsltdom);
result = xmldom.documentElement.firstChild.lastChild.transformNode(xsltdom);

        复杂的 XSLT 转换

    虽然 transformNode()方法提供了基本的 XSLT 转换能力,但还有使用这种语言的更复杂的方式。为此,必须要使用 XSL 模板和 XSL 处理器。

    XSLTProcessor类型

    开发人员可以通过XSLTProcessor 类型使用 XSLT 转换 XML 文档,其方式与在 IE 中使用 XSL 处理器类似。因为这个类型是率先出现的,所以 Chrome、 Safari 和 Opera 都借鉴了相同的实现,最终使 XSLTProcessor 成为了通过 JavaScript 进行 XSLT 转换的事实标准。

    跨浏览器使用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/funkstill/article/details/85090172