首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

4.1.4  基本的XML实例

XML是一种语义描述语言。一般来说,包含在给定XML文档中的元素描述该文档的数据,因此对于静态信息或是不常改变的信息,这是一种不错的数据存储方法。

假设有一个在线书店,它有一个保存在XML文档books.xml中的“最佳选择”列表。你需要将这些信息显示给用户,但是又不希望使用服务器组件来实现,因此只能采用基于JavaScript的解决方案。使用zXml库就可以编写这样的JavaScript解决方案,载入、解析XML文件,并使用DOM方法在Web页面中显示这些信息。

books.xml文件中包含下列XML数据:

<?xml version="1.0" encoding="utf-8"?>

 

<bookList>

    <book isbn="0471777781">

       <title>Professional Ajax</title>

       <author>Nicholas C. Zakas, Jeremy McPeak, Joe Fawcett</author>

       <publisher>Wrox</publisher>

    </book>

    <book isbn="0764579088">

       <title>Professional JavaScript for Web Developers</title>

       <author>Nicholas C. Zakas</author>

       <publisher>Wrox</publisher>

    </book>

    <book isbn="0764557599">

        <title>Professional C#</title>

       <author>Simon Robinson, et al</author>

       <publisher>Wrox</publisher>

    </book>

    <book isbn="1861006314">

       <title>GDI+ Programming: Creating Custom Controls Using C#</title>

       <author>Eric White</author>

       <publisher>Wrox</publisher>

    </book>

    <book isbn="1861002025">

       <title>Professional Visual Basic 6 Databases</title>

       <author>Charles Williams</author>

       <publisher>Wrox</publisher>

  </book>

</bookList>

正如你所见,文档元素<bookList/>中包含一系列的<book/>元素,每个<book/>元素包含一本特定书籍的信息。

1.  载入XML数据

实现的第一步是创建XML DOM文档,并载入XML数据。因为books.xml是以异步模式载入的,因此需要设置onreadystatechange事件处理函数:

var oXmlDom = zXmlDom.createDocument();

oXmlDom.onreadystatechange = function () {

    if (oXmlDom.readyState == 4) {

 

    }

};

readystatechange事件触发并调用相应的事件处理函数时,将对readyState属性进行检查,如果该属性的值为4,就表明文档已完全载入,可以使用DOM了。

接下来一步是检查错误,因为即使文档已经完全载入,但并不表示一切正常:

var oXmlDom = zXmlDom.createDocument();

oXmlDom.onreadystatechange = function () {

    if (oXmlDom.readyState == 4) {

       if (oXmlDom.parseError.errorCode == 0) {

           parseBookInfo(oXmlDom);

       } else {

           var str = "An error occurred!!\n" +

              "Description: " + oXmlDom.parseError.reason + "\n" +

               "File: " + oXmlDom.parseError.url + "\n" +

               "Line: " + oXmlDom.parseError.line + "\n" +

                "Line Position: " + oXmlDom.parseError.linePos + "\n" +

               "Source Code: " + oXmlDom.parseError.srcText;

           alert(str);

       }

    }

};

如果没有错误发生,那么XML DOM文档将作为参数传给parseBookInfo()函数,该函数负责解析这个书籍列表。如果发生了错误,那么将通过alert()方法在警告框中来显示parseError对象中的错误信息。

当完成了onreadystatechange事件处理函数的编写之后,就将使用load()方法载入XML数据:

oXmlDom.load("books.xml");

现在XML文档已经载入。接下来则是对XML数据进行解析。

2. 解析书籍列表

parseBookInfo()函数负责对DOM文档进行解析。该函数接受一个参数,即DOM文档自身:

