欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript高級(jí)程序設(shè)計(jì) XML、Ajax 學(xué)習(xí)筆記

 更新時(shí)間:2011年09月10日 02:39:39   作者:  
JavaScript高級(jí)程序設(shè)計(jì) XML、Ajax 學(xué)習(xí)筆記,需要的朋友可以參考下。

第十五章 JavaScript與XML

1.瀏覽器對(duì)XML DOM的支持

1.1 DOM2級(jí)核心

①在DOM2級(jí)在document.implementation中引入了createDocument()方法(IE6~8不支持)。

可以創(chuàng)建一個(gè)空白XML。

var xmldom = document.implemention.createDocument(namespaceUri,root,docype);

②要?jiǎng)?chuàng)建一個(gè)新的文檔元素為<root>的XML文檔,可用如下代碼:

var xmldom = document.implementation.createDocument("","root",null);

aert(xmldom.documentElement.tagName);  //"root"

var child = xmldom.createElement("child");

xmldom.documentElement.appendChild(child);

③檢測(cè)瀏覽器是否支持DOM2級(jí)XML:

var hasXmlDom = document.implementation.hasFeature("XML","2.0");

1.2 DOMParse類型

①Firefox、Opera、Chrome、Safari支持(IE8不支持),DOMParse類型可將XML解析為DOM文檔。

②創(chuàng)建一個(gè)DOMParse實(shí)例,再調(diào)用parseFromString()方法。這個(gè)方法接受兩個(gè)參數(shù):要解析的XML字符串和內(nèi)容類型(內(nèi)容類型始終為"text/xml")。返回值是一個(gè)Document實(shí)例。

var parser = new DOMParse();

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

var children = xmldom.getElementsByTagName("child");

alert(children.length);  //2

③發(fā)生解析錯(cuò)誤時(shí),仍然會(huì)從parseFromString()中返回一個(gè)Document對(duì)象。但這個(gè)對(duì)象的文檔元素是<parsererror>(Firefox、Opera);對(duì)象根元素第一個(gè)子元素為<parsererro>(Safari、Chrome)。

<parseerror>元素的內(nèi)容是對(duì)解析錯(cuò)誤地描述。通過getElementsByTagName()查找<parsererror>確定是否有解析錯(cuò)誤。

var parse = new DOMParse();

var xmldom = parser.parseFromString("<root>","text/xml");

var errors = xmldom.getElementsByTagName("parsererror");

if(errors.length > 0 ){

alert("Parsing error!");

}

1.3 XMLSerializer類型

①此類可將DOM文檔序列化為XML字符串。(IE6~8不支持)。

②要序列化DOM文檔,首相必須創(chuàng)建XMLSerializer實(shí)例,然后將文檔傳入其serializerToString()方法:

var serializer = new XMLSerializer();

var xml = serializer.serializeToString(xmldom);

alert(xml);

1.4 DOM3級(jí)加載和保存

①DOM3級(jí)“加載和保存”規(guī)范的目的在于將加載、解析和序列化XML文檔的任務(wù)標(biāo)準(zhǔn)化,模塊規(guī)定了兩個(gè)解析方法:同步方法和異步方法。

②檢測(cè)DOM3級(jí)加載和保存

var hasLSSync = document.implementation.hasFeature("LS","3.0");

var hasLSAsync = document.implementation.hasFeature("LS-Async","3.0");

③DOM3級(jí)“加載和保存”還為document.implementation對(duì)象添加了下列新屬性和新方法:

□MODE_SYNCHRONOUS:為同步解析方式定義的常量;

□MODE_ASYNCHRONOUS:為異步解析方式定義的常量;

□createLSParse(mode,schemaType):創(chuàng)建一個(gè)在指定方式(mode)下運(yùn)行且符合指定模式(schema)類型的解析器。

□createLSSerializer():創(chuàng)建一個(gè)新XML序列化器。

□createLSInput():創(chuàng)建一個(gè)新的輸入對(duì)象,用于解析/序列化操作。

□createLSOutput():創(chuàng)建一個(gè)新的輸出對(duì)象,用于解析/序列化操作。

1.4.1 解析XML

(1)同步解析器

①需要先創(chuàng)建同步解析器。如果解析器并不想基于哪個(gè)模式進(jìn)行驗(yàn)證,為createLSParser()的第二個(gè)參數(shù)傳入null。如果需要基于XML模式進(jìn)行驗(yàn)證,則應(yīng)為第二個(gè)參數(shù)傳入"http://www.w3.org/2001/XMLSchema",如果要基于XML DTD進(jìn)行驗(yàn)證,則應(yīng)該為第二個(gè)參數(shù)傳入"http://www.w3.org/TR/REC-xml"。

②解析之前還要?jiǎng)?chuàng)建一個(gè)新的LSInput對(duì)象。為此,要使用createLSInput()方法;創(chuàng)建LSInput對(duì)象后,還需要將XML字符串賦值給該對(duì)象的stringData屬性。

③解析完成后,就會(huì)返回一個(gè)XML DOM文檔對(duì)象

④如果在同步解析方式下發(fā)生解析錯(cuò)誤,則會(huì)拋出錯(cuò)誤。

⑤示例:

