zoukankan      html  css  js  c++  java
  • Firefox 1.5 中的 XML,第 3 部分: 利用 JavaScript 处理 Firefox 中的 XML

    了解了 XML 在 Firefox 浏览器中的基本显示和样式后,下一个要关注的功能就是脚本。本文中,我将展示利用 JavaScript 代码处理 XML 这一基本概念。本文包含的所有代码示例和屏幕截图都是在 Ubuntu Linux® 系统中使用 Firefox 1.5.0.4 创建和测试的,配置文件没有修改过(即没有扩展,保留了安装时的默认选项)。如果要编写用于 XML 处理的跨浏览器代码,可能必须使用其他的浏览器嗅探技术,但是,我没有在本文介绍这些技术。

    加载 XML 文件

    您可以使用 Web 页面内嵌的 JavaScript 代码加载 XML 文档。我将从一个 HTML Web 页面示例入手,该页面加载一个简单的 XML 邮件列表格式用于动态更新,要加载的 XML 文档如 清单 1 所示(labels.xml)。


    清单 1.(labels.xml)地址标签 XML
    				<?xml version="1.0" encoding="iso-8859-1"?>
            <labels>
            <label id='ep' added="2003-06-10">
            <name>Ezra Pound</name>
            <address>
            <street>45 Usura Place</street>
            <city>Hailey</city>
            <province>ID</province>
            </address>
            </label>
            <label id='tse' added="2003-06-20">
            <name>Thomas Eliot</name>
            <address>
            <street>3 Prufrock Lane</street>
            <city>Stamford</city>
            <province>CT</province>
            </address>
            </label>
            <label id="lh" added="2004-11-01">
            <name>Langston Hughes</name>
            <address>
            <street>10 Bridge Tunnel</street>
            <city>Harlem</city>
            <province>NY</province>
            </address>
            </label>
            <label id="co" added="2004-11-15">
            <name>Christopher Okigbo</name>
            <address>
            <street>7 Heaven's Gate</street>
            <city>Idoto</city>
            <province>Anambra</province>
            </address>
            </label>
            </labels>
            

    清单 2 是仅包括一个链接的 HTML 页面,链接显示 “Click here to load addresses”。单击链接,地址标签的信息被添加到页面中。


    清单 2. HTML 页面利用 JavaScript 加载 XML 用于动态更新
    				<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
            <html>
            <head>
            <meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
            <title>Address book</title>
            <script type="application/javascript">
            var ELEMENT_NODE = 1
            //TEXT_NODE
            function loadAddresses()
            {
            xmlDoc = document.implementation.createDocument("", "", null);
            xmlDoc.onload = writeList;
            xmlDoc.load("labels.xml");
            }
            function writeList()
            {
            var labels = xmlDoc.getElementsByTagName('label');
            var ol = document.createElement('OL');
            for (i=0; i < labels.length; i++)
            {
            var li = document.createElement('LI');
            for (j=0; j < labels[i].childNodes.length; j++)
            {
            if (labels[i].childNodes[j].nodeType != ELEMENT_NODE) continue;
            var cdata = document.createTextNode(
            labels[i].childNodes[j].firstChild.nodeValue);
            li.appendChild(cdata);
            }
            var labelId = document.createTextNode('(' +
            labels[i].getAttribute('id') + ')');
            li.appendChild(labelId);
            ol.appendChild(li);
            }
            document.getElementById('updateTarget').appendChild(ol);
            }
            </script>
            </head>
            <body id='updateTarget'>
            <p>
            <a href="javascript:loadAddresses()">Click here to load addresses</a>
            </p>
            </body>
            </html>
            

    script 元素体现动态特性,定义一个 JavaScript 函数 loadAddresses,这个函数将被 HTML 中的链接调用。该函数创建一个空文档实例,然后使用 load 函数读入 清单 1(labels.xml)。load 函数是异步执行的,因此,在 XML 文档读入的同时,脚本可跳到下一行执行,使您能够在 XML 加载开始后就使用一个触发函数开始运行。因此,我为一个独立的函数 writeList 设置 onload 属性。该函数使用方便的文档对象模型(Document Object Model, DOM)的 getElementsByTagName 方法遍历标签。如果 XML 文档使用名称空间,那么要使用 getElementsByTagNameNS 表单而不是上面的方法,并将名称空间指定为第一个参数。在下一节中,您将会看到一个这样的例子。在 清单 2 中,只使用 DOM 的基本层(叫做 DOM Level 1)进行 XML 处理。对于支持名称空间的应用程序,需要使用 DOM Level 2,它扩展了许多 Level 1 方法,可以支持名称空间。清单 2 创建了一个表示有序列表的子树,将 HTML 主文档作为工厂(factory)来创建节点。这样,生成的子树可以插入到 HTML 主文档中。清单 2 使用普通模式读取源 XML 树,然后将相应的节点添加到输出 HTML 子树中。

    对每个 label 元素执行循环语句 labels[i].childNodes,查找 name 和 address 子节点。为避免对文本节点的子节点执行操作,使用 nodeType 测试。使用 firstChild.nodeValue 方法进行访问获得 name 元素的子文本。对 address 元素来说,第一个子节点是空格。您不能访问 address 的子节点的任何文本内容。使用 getAttribute 方法可以访问 ID。将收集到的所有文本添加到列表项中。编译完所有的列表项元素之后,使用 appendChild 方法更新包含子树的 HTML 文档。可以使用 updateTarget ID 标记将添加该子树的元素(body)。当第一次在 Firefox 中加载该 HTML 时,只能看到如 图 1 所示的链接。


    图 1. 加载清单 2 之后的浏览器显示
    清单 2 的初始浏览器显示 

    单击链接,就立刻获得最新的显示,如 图 2 所示。


    图2. 加载清单 2 并单击链接之后的浏览器显示
    清单 2 的更新后的浏览器显示 

    对 XML 主文档使用脚本

    在本系列的第一部分中,我介绍了如何在 Firefox 中浏览 XML 文件。要在这种情况下使用 JavaScript,需要在脚本文件中嵌套一个引用。清单 3(designers.xml)显示的示例 XML 文件是一个设计师列表。XML 引用独立的 CSS 文件来显示 XML,引用独立的 JavaScript 文件来创建链接元素。


    清单 3.(designers.xml)表示时装设计师链接的 XML 格式 
    				<?xml version='1.0' encoding='utf-8'?>
            <?xml-stylesheet type="text/css" href="designers.css"?>
            <designers>
            <blurb>
            <designer  homepage="http://doria.co.uk">Doria Ltd.</designer>
            of London
            </blurb>
            <blurb>
            <designer homepage="http://samsara.biz">Samsara Saris</designer>
            of Mumbai
            </blurb>
            <blurb>
            <designer homepage="http://pcp.co.uk">Pikeman Camouflage, Plc.</designer>
            of London
            </blurb>
            <blurb>
            <designer homepage="http://mandalay.co.jp">Mandalay</designer>
            of Tokyo
            </blurb>
            <xhtml:script xmlns:xhtml="http://www.w3.org/1999/xhtml"
            src="designers.js"
            type="application/javascript"/>
            </designers>
            

    样式表处理指令提供显示 XML 的基本指令。清单 4(designers.css)显示 CSS。


    清单 4.(designers.css)修饰清单 3 中 XML 格式基本显示的 CSS
    				* { display: inherit; }
            designers { display: block; }
            blurb {
            margin: 1em;
             20em;
            }
            a {
            display: inline;
            text-decoration: none;
            color: green;
            border: thin blue solid;
            }
            script { display: none; }
            

    样式表通知浏览器把 designers 和 blurb 作为块区域,而忽略用于显示的 script 元素。通过将链接(a 元素)和可见的提示一同显示,可以更容易识别出链接。您将注意到在 XML 源文件中不存在 a 元素。因此,这里要用到脚本。JavaScript 代码使用 XHTML 链接元素代替 designer 元素。XHTML 链接元素通过一个 XHTML 脚本元素提供,因此只要使用到 Firefox,就可以嵌入任何 XML(当然,您可能会遇到模式兼容性的问题)。Firefox 在载入的文档中遇到脚本后就运行它们,因此要把脚本放在所有待处理的元素之后。清单 5(designers.js)显示了 JavaScript 代码。


    清单 5.(designers.js)将 XML 元素从清单 3 转换为 XHTML 链接的脚本
    				//Save the XHTML namespace for when you need it
            var xhtmlns = "http://www.w3.org/1999/xhtml";
            //get all elements named "blurb" in the document
            //The first "" indicates no namespace for the element we're seeking
            var blurbs = document.getElementsByTagNameNS("", "blurb");
            //Loop over each element we found
            for (var i=0; i < blurbs.length; i++)
            {
            //retrieve the blurb element from the collection
            var blurb = blurbs[i];
            //Get the designer element within the blurb
            //Assumes only one designer element per blurb
            var designer = blurb.getElementsByTagNameNS("", "designer").item(0);
            //In DOM the text in designer is actually a text node object child
            //of blurb. The link title is the value of this text node
            //Assumes the text node is normalized
            var link_title = designer.firstChild.nodeValue;
            //Link URL is the homepage attribute of designer, in no namespace
            var link_url = designer.getAttributeNS("", "homepage");
            //Create a new XHTML namespace link element
            var xhtml_link = document.createElementNS(xhtmlns, "a");
            //Create a new text node with the link title
            var new_text_node = document.createTextNode(link_title);
            //Set the href attribute to the link URL
            xhtml_link.setAttributeNS("", "href", link_url);
            //Attach the text node with the link title to the XHTML link
            xhtml_link.appendChild(new_text_node);
            //Replace the designer element with the new XHTML link element
            blurb.replaceChild(xhtml_link, designer);
            }
            

    因为 清单 5 中的脚本可以支持名称空间(尤其是其中的 XHTML 名称空间),所以我使用支持名称空间的 DOM 方法。图 3 显示查看 清单 3 的结果。可以看到,浏览器立即应用 CSS 和脚本。


    图 3. 加载清单 3 的浏览器显示
    加载清单 3 的浏览器显示 




    回页首


    调用 XSLT

    使用 JavaScript 可以访问大多数的浏览器功能,其中包括 XSLT 引擎。清单 6 是一个执行 XSLT 转换的脚本片段。


    清单 6. 加载 XML 文档和 XSLT 转换并执行转换的 JavaScript 代码
            //Create an XSLT processor instance
            var processor = new XSLTProcessor();
            //Create an empty XML document for the XSLT transform
            var transform = document.implementation.createDocument("", "", null);
            //Load the XSLT
            transform.onload = loadTransform;
            transform.load("display.xslt");
            //Triggered once the XSLT document is loaded
            function loadTransform(){
            //Attach the transform to the processor
            processor.importStylesheet(transform);
            source = document.implementation.createDocument("", "", null);
            source.load("source.xml");
            source.onload = runTransform;
            }
            //Triggered once the source document is loaded
            function runTransform(){
            //Run the transform, creating a fragment output subtree that
            //can be inserted back into the main page document object (given
            //in the second argument)
            var frag = processor.transformToFragment(source, document);
            //insert the result subtree into the document, using the target element ID
            document.getElementById('updateTarget').appendChild(frag);
            }
            

    如果想创建整个输出文档,而不是创建插入到其他文档的子树,使用 transformToDocument 方法代替 transformToFragment 方法。





    回页首


    结束语

    首先是一份重要的免责声明:XML 的 Web 脚本语言还没有完全标准化。文中涉及的很多内容并不是跨浏览器标准化的。由于本系列主要关注 Firefox,文中没有介绍其他浏览器需要做的修改,但是您可以继续了解如何修改以适合各种用户界面。XML 甚至是 XSLT 的 JavaScript 操作都可使用跨浏览器库。如果不能专门针对基于 Mozila 的浏览器进行开发,那么可以使用跨浏览器库。处理 Web 脚本时,必须要考虑可访问性。同时,要注意内容、处理和显示的分离,避免在最后一刻才将引用嵌入到脚本中。另外,也可以保存和管理不包含这类引用的 XML,在将 XML 传送给浏览器之前,插入这些引用。

    现在,您已经了解如何在 Web 脚本中加载和处理一个独立的 XML 文件,如何从 XML 主文档中调用脚本,以及如何从脚本中调用 XSLT 处理器。因为 JavaScript 支持所有浏览器特性,因此可以使用它进行更多 XML 处理。可以将学过的各种脚本编制技术,例如动态 HTML(DHTML),应用到 XML 处理中。ECMAScript for XML (E4X) 是一组对 JavaScript 的语言增强(从技术上讲,是 ECMAScript),使 JavaScript 的 XML 处理更容易。这个新标准为 XML 处理添加了专门的用法。Firefox 1.5 支持 E4X,我将在以后的文章中对它进行介绍。不用牺牲 XML 的强大的结构特性,适度和精心设计的脚本可以展现现代 Web 应用程序的全部魅力。



    参考资料

    学习

    获得产品和技术
    • Firefox:获得基于 Mozilla 的 Web 浏览器,该浏览器提供标准遵从性、高性能和安全性,以及稳定的 XML 特性。当前版本为 1.5.0.4。


    讨论


    关于作者

    Uche Ogbuji 是 Fourthought Inc. 的顾问和创立者之一,这是一家专门从事企业知识管理 XML 解决方案的软件供应商和咨询公司。Fourthought 开发了 4Suite,这是一个用于 XML、RDF 和知识管理应用程序的开放源码平台。Ogbuji 先生还是 Versa RDF 查询语言的主要开发人员。他是一位出生在尼日利亚的计算机工程师和作家,目前在美国科罗拉多州博耳得定居和工作。您可以通过他的 Weblog Copia 进一步了解 Ogbuji 先生。

  • 相关阅读:
    JOIN条件限制对结果记录的影响
    什么是linux?
    什么是操作系统?
    Internship settled!
    Python dict 调试技巧 —— 利用YAML存储dict内容
    c++ 异常处理
    C#可空类型
    C# 异常处理
    C#值类型与引用类型
    C# 类类型
  • 原文地址:https://www.cnblogs.com/yuzhongwusan/p/1371552.html
Copyright © 2011-2022 走看看