function parseBookInfo(oXmlDom) {

    var oRoot = oXmlDom.documentElement;

    var oFragment = document.createDocumentFragment();

oRoot变量将赋值为XML文档的documentElement。这样做仅仅是为了方便,毕竟输入oRoot要比输入oXmlDom.documentElement简单、迅速得多。你还需要创建一个文档片断。parseBookInfo()函数将生成许多HTML元素,并将其转换成HTML DOM载入浏览器。往HTML DOM中添加每个元素是一个大开销的过程,因为显示这些变化会花费不少时间。所以我们采用的方法是,先将每个元素添加到文档片断,当所有HTML元素创建后,再将文档片断添加到文档中。这样做只需要对HTML DOM进行一次更新,从而可以更快地呈现。

你知道,文档元素的子节点只有<book/>元素,因此可以通过childNodes集合来遍历该文档:

var aBooks = oRoot.getElementsByTagName("book");

 

for (var i = 0; i < aBooks.length; i++) {

    var sIsbn = aBooks[i].getAttribute("isbn");

    var sAuthor, sTitle, sPublisher;

for循环中,实际的解析工作才开始。首先,通过getAttribute()方法获取<book/>元素的isbn属性,并保存在变量sIsbn中。该值用来向用户显示书籍封面及其实际的ISBN值。这里还声明了变量sAuthorsTitlesPublisher,它们分别用来保存<author/><title/><publisher/>元素的值。

接下来必须获取书籍的相关数据,这可以通过多种不同的方法来实现。例如可以使用childNodes集合并遍历子节点,但这个例子中采用了另一种不同的方法。它通过一个使用firstChildnextSibling属性的do...while循环来达到相同的目的:

var oCurrentChild = aBooks[i].firstChild;

 

do {

    switch (oCurrentChild.tagName) {

       case "title":

           sTitle = oCurrentChild.text;

       break;

       case "author":

           sAuthor = oCurrentChild.text;

       break;

       case "publisher":

           sPublisher = oCurrentChild.text;

       break;

       default:

       break;

    }

    oCurrentChild = oCurrentChild.nextSibling;

} while (oCurrentChild = oCurrentChild.nextSibling);

第一行代码将oCurrentChild变量的值设置为当前<book/>元素的第一个子节点(记住,这将发生在for循环中)。子节点的tagName属性用在switch语句中来判断如何进行数据的处理。switch语句将根据当前节点的相应tagName来将其值赋给相应的变量。为了获取这个数据,可以使用节点的text属性,该属性可以获取元素内的所有文本节点。使用nextSibling属性,将当前节点的下一个节点赋给变量oCurrentChild。如果下一个邻居存在,那么继续循环,否则oCurrentChild设为null并退出循环。

当所有数据变量包含所需数据时,就可以开始生成HTML元素来显示数据。通过程序创建的HTML元素结构可能如下所示:

<div class="bookContainer">

    <img class="bookCover" alt="Professional Ajax" src="0471777781.png" />

    <div class="bookContent">

       <h3>Professional Ajax</h3>

       Written by: Nicholas C. Zakas, Jeremy McPeak, Joe Fawcett<br />

       ISBN #0471777781

       <div class="bookPublisher">Published by Wrox</div>

    </div>

</div>

为了提高列表的可读性,可以通过<div/>元素来实现交替背景色的效果。奇数行的书籍信息的背景色为浅灰,由类名为bookContainer-oddCSS)类定义;偶数行的书籍信息的背景色为白色,由bookContainerCSS)类定义。

通过DOM方法来生成这些代码,虽然很简单但也十分冗长。第一步是通过createElement()DOM方法来创建容器<div/><img/>和内容<div/>元素。

var divContainer = document.createElement("div");

var imgBookCover = document.createElement("img");

var divContent = document.createElement("div");

 

var sOdd = (i % 2)?"":"-odd";

divContainer.className = "bookContainer" + sOdd;

在创建元素的同时,将为其指定相应的CSS类。通过使用取余操作符(%)判断当前书籍是位于奇数行还是偶数行。根据不同情况对sOdd变量赋予相应的值,偶数是空字符串,奇数则是“-odd”,并用在className的赋值上。