var implementation = document.implementation;

var parser = implementation.createLSParser(implementation.MODE_SYNCHRONOUS,null);

var input = implement.createLSInput();

input.stirngData = "<root>";

try{

xmldom = parser.parse(input);

}catch(ex){

alert("Parsing error!");

}

(2)異步解析器

①需要在createLSParser()的第一個(gè)參數(shù)的位置上傳入常量MODE_ASYNCHRONOUS。

②通過addEventListener()來預(yù)訂load事件,以便知道文檔何時(shí)解析完畢。

③如果異步解析期間發(fā)生錯(cuò)誤,則不會(huì)觸發(fā)load事件。要捕獲這個(gè)錯(cuò)誤,需要使用LSParser對(duì)象上一個(gè)名叫domConfig的特殊接口定義一個(gè)錯(cuò)誤處理程序。(BUG:Opera9.5不會(huì)觸發(fā)load)

④domConfig為DOMConfiguration類型的實(shí)例,表示針對(duì)特定文檔的解析和格式化規(guī)則。LSParser會(huì)用此對(duì)象指定額外配置信息,需調(diào)用setParameter()方法。其中一個(gè)參數(shù)是"error_handler",用于指定處理解析錯(cuò)誤的函數(shù)。

var implementation = document.implementation;

var parser = implementation.createLSParser(implementation.MODE_ASYNCHROUNS,null);

var input = implementation.createLSInput();

input.stringData = "<root>";

//預(yù)訂load事件,但不會(huì)觸發(fā)load事件

parser.addEventListener("load",function(event){

var xmldom = event.newDocument;

var input = event.input;

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

},false);

parser.domConfig.setParameter("error_handler",fucntion(ex){

alert("Parsing error!");

});

//開始解析

parser.parse(input);

1.4.2 其它解析方式

通過LSParser還可以執(zhí)行兩種類型的解析:解析來自URI的文件和基于上下文解析。

(1)解析來自URI的XML。

①不用創(chuàng)建LSInput。

②開始解析時(shí)調(diào)用parseURI()方法,并為其傳入一個(gè)指向有效XML的URI。Parser.parseURI("example.xml");

(2)基于上下文解析

①首先解析字符串,然后將解析結(jié)果插入另一個(gè)文檔。

②使用parseWithContext()方法接受3個(gè)參數(shù):LSInput對(duì)象、上下文節(jié)點(diǎn)和要執(zhí)行的操作。

□LSInput對(duì)象的stringData屬性中必須包含XML片段的代碼,不能含有XML序言內(nèi)容(prolog)。

□上下文節(jié)點(diǎn)是解析完的片段該插入的地方。

□要執(zhí)行的操作必須是下列LSParser常量之一。

◇ACTION_APPEND_AS_CHILDERN:將解析結(jié)果作為子節(jié)點(diǎn)添加到上下文節(jié)點(diǎn)中。

◇ACTION_REPLACE_CHILDREN:先移除上下文節(jié)點(diǎn)的所有節(jié)點(diǎn),然后將解析結(jié)果作為上下文節(jié)點(diǎn)的子節(jié)點(diǎn)插入。

◇ACTION_INSERT_BEFORE:將解析結(jié)果作為上下文節(jié)點(diǎn)的同輩節(jié)點(diǎn),插入到上下文節(jié)點(diǎn)前面。

◇ACTION_INSERT_AFTER:將解析結(jié)果作為上下文節(jié)點(diǎn)的同輩節(jié)點(diǎn),插入到上下文節(jié)點(diǎn)后面。

◇ACTION_REPLACE:用解析結(jié)果替換上下文節(jié)點(diǎn)。

◇在解析錯(cuò)誤時(shí),以上操作均會(huì)被取消。

var implementation = document.implement;

var parser = implementation.createLSPareser(implementation.MODE.SYNCHRONOUS,null);

var input = implementation.createLSInput();

input.stringData = "<root/>";

var xmldom = parser.parse(input);

var newInput = implementation.createLSInput();

newInput.StringData = "<child/>";

parse.parseWithContext(newInput,xmldom.documentElement,parser.ACTION_APPEND_AS_CHILDREN);

alert(xmldom.documentElement.firstChild.tagName);  //"child"

1.4.3 序列化XML

①要調(diào)用document.implementation上的createLSSerialization()方法,創(chuàng)建一個(gè)LSSerializer對(duì)象。LSSerializer對(duì)象的主要方法是writeToString(),接受一個(gè)節(jié)點(diǎn)類型參數(shù)并返回該節(jié)點(diǎn)的XML代碼字符串表述。

②通過LSSerializer對(duì)象的domCOnfig屬性來設(shè)置適合打印輸出的XML字符串格式,即將該屬性的"format_pretty_print"參數(shù)設(shè)為true。

③序列化期間發(fā)生錯(cuò)誤,錯(cuò)誤會(huì)被拋出。通過將writeToStirng()放try-catch語句中,可以測(cè)試是否發(fā)生了錯(cuò)誤。

var serializer = implementation.createLSSerializer();

serializer.domConfig.setParameter("format_pretty_print",true);

var xml = "";

try{

Xml = serializer.writeToString(xmldom);

}catch(ex){

Alert("Serialization error occurred");

}

alert(xml);

1.5 IE對(duì)XML的支持

①IE有6種不同的XML文檔版本可供選擇,只建議其中3種:

□MSXML2.DOMDocument:為方便腳本處理而更新的版本,建議僅在特殊情況下作后備版本使用。

□MSXML2.DOMDocument.3.0:為了在JavaScript中使用,這是最低的建議版本。

□MSXML2.DOMDocument.6.0:通過腳本能夠可靠地處理的最新版本。

□確定可用版本:

function createDocument(){

if(typeof arguments.callee.activeXString ! = "string"){

var versions = ["MSXML2.DOMDocument.6.0","MSXML2.DOMDocument.3.0","MSXML2.DOMDocument"];

for(var i = 0, len = versions.length; i < len; i++){

try{

var xmldom = new ActiveXObject(versions[i]);

arguments.callee.activeXString = versions[i];

return xmldom;

}catch(ex){

//跳過

}

}

}

return new ActiveXObject(arguments.callee.activeXString);

}

②要解析XML字符串,先創(chuàng)建XML DOM文檔,然后調(diào)用其loadXML()方法。

var xmldom = createDocument();

xmldom.loadXML("<root><child/></root>");

□在新DOM文檔中填充了XML內(nèi)容后,就可以像操作其他DOM文檔一樣操作它了(可以使用任何方法和屬性)

③如果解析過程中出錯(cuò),可以在parseError屬性對(duì)象中找到錯(cuò)誤。包含多個(gè)保存錯(cuò)誤信息的屬性。

□errorCode:錯(cuò)誤類型的數(shù)值編碼;沒有發(fā)生錯(cuò)誤時(shí)值為0

□filePos:文件中導(dǎo)致錯(cuò)誤發(fā)生的位置。

□line:發(fā)生錯(cuò)誤的行。

□linepos:發(fā)生錯(cuò)誤的行中的字符。

□reason:對(duì)象錯(cuò)誤地文本解析。

□srcText:導(dǎo)致錯(cuò)誤的代碼。

□url:導(dǎo)致錯(cuò)誤的文件的URL。

□parseError的valueof()方法返回errorCode的值。

if(xmldom.parseError != 0){

alert("An error occurred: \n Error Code:"+xmldom.parseError.errorCoed + "\n" 

+ "line:" + xmldom.parseError.line + "\n"

+ "line.Pos" + xmldom.parseError.linepos + "\n"

+ "Reson:" + xmldom.parseError.reason

);

}

1.5.1序列化XML

IE序列化XML的能力內(nèi)置在了XML DOM文檔中。每個(gè)XML DOM節(jié)點(diǎn)都有一個(gè)xml屬性,其中保存著表示該節(jié)點(diǎn)的XML字符串。alert(xmldom.xml)

1.5.2 加載XML文件

①與DOM3級(jí)功能類似,要加載的XML文檔必須與JS代碼來自同一服務(wù)器。

②加載文檔的方式也可以分為同步和異步兩種。要指定加載文檔的方式,可以設(shè)置async屬性,true表示異步(默認(rèn)),false表示同步。使用load(URI)方式加載。

③異步加載XML,需為XML DOM文檔的onreadystatechange事件指定處理程序。有4個(gè)就緒狀態(tài)(ready state)

□1:DOM正在加載數(shù)據(jù)。

□2:DOM已經(jīng)加載完數(shù)據(jù)。

□3:DOM已經(jīng)可以使用,但某些部分可能還無法訪問。

□4:DOM已經(jīng)完全可以使用。

□實(shí)際上,只需要關(guān)注狀態(tài)4。通過XML文檔的readyState屬性可得其就緒狀態(tài)。

var xmldom = createDocument();

xmldom.async = true;

xmldom.onreadystatechange = function(){

if(xmldom.readyState == 4){

if(xmldom.parseError != 0){

Alert("An error occurred");

}else{

//其他xmldom操作

}

}

}

xmldom.load("exmaple.xml");

注:

□onreadystatechange事件指定處理語句須在調(diào)用load()方法之前。

□在事件處理內(nèi)部由于ActiveX控件為預(yù)防錯(cuò)誤,不允許使用this。

1.6 跨瀏覽器處理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(document.implementation.hasFeature("LS","3.0")){

var implementation = document.implementation;

var parser = implementation.createLSParser(implementation.MODE_SYNCHRONOUNS,null);

var input = implementation.createLSInput();

input.stringData = xml;

xmldom = parser.parse(input);

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

}

用此函數(shù)解析XML字符串時(shí),應(yīng)該放在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(document.implementation.hasFeature("LS","3.0")){

var implementation = document.implementation;

var serializer = implemetation.createLSSerializer();

return serializer.writeToString(xmldom);

}else if(typeof xmldom.xml != "undefined"){

return xmldom.xml;

}else{

throw new Error("Could not serialize XMLDOM.");

}

}

2.瀏覽器對(duì)XPath的支持

2.1 DOM3級(jí)Xpath

①DOM3級(jí)支持XPath,檢測(cè)瀏覽器支持:

Var supportsXPath = document.implementation.hasFeature("XPath","3.0");