接下来对书籍封面图像的属性进行赋值。这些PNG图像使用ISBN号作为文件名:

imgBookCover.src = "images/" + sIsbn + ".png";

imgBookCover.className = "bookCover";

divContainer.appendChild(imgBookCover);

在这里,将对该图像的srcclassName属性进行赋值,并将其添加到divContainer中。完成图像处理后,就可以添加内容。首先要添加的信息是书籍标题,这是一个3级标题元素<h3/>。该元素也通过createElement()方法创建。

var h3Title = document.createElement("h3");

h3Title.appendChild(document.createTextNode(sTitle));

divContent.appendChild(h3Title);

如果要创建包含标题的文本节点,那么要使用createTextNode()方法,并将其添加到<h3/>元素中,然后将完整标题添加到divContent中。

接下来添加作者和ISBN的信息。这两部分信息都是文本节点,且除了divContent不存在父元素。不过在这两个文本节点间还将加入一个换行元素。

divContent.appendChild(document.createTextNode("Written by: " + sAuthor));

divContent.appendChild(document.createElement("br"));

divContent.appendChild(document.createTextNode("ISBN: #" + sIsbn));

这段代码将创建这些信息。首先,将包含作者信息的文本节点添加到divContent中,接着创建并添加换行元素<br/>最后添加包含ISBN信息的文本节点。

最后添加的是出版社信息:

var divPublisher = document.createElement("div");

divPublisher.className = "bookPublisher";

divPublisher.appendChild(document.createTextNode("Published by: " + sPublisher));

divContent.appendChild(divPublisher);

出版社信息在<div/>元素中显示。<div/>元素创建后,其className设为“bookPublisher”,包含出版社名称的文本节点添加到该元素中。这样就完成了divPublisher元素,可以将其添加到divContent中。

到此为止,所有的数据操作就全部完成了。但是,divContent还没有指定CSS类名,而且必须添加到divContainer中,而divContainer必须依次地添加到文档片段中。下面三行代码将完成这个功能:

divContent.className = "bookContent";

divContainer.appendChild(divContent);

oFragment.appendChild(divContainer);

最后一步是,当通过下述代码遍历了所有的书籍节点之后,则将文档片段添加到页面主体中。

document.body.appendChild(oFragment);

这段代码并没有真正地添加文档片段本身,实际上只是添加文档片段的所有子节点,并立刻将其转换成HTML DOM。有了这最后一行代码,parseBookInfo()函数也就完成了。

3. 整合

Web页面的主体部分完全是由JavaScript生成的。正因如此,所以必须在文档载入后才能执行元素的创建和代码的插入。请记住,在载入books.xml后才调用parseBookInfo(),所以创建XML DOM对象的代码必须在页面载入时执行。创建一个名为init()的函数,用来放置创建XML DOM对象的代码。

function init() {

    var oXmlDom = zXmlDom.createDocument();

    oXmlDom.onreadystatechange = function () {

       if (oXmlDom.readyState == 4) {

           if (oXmlDom.parseError.errorCode == 0) {

               parseBookInfo(oXmlDom);

           } else {

               alert("An Error Occurred: " + oXmlDom.parseError.reason);

           }

       }

    };

    oXmlDom.load("book.xml");

}

init()函数用来处理window.onload事件。这有助于确保JavaScript生成的元素添加到页面中,而不引起任何错误。

这个小应用程序就在一个HTML文档中。所需的只是两个<script/>元素,一个为CSS提供的<link/>元素,以及为onload事件处理函数赋值。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"

                       "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head>

    <title>Book XML Exercise</title>

    <link rel="stylesheet" type="text/css" href="books.css" />

    <script type="text/javascript" src="zxml.js"></script>

    <script type="text/javascript" src="books.js"></script>

</head>

<body onload="init()">

 

</body>

</html>

当运行这段代码时,将看到如图4-2所示的结果。

  4-2

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论