②DOM3級(jí)XPath中最重要的兩個(gè)類型:XPathEvaluator和XPathResult。

③XPathEvalutor用于特定的上下文中隊(duì)XPath表達(dá)式求值。有3個(gè)方法:

□createExpression(expression,nsresolver):將XPath表達(dá)式及相應(yīng)的命名空間信息轉(zhuǎn)換成一個(gè)XPathExpression,這是查詢的編譯版。在多次使用一個(gè)查詢時(shí)很有用。

□createNSResolver(node):根據(jù)node的命名空間信息創(chuàng)建一個(gè)新的XPathNSResolver對(duì)象。在基于使用命名空間的XML文檔求值時(shí),需要使用XPathNSResolver對(duì)象。

□evaluate(expression,context,nsresolver,type,result):在給定的上下文中,基于特定的命名空間信息來對(duì)XPath表達(dá)式求值。剩下的參數(shù)表示如何返回結(jié)果。

□在支持DOM3級(jí)的瀏覽器中,Document類型通常都是與XPathEvaluator接口一起實(shí)現(xiàn)的。

④上面3個(gè)方法中,evalute最常用。接受5個(gè)參數(shù):

□XPath表達(dá)式

□上下文節(jié)點(diǎn)

□命名空間解析器(只在XML代碼中使用了XML命名空間時(shí)有必要指定,否則為null)

□返回結(jié)果的類型(見書P415)

□保存結(jié)果的XPathResult對(duì)象(通常是null,因?yàn)榻Y(jié)果也會(huì)以函數(shù)值形式返回)

■返回結(jié)果類型為以下的其中一個(gè):

◇XPathResult.ANY_TYPE

◇XPathResult.NUMBER_TYPE

◇XPathResult.STRING_TYPE

◇XPathResult.BOULEAN_TYPE

◇XPathResult.UNORDER_NODE_ITERATOR_TYPE

◇XPathResult.ORDERED_NODE_SNAPSHOT_TYPE

◇XPathResult.ANY_UNORDERED_NODE_TYPE

◇XPathResult.FIRST_ORDERED_NODE_TYPE

1)指定的是迭代器結(jié)果,須用iterateNext()方法從節(jié)點(diǎn)中取得匹配節(jié)點(diǎn),無則返回null。

var result = xmldom.evalute("employee/name",xmldom.document,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);

if(result !== null){

var node = result.iterateNext();

while(node){

alert(node.tagName);

node = node.iterateNext();

}

}

2)指定的是快照類型,就必須使用snapshotItem()和snapshotLength屬性。

1.單節(jié)點(diǎn)結(jié)果

指定常量XPathResult.FIRST_ORDER_NODE.TYPE會(huì)返回第一個(gè)匹配節(jié)點(diǎn),可通過singleNodeValue屬性來訪問該節(jié)點(diǎn)。

2.簡(jiǎn)單類型結(jié)果

booleanValue、numberValue和stringValue

3.默認(rèn)類型結(jié)果

4.命名空間支持

□對(duì)于利用了命名空間的XML文檔,XPathEvaluator必須知道命名信息,然后才能正確地進(jìn)行求值。

□第一種方法是通過createNSResolver()來創(chuàng)建XPathNSResolver對(duì)象,這個(gè)方法接受一個(gè)參數(shù),即文檔中包含命名空間定義的節(jié)點(diǎn)。

Var nsresolver = xmldom.createNSResolver(xmldom.documentElement);

Var result = xmldom.evaluate("wrox:book/wrox:author",xmldom.document,nsresolver,XPathResult.ORDERED_NODESNAPSHOTTYPE,null);

Alert(result.snapshotlength);

□第二種方法是定義一個(gè)函數(shù),讓它接受一個(gè)命名空間前綴,返回關(guān)聯(lián)的URI。

Var nsresolver = function(prefix){

Switch(prefix){

Case "wrox" : return "http://www.wrox.com/";

//其他前綴

}

};

Var result = xmldom.evaluate("count(wrox:book/wrox:author)",xmldom.document,nsresolver,XPathResult.NUMBER_TYPE,null);

2.2 IE中的XPath

①IE對(duì)XPath的支持是內(nèi)置在XML DOM文檔對(duì)象中的。含有兩個(gè)方法。

□selectSingleNode()方法接受一個(gè)XPath模式,在找到匹配節(jié)點(diǎn)時(shí)返回第一個(gè)匹配的節(jié)點(diǎn)。

var element = xmldom.documentElement.selectSingleNode("employee/name");

□selectNodes(),接受一個(gè)XPath模式作參數(shù),返回與模式匹配的所有節(jié)點(diǎn)的NodeList(如果沒有匹配的節(jié)點(diǎn),則返回一個(gè)包含零項(xiàng)的NoedList)。

Var elements = xmldom.documentElement.selectNodes("employee/name");

Alert(elements.length);

②IE對(duì)命名空間的支持

□必須知道自己使用的命名空間,并按格式創(chuàng)建一個(gè)字符串:

"xmlns:prefix1 = 'uri1' xmlns:prefixf2 = 'uri2' xmlns:prefix3:'uri3' "

□將上述格式字符串傳入到XML DOM文檔對(duì)象的特殊方法setProperty()中。

□setProperty()接受兩個(gè)參數(shù):要設(shè)置的屬性名和屬性值。這里屬性名應(yīng)為"SelectionNameSpaces",屬性值是前面格式的字符串。

xmldom.setProperty("selectionNameSpaces","xmlns:wrox = http://www.wrox.com");

var result = xmldom.documentElement.selectNodes("wrox:book/wrox:author");

2.3 跨瀏覽器使用XPath

□selectSingleNode()函數(shù)兼容代碼

function selectSingleNode(context,expression,namespace){

var doc = (context.nodeType != 9 ? context.ownerDocument : context);

if(typeof doc.evaluate != "undefined"){

var nsresolver = null;

if(namespace instanceof Object){

nsresolver = fucntion(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"){

//創(chuàng)建命名空間字符串

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

}

}

□selectNodes()函數(shù)兼容代碼

P420略

3.函數(shù)對(duì)XSLT的支持

XSLT是與XML相關(guān)的一種技術(shù),它利用XPath將文檔從一種表現(xiàn)形式轉(zhuǎn)換成另一種表現(xiàn)形式。

3.1 IE中的XSLT轉(zhuǎn)換

1.簡(jiǎn)單的XSLT轉(zhuǎn)換

□最簡(jiǎn)單方法:XSLT、XML分別加載到一個(gè)DOM文檔中,再使用transformNode()方法。

□transformNode()方法:只有一個(gè)參數(shù)——包含XSLT樣式表的文檔。返回一個(gè)包含轉(zhuǎn)換信息的字符串。

□可在xmldom各個(gè)節(jié)點(diǎn)機(jī)型轉(zhuǎn)換。

//加載xmldom各個(gè)節(jié)點(diǎn)進(jìn)行轉(zhuǎn)換

xmldom.load("employees.xml");

xsltdom.load("employees.xslt");

//轉(zhuǎn)換

var result = xmldom.transformNode(xsltdom);

2.復(fù)雜的XSLT轉(zhuǎn)換

①基本原理:

a.將xml加載到“線程安全的XML DOM”中。

b.將XSLT加載到“XSL模板”中

c.使用“XSL處理器”進(jìn)行轉(zhuǎn)換。

□自由線程DOM:MSXML2.FreeThreadedDOMDocument

□XSL模板:MSXML2.XSLTemplate

□XSL處理器:調(diào)用XSL模板的createProcessor()創(chuàng)建XSL處理器。

②把XSLT樣式表加載到一個(gè)線程安全的XML文檔中。

function createThreadSafeDocument(){

if(typeof arguments.callee.activeXString != "string"){

var versions = ["MSXML2.FreeThreadedDOMDocument.6.0","MSXML2.FreeThreadedDOMDocument.3.0","MSXML2.FreeThreadedDOMDocument\"];

for(var i=0,len = version.length; i<len; i++){

try{

var xmldom = new ActiveXObject(versions[i]);

arguments.callee.activeXString = versions[i];

return xmldom;

}catch(ex){

// 跳過

}

}

}

return new ActiveXObject(arguments.callee.activeXString);

}

□線程安全的XML DOM與常規(guī)XML DOM使用方式一致。

var xsltdom = createThreadSafeDocument();

xsltdom.async = fasle;

xsltdom.load("employee.xslt");

③為自由線程DOM指定XSL模板

fucntion createXSLTemplate(){

if(typeof arugments.callee.activeXString != "string"){

var versions = ["MSXML2.XSLTemplate.6.0","MSXML2.XSLTemplate.3.0","MSXML2.XSLTemplate"];

for(var i=0,len=versions.length;i<len;i++){

try{

var template = new ActiveXObject(versions[i]);

arguments.callee.activeXString = version[i];

return template;

}catch(ex){

//跳過

}

}

}

return new ActiveXObject(arguments.callee.activeXString);

}

□使用createXSLTemplate()函數(shù)創(chuàng)建用法:

var template = createXSLTemplate();

template.stylesheet = xsltdom;

var processor = template.createProcessor();

processor.input = xmldom;

processor.transform();

var result = processor.output;

④創(chuàng)建XSL處理器之后,須將要轉(zhuǎn)換的節(jié)點(diǎn)指定給input屬性。然后,調(diào)用transform()方法執(zhí)行轉(zhuǎn)換并將結(jié)果左字符串保存在output屬性中。

⑤使用XSL處理器可以對(duì)轉(zhuǎn)換進(jìn)行更多的控制,同時(shí)也支持更高級(jí)的XSLT特性。

□addParameter():兩個(gè)參數(shù):要設(shè)置的參數(shù)名稱(與在<xsl:param>的name特性中給指定的一樣)和要指定的值(多數(shù)是字符串,也可以是數(shù)值或布爾值)。

□setStartMode():接受一個(gè)參數(shù),即要為處理器設(shè)置的模式。

□reset():重置處理器,清除原先的輸入和輸出屬性、啟動(dòng)模式及其它指定的參數(shù)。processor.reset();

3.2 XSLTProcessor類型(非IE瀏覽器支持)

①基本原理:

a.加載兩個(gè)DOM文檔,一個(gè)基于XML,另一個(gè)基于XSLT。

b.創(chuàng)建一個(gè)新XSLTProcessor對(duì)象

c.使用importStylesheet()方法指定一個(gè)XSLT

d.最后使用transformToDocument()或transfromToFragment()方法可得一個(gè)文檔片段對(duì)象。

var processor = new XSLTProcessor();

processor.importStylesheet(xsltdom);

□transformToDocument():只要傳入XML DOM,就可將結(jié)果作為一個(gè)完全不同的DOM文檔使用。

□transformToFragement():兩個(gè)參數(shù):要轉(zhuǎn)換的XML DOM和應(yīng)該擁有結(jié)果片段的文檔

var fragment = processor.transformToDocument(xmldom,document);

②使用參數(shù):

□setParameter():3個(gè)參數(shù):命名空間URI(一般為null)、參數(shù)內(nèi)部名稱和要設(shè)置的值

□getParameter():取得當(dāng)前參數(shù)的值,兩個(gè)參數(shù):命名空間和參數(shù)內(nèi)部名。

□removeParameter():移除當(dāng)前參數(shù)的值,兩個(gè)參數(shù):命名空間和參數(shù)內(nèi)部名。

③重置處理器

□reset()方法:從處理器中移除所有參數(shù)和樣式表。

3.3 跨瀏覽器使用XSLT

IE對(duì)XSLT轉(zhuǎn)換支持與XSLTProcessor區(qū)別太大,跨瀏覽器兼容性最好的XSLT轉(zhuǎn)換技術(shù),只能是返回結(jié)果字符串。

function transform(context,xslt){

if(typeof XSLTProcess != "undefined"){

var processor = new XSLTProcessor();

processor.importStylesheet(xslt);

var result = processor.transfromToDocument(context);

return(new XMLSerialize()).serializeToString(result);

}else if(typeof context.transforamNode != "undefined"){

return context.transformNode(xslt);

}else{

throw new Error("No XSLT processor available.");

}

}

第十六章 E4X (略)

第十七章 Ajax與JSON

1.XHR對(duì)象

①IE6需要使用MSXML庫中的一個(gè)ActiveX對(duì)象實(shí)現(xiàn),而其他瀏覽器原生支持XHR對(duì)象。

function createXHR(){

if(typeof XMLHttpRequest != "undefined"){

return new XMLHttpRequest();

}else if(typeof ActiveXobject != "undefined"){

if(typeof arguments.callee.activeXString != "string"){

var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"];

for(var i=0, len = versions.length; I <len; i++){

try{

var xhr = new ActiveXObject(versions[i]);

Arguments.callee.activeXString = versions[i];

return xhr;

}catch(ex){

//跳過

}

}

}

return new ActiveXObject(arguments.callee.activeXString);

}else{

throw new Error("No XHR object available");

}

}

1.1 XHR的用法

①open()方法

□接受3個(gè)參數(shù):要發(fā)送的請(qǐng)求的類型(“get”、“post”等)、請(qǐng)求的URL和表示是異步發(fā)送請(qǐng)求的布爾值。

□參數(shù)URL是相對(duì)于執(zhí)行代碼的當(dāng)前頁面(當(dāng)然也可以使用絕對(duì)路徑);

□調(diào)用open()方法并不會(huì)真正發(fā)送請(qǐng)求,而只是啟動(dòng)一個(gè)請(qǐng)求以備發(fā)送。

②send()方法

□要發(fā)送特定的請(qǐng)求,必須使用send()方法啟動(dòng)。

□接受一個(gè)參數(shù),即要作為請(qǐng)求主體發(fā)送的數(shù)據(jù)。如果不需要通過請(qǐng)求主體發(fā)送數(shù)據(jù),則必須傳入null,因?yàn)檫@個(gè)參數(shù)對(duì)有些瀏覽器來說是必須的。

□調(diào)用send()之后,請(qǐng)求就會(huì)被分派到服務(wù)器。

③相應(yīng)的數(shù)據(jù)會(huì)自動(dòng)填充XHR對(duì)象的屬性,相關(guān)的屬性簡(jiǎn)介如下:

□responseText:作為相應(yīng)主體被返回的文本。

□responseXML:如果響應(yīng)的內(nèi)容是“text/xml”或“application/xml”,這個(gè)屬性中將保存含著響應(yīng)數(shù)據(jù)的XML DOM文檔。

□status:響應(yīng)的HTTP狀態(tài)。

□statusText:HTTP狀態(tài)的說明。

④處理響應(yīng)的判斷

□檢查status屬性,以確定響應(yīng)成功返回。

□HTTP狀態(tài)代碼為200是成功的標(biāo)志,此時(shí)responseText、responseXML應(yīng)能訪問。

□HTTP狀態(tài)代碼為304表示請(qǐng)求的資源沒修改,可使用緩存值。

⑤同步請(qǐng)求

xhr.open("get", "example.txt", false);

xhr.send(null);

if( (xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){

alert(xhr.statusText);

}else{

alert("Request was unsuccessful:" + xhr.status);

}

⑥異步請(qǐng)求

1)發(fā)送異步請(qǐng)求還需要檢測(cè)XHR對(duì)象的readyState屬性,該屬性表示請(qǐng)求/響應(yīng)過程的當(dāng)前活動(dòng)階段。取值如下:

□0:未初始化。尚未調(diào)用open()方法。

□1:?jiǎn)?dòng)。已調(diào)用open()方法,未調(diào)用send()方法。

□2:發(fā)送。已調(diào)用send()方法,但尚未接收到響應(yīng)。

□3:接收。已接收到部分響應(yīng)數(shù)據(jù)。

□4:完成。已經(jīng)接收到全部響應(yīng)數(shù)據(jù),而且已經(jīng)可以在客戶端使用了。

2)readyState值的變化會(huì)觸發(fā)readyStatechange事件。由于并非所有瀏覽器支持DOM2級(jí)方法,因此用DOM0級(jí)添加處理程序。

var xhr = createXHR();

xhr.onreadystatechange = function(){

if(xhr.readyState == 4){

if( (xhr.staus >= 200 && xhr.status < 300) || xhr.status == 304){

alert(xhr.responseText);

}else{

alert("Request was unsuccessful: " + xhr.status);

}

}

};

xhr.open("get","example.txt", true);

xhr.send(null);

⑦在接收到響應(yīng)之前還可以調(diào)用abort()方法取消異步請(qǐng)求。xhr.abort();

1.2 HTTP頭部信息

XHR對(duì)象提供了操作“請(qǐng)求頭部”和“響應(yīng)頭部”信息的方法。

①請(qǐng)求頭部

1)請(qǐng)求頭部信息

□Accept:瀏覽器能夠處理的內(nèi)容類型。

□Accept-Charset:瀏覽器能夠顯示的字符集。

□Accept-Encoding:瀏覽器能夠處理的壓縮編碼。

□connection:瀏覽器與服務(wù)器之間連接的類型。

□Cookie:當(dāng)前頁面設(shè)置的任何cookie。

□Host:發(fā)出請(qǐng)求的頁面所在的域。

□Referer:發(fā)出請(qǐng)求的頁面的URI。

□User-Agent:瀏覽器的用戶代理字符串。

②setRequestHeader()方法可以設(shè)置自定義的請(qǐng)求頭部信息。

□接收兩個(gè)參數(shù):頭部字段名稱和頭部字段的值。

□要成功發(fā)送請(qǐng)求頭部信息,必須在調(diào)用open()方法之后且調(diào)用send()方法之前。

③getResponseHeader()方法,傳入頭部字段名稱,可以取得相應(yīng)的響應(yīng)頭部信息。

④getAllResponseHeader()方法,取得一個(gè)包含所有頭部信息的長(zhǎng)字符串。

1.3 GET請(qǐng)求

①常用語服務(wù)器查詢信息。

②GET請(qǐng)求經(jīng)常會(huì)發(fā)生查詢字符串格式問題。查詢字符串中每個(gè)參數(shù)的名稱和值都必須使用encodeURIComponent()進(jìn)行編碼。

③輔助向現(xiàn)有URL末尾添加查詢字符串參數(shù):

function addURLParam(url, name, value){

url += (url.indexOf("?") == -1 ? "?" : "&" );

url += encodeURIComponent(name) + "=" + encodeURIComponent(value);

return url;

}

1.4 POST請(qǐng)求

①通常用于向服務(wù)器發(fā)送應(yīng)該被保存的數(shù)據(jù)。

②xhr.open("post","example.php",true);發(fā)送post請(qǐng)求的第二步就是向send方法中傳入某些數(shù)據(jù)。

1.5瀏覽器差異

①IE

□IE為XHR對(duì)象添加了一個(gè)timeout屬性,表示請(qǐng)求在等待響應(yīng)。

□規(guī)定時(shí)間內(nèi)沒有接收到響應(yīng),就出發(fā)timeout事件,進(jìn)而調(diào)用ontimeout事件處理程序。

②Firefox

1)load事件

2)progress事件

2.跨域請(qǐng)求

①IE中XDomainRequest對(duì)象

1)XDR與XHR區(qū)別

□cookie不會(huì)隨請(qǐng)求發(fā)送,也不會(huì)隨響應(yīng)返回。

□只能設(shè)置請(qǐng)求頭部信息中的Content-Type字段。

□不能訪問響應(yīng)頭部信息。

□只支持GET和POST請(qǐng)求。

□XDR只能訪問Access-Control-Allow-Origin頭部設(shè)置為有當(dāng)前域的資源。

2)所有XDR請(qǐng)求都是異步執(zhí)行的,不能創(chuàng)建同步請(qǐng)求。

□返回請(qǐng)求之后,會(huì)觸發(fā)load事件,響應(yīng)的數(shù)據(jù)也會(huì)保存在response屬性中。

□接收到響應(yīng)后,只能訪問響應(yīng)的原始文本,沒有辦法確定響應(yīng)的狀態(tài)代碼。

□響應(yīng)有效會(huì)觸發(fā)load事件,如果失?。ò憫?yīng)中缺少Access-Control-Origin頭部)就會(huì)觸發(fā)error事件。

□XDR也支持timeout屬性以及ontimeout事件處理程序。

□為了支持POST請(qǐng)求,XDR對(duì)象提供了ontentType屬性,用來表示發(fā)送數(shù)據(jù)的格式。

□在請(qǐng)求返回前調(diào)用abort()方法可終止請(qǐng)求。

var xdr = new XDomainRequest();

xdr.onload = function(){

alert(xdr.responseText);

};

xdr.timeout = 1000;

xdr.ontimeout = function(){

alert("Request took too long.");

};

xdr.open("get","http://www.xx.com/page/");

xdr.send(null);

②Firefox

1)要求遠(yuǎn)程資源有權(quán)決定自身是否可以被遠(yuǎn)程瀏覽器訪問。

□這需要通過設(shè)置Access-Contro-Allow-Origin頭部實(shí)現(xiàn)。

□要訪問另一個(gè)域資源,可以使用標(biāo)準(zhǔn)XHR對(duì)象,并為open()方法傳入一個(gè)絕對(duì)URL。

2)與IE中XDR對(duì)象不同,跨域XHR對(duì)象允許訪問status和statusText屬性,也支持同步請(qǐng)求。

3)跨域XHR的額外限制如下:

□不能使用setRequestHeader()設(shè)置自定義頭部。

□不會(huì)發(fā)送也不會(huì)接受cookie

□getAllRequestponseHeaders()方法只能返回空字符串。

3.JSON

①JSON是純文本,而不是JavaScript代碼。JSON的設(shè)計(jì)意圖在服務(wù)器端構(gòu)建格式化的數(shù)據(jù),然后再將數(shù)據(jù)發(fā)送給瀏覽器。

②由于JSON在JavaScript中相當(dāng)于對(duì)象和數(shù)組,因此JSON字符串可以傳遞給eval()函數(shù),讓其解析并返回一個(gè)對(duì)象或數(shù)組的實(shí)例。

③如果你是自己編寫代碼來對(duì)JSON求值,最好將輸入文本放在一對(duì)圓括號(hào)中。因?yàn)閑val()在對(duì)輸入的文本求值時(shí),是將其作為JS代碼而非數(shù)據(jù)格式看待。在對(duì)以左花括號(hào)開頭的對(duì)象求值時(shí),就好像是遇到一個(gè)沒有名字的JavaScript語句,會(huì)導(dǎo)致錯(cuò)誤。將文本放在一對(duì)圓括號(hào)中可以解決這個(gè)問題,因圓括號(hào)表示值而不是語句。

var object1 = eval("{}");  //拋出錯(cuò)誤

var object2 = eval("({})");  //沒有問題

var object3 = eval("(" + jsonText + ")");  //通用解決方案

3.1在Ajax中使用JSON

①Douglas Crockford的JSON序列化器/解析器。www.json.org/js.html

②在上述庫中,有一個(gè)全局JSON對(duì)象,有兩個(gè)方法:parse()和stringify()。

③parse()方法:

□兩個(gè)參數(shù):JSON文本和一個(gè)可選的過濾函數(shù)。在傳入的文本是有效地JSON情況下,parse()方法返回傳入數(shù)據(jù)的一個(gè)對(duì)象表示。

□例子:var object = JSON.parse("{}"); 與直接使用eval()不同的是,這里不需要傳入的文本家圓括號(hào)(內(nèi)部自動(dòng)處理)。

□第二個(gè)參數(shù)是一個(gè)函數(shù),這個(gè)函數(shù)以一個(gè)JSON鍵和值作為參數(shù)。要想讓作為參數(shù)的鍵出現(xiàn)在結(jié)果對(duì)象中,該函數(shù)必須返回一個(gè)值。

var jsonText = "{\"name\":\"Nicholas\",\"age\":29,\"author\":true}";

var object = JSON.parse(jsonText,function(key,value){

switch(key){

case "age" : return value+1;

case "author" : return undefined;

default : return value;

}

});

alert(object.age);  //30

alert(object.author); //undefined

④JSON同樣也是向服務(wù)器發(fā)數(shù)據(jù)的流行格式。發(fā)送數(shù)據(jù)時(shí),一般會(huì)把JSON放到POST請(qǐng)求主體中,而JSON對(duì)象的stringify()方法正是為此而設(shè)計(jì)。

⑤stringify()方法:

□三個(gè)參數(shù):要序列化的對(duì)象、可選的替換函數(shù)(用于替換未受支持的JSON值)和可選的縮進(jìn)說明符(可以是每個(gè)級(jí)別縮進(jìn)的空格數(shù),也可以是用來縮進(jìn)的字符)。

var contact = {

name : "Nicholas C. Zakas",

email : "nicholas@some-domain-name.com"

};

var jsonText = JSON.stringify(contact);

alert(jsonText);

□JSON序列化支持的類型:字符串、數(shù)值、布爾值、null、對(duì)象、數(shù)組和Date(Date將被換成字符串形式)。其他不支持類型將被移除,可通過stringify()第二個(gè)參數(shù)所傳入的函數(shù)改變行為。

3.2安全

①JSON缺點(diǎn):使用eval(),有可能受到XSS攻擊。

②建議使用Crockford的庫,可妥當(dāng)解析JSON字符串,過濾其中惡意代碼。降低遭受代碼式XSS攻擊的可能性。

相關(guān)文章

最新評(píng)論