新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> DTD, XML Schema(XMLS), RELAX NG
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - XML技术『 DTD/XML Schema 』 → XML 问题: MochiKit (IBM developmentworks China) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 5276 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: XML 问题: MochiKit (IBM developmentworks China) 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     struppimm 帅哥哟,离线,有人找我吗?
      
      
      等级:大一(猛啃高等数学)
      文章:16
      积分:110
      门派:XML.ORG.CN
      注册:2007/2/3

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给struppimm发送一个短消息 把struppimm加入好友 查看struppimm的个人资料 搜索struppimm在『 DTD/XML Schema 』的所有贴子 引用回复这个贴子 回复这个贴子 查看struppimm的博客楼主
    发贴心情 XML 问题: MochiKit (IBM developmentworks China)

    XML 问题: MochiKit

    改进 XML 的 DOM 操作
     developerWorks
     
     
    文档选项
     将此页作为电子邮件发送 

    将此页作为电子邮件发送

    拓展 Tomcat 应用
      

    下载 IBM 开源 J2EE 应用服务器 WAS CE 新版本 V1.1

    级别: 中级

    David Mertz, Ph.D (mertz@gnosis.cx), 作家, Gnosis Software, Inc.

    2007 年 1 月 15 日

        MochiKit 是一种有用的高端 JavaScript 库。MochiKit 主要受到 Python 和 Python 标准库提供的很多便利之处的启发,另外还缓解了浏览器版本之间的不一致性。其中的 MochiKit.DOM 尤其方便,能够以比原始 JavaScript 更友好的方式处理 DOM 对象。MochiKit.DOM 大部分都是针对 XHTML 文档定制的,如果与 MochiKit 和 Ajax 结合在一起,使用 XHTML 包装的微格式尤其方便。

    简介

    我最近的客座专栏作家 Dethe Elza 围绕着 Ajax、微格式和 Atom 提出了一些有趣的观点,我认为值得进一步探讨。首先,本文介绍了 Dethe 在其关于纤格式的文章中提到的一种很好的 ECMAScript 库(请参阅 参考资料):Bob Ippolito 的 MochiKit。MochiKit 对 JavaScript(从技术上说是 ECMAScript)的基本功能提供了一些出色的改进,多数源于对 Ippolito 的函数性编程的喜好,以及对 Python 丰富的标准库和灵活的结构的钟爱。使用 MochiKit 进行 JavaScript 编程,不少开发人员认为在很多方面就像是使用更加友好的 Python 语言。

    为何使用 XML?

    本专栏的读者知道,Ajax 中的 “X” 在很大程度上是因为 Web 浏览器中的 ECMAScript 实现或多或少支持 W3C 文档对象模型(DOM)规范。(根据具体的浏览器版本,“少” 可能超过 “多”。)这仅仅是一种美妙的说法,说 JavaScript 代码自动具有 XML 和 (X)HTML 文档解析器,并且有一套遍历、搜索和修改这类文档的抽象结构的 API 调用。看起来配合得非常自然,美中不足的是 DOM 是一种极其可怕的 API。虽然您可能争论说在 Java 这类功能强大、静态类型、高度结构化、小心封装的语言中 —— 我们程序员称之为拘谨、讲纪律的语言,保持了 W3C DOM 的形式,但是在 ECMAScript 这种比较敏捷的语言中没有理由这么做。

    读者可能要问何必去管 XML 呢,既然 MochiKit.DOM 已经把工作简化了?无论如何,JSON 本质上仅仅是一种原生的 JavaScript 数据结构(有趣的是恰好也是有效的 Python),仍然比较弱小。不管怎么说,XML 还保留着一些优势。一方面就表示而言,XML 可以直接用 CSS2(级联样式表 2)设置样式。当然,可以将 JSON 转换成可设置样式的 DOM 对象,但本质上说只不过是又回到了 XML 或 (X)HTML。另一方面,和 JSON 相比,除了 ECMAScript 解释器本身以外有更多的工具支持 XML。数据可能来自——或者返回——使用 XML 定义结构化数据的服务器。有时候,这些 XML 遵循众所周知的、精心定义的模式,包括遵守那些已发布的标准。如果整个通信流中其他某些系统希望使用 SVG、OpenDocument、TEI 或者某种 ebXML 标准通信,就没有必要再额外增加一层 JSON 了。

    简单的戏法

    幸运的是,MochiKit.DOM 是根据 W3C DOM 的目标打造的,即为抽象文档结构提供一种 API,把 W3C DOM 中简单的东西变得更加简单,困难的东西变得不那么困难。MochiKit.DOM 真正的魔法在于它在方法调用过程中积极而灵活地把各种对象类型强制转换成正确的类型,包括在递归过程中。MochiKit 认为,只要明显正确的事情,就没有必要让程序员转圈子强制类型转换,或者调用方法来提取或变出需要的东西。此外,MochiKit 受 FP 启发而建立的部分应用程序也简化了程序员(以及程序)的工作,只要这样做最方便。


     回页首


    什么是 HTML 的大问题?

    显然网页通常用 (X)HTML 编写,或者某种类似 HTML 但实际上不是 HTML 的东西编写。我承认浏览器的 quirks 模式工作非常出色。但是现代浏览器中普遍实现了 CSS,适合样式处理的任何 XML 文档都一样好,实际上允许在文档中使用更能反映语义的具体标签。现在,(X)HTML 很可能被看作是带有默认 CSS 样式表的 XML 模式。

    一般化的 XML 与 (X)HTML 同时存在非常适合 Ajax。MochiKit 提供的大部分例子最后都把 XML 或 JSON 解析成 HTML 标签,但是从概念上说更纯粹的 XML 样式是很可能的。作为例子,我使用了 MochiKit 在 ajax_tables 例子中使用的 <datatable> XML 格式,但用法略有不同。首先适当设置表格的样式。下面是一个简单的 CSS 样式表:


    清单 1. table.css

    datatable {
        display: table;
        width: 99%;
        border: solid 1px;
        margin-left: auto;
        margin-right: auto
        }
    columns {
        display: table-header-group;
        background-color: lightblue;
        }
    column {
        display: table-cell;
        font-weight: bold;
        border-right: solid 1px;
        }
    rows {
        display: table-row-group
        }
    row {
        display: table-row
        }
    cell {
        display: table-cell; border-right: solid 1px;
        }


    从 CSS 很容易推断出 XML 样式的文档结构,不过先看一个数据文件吧:


    清单 2. table1.xml

    <?xml version="1.0"?>
    <?xml-stylesheet href="table.css" type="text/css"?>
    <datatable>
        <columns>
            <column>First_name</column>
            <column>Last_name</column>
            <column>Domain_name</column>
        </columns>
        <rows>
            <row>
                <cell>Dethe</cell>
                <cell>Elza</cell>
                <cell>livingcode.org</cell>
            </row>
            <row>
                <cell>Bob</cell>
                <cell>Ippolito</cell>
                <cell>bob.pythonmac.org</cell>
            </row>
        </rows>
    </datatable>


    没有什么特别之处,这个静态文档完全可以发布。读者可能会看到下面的结果:


    图 1. Firefox 显示 table1.xml 的截屏图
    Firefox 显示 table1.xml 的截屏图


     回页首


    操作 XML

    仅仅显示带样式表的 XML 不需要 Ajax,也不需要 MochiKit。我们就来编写一些代码对 XML 做点什么吧。首先,将您的 XML 包装成老式的 HTML。的确,可以用神奇的 xml:link 属性添加 XLINK 功能,但先不要搞得那么复杂吧:


    清单 3. 表格项目的 index.html 主页


    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
                   "http://www.w3.org/TR/html4/strict.dtd">
    <html>
      <head>
        <title>DOM made simple</title>
        <script type="text/javascript"
                src="../../lib/MochiKit/MochiKit.js"></script>
        <script type="text/javascript"
                src="../../lib/MochiKit/DOM.js"></script>
        <script type="text/javascript"
                src="table.js"></script>
      </head>
      <body>
      <p id="actions">
        <b onclick="showXML()">[Show current XML]</b>
        <b onclick="showText()">[Show text of table]</b> <br/>
        <b onclick="newChildContent('table1.xml')">[Load table1.xml]</b>
        <b onclick="newChildContent('table2.xml')">[Load table2.xml]</b>
        <b onclick="addRow()">[Add row of data]</b>        </p>
      <iframe name="child" id="child" src="table.xml" width="600" />
      </body>
    </html>


    清单 3 中的 HTML 页面例子包括三个主要部分:

       1. 从两个 MochiKit 组件加载一些 ECMAScript 和一个定制的脚本文件。
       2. 定义几个可单击的动作。
       3. 在 <iframe> 中显示表格,如图 1 所示。

    显然,更完善的应用程序还可能以更复杂的方式和页面交互,也许会用到表单、页面区域和自定义控件。但那些内容要在其他文章中讨论。

    分割 JavaScript

    支持 HTML 中调用函数的是两个小函数。如清单 4 所示:


    清单 4. table.js 中的支持例程

    childDoc = function() {
        return frames['child'].document;
    };
    getRows = function() {
        return childDoc().getElementsByTagName('rows')[0];
    };
    randint = function(n) {
        return Math.floor(Math.random()*n);
    }


    意义都很明显,也没有使用任何 MochiKit 功能。两个显示函数利用了 MochiKit 一些次要的便利之处:


    清单 5. 在 table.js 中显示 XML 内容

    showXML = function() {
        alert(toHTML(childDoc().documentElement));
    };
    showText = function() {
        alert(scrapeText(childDoc().documentElement));
    };


    这段代码也不是很长。在非娱乐的程序中,我认为可能要对 XML 做更多的处理,而不仅仅是在 alert() 框中显示出来:可以将它发送到服务器,或者至少作为客户机应用程序的一部分进一步处理和扫描。但 scrapeText() 仍不失为一个方便的函数,可以提取文档中的所有文本节点;toHTML() 也能正确地转义保留字符把 DOM 树作为一个 XML 字符串来呈现(尽管名称是 HTML)。这些函数至少能够让您分析表格 XML 的状态。

    (略接近)真正的 XML 处理

    真正有趣的地方是加载和修改 XML 内容。详细说明之前,我先给出加载新 XML 数据的代码:


    清单 6. 在 table.js 中加载 XML

    newChildContent = function(url) {
        var req = getXMLHttpRequest();
        req.overrideMimeType("text/xml");
        req.open("GET", url, true);
        d = sendXMLHttpRequest(req).addCallback(datatableFromXMLRequest);
    };
    datatableFromXMLRequest = function (req) {
        var xml = req.responseXML;
        var new_rose = xml.getElementsByTagName('rows')[0]
        swapDOM(getRows(),new_rose);
        rows = getRows().getElementsByTagName('row');
        for (var i=0; i < rows.length; i++) {
            setNodeAttribute(rows[i], 'id', 'row'+i);
        }
    };


    首先注意到的 MochiKit 一个优点——和其他一些 JavaScript 库一样——是用一个友好的函数包装了 Microsoft Internet Explorer 各种版本的特性,getXMLHttpRequest() ,这样就不用担心其中的细节了。当然,它也能愉快地和支持 XMLHttpRequest() 的标准浏览器打交道。更有意思的是 sendXMLHttpRequest(),它利用了 MochiKit.Async 工具箱。和名字所暗示的一样,它允许异步检索请求,在等待确定请求成功与否的同时可以做其他工作。这段简单的代码并没用使用异步请求,但真正的代码可以根据结果决定怎么做。比如,MochiKit 的 ajax_tables.js 例子用延迟对象 d 完成这件事:


    清单 7. 在 ajax_tables.js 中处理延迟的对象


    // call this.initWithData(data) once it's ready
    d.addCallback(this.initWithData);
    // except for a simple cancellation, log the error
    d.addErrback(function (err) {
        if (err instanceof CancelledError) {
            return;
        }
        logError(err);
    });


    table.js 中仅仅假设加载本地文件的请求成功了。然后我使用标准 DOM .getElementsByTagName() 方法取出了 <rows> 元素。但 MochiKit 中的 swapDOM() 为那些绕弯子的 DOM 语法提供了更好的快捷方式。但我第一次怀疑是在用 swapDOM(childDoc().documentElement,xml.documentElement) 交换整个文档元素的时候。不幸的是,没有增加上任何节点,也许读者能够告诉为什么失败了。显然,交换什么依赖于应用程序的特殊要求,但令我感到挫折的是不能选择层次结构的顶端。

    在回调函数中我也有些多余地为 <row> 元素增加了 id 属性。围绕着 DOM .getElementsById() 方法有一大堆 MochiKit 快捷元素,但是都假定上下文是主文档而不是在 iframe DOM 中。因此对上面的娱乐应用程序没有明显的用处。如果仅考虑主文档,可以这样用:


    清单 8. Firebug 交互控制台

    >>> $('child')
    <iframe width="600" src="table.xml" id="child" name="child">
    >>> $('actions')
    <p id="actions">


    一些 MochiKit 允许根据 id 命名节点并对其执行一些动作。比如,addElementClass(“foo”,“newClass”) 将为 id 为 “foo” 的元素添加 newClass,而不会破坏已有的类。

    调整 XML

    加载文档仅仅是开始,虽然上面的示例代码除此以外没有做多少工作。但 MochiKit.DOM 中里一个很好的 XML 和 (X)HTML 便利工具是其简单的 DOM 创建函数,它能够与 MochiKit 的迭代器和函数性编程风格很好地结合。大多数 HTML 功能已经有预先建好的便捷函数(按照惯例全部用大写命名),但是也很容易为 XML 格式创建自己的函数。比如,下面的代码在 XML 表格中(有点傻)增加行:


    清单 9. table.js 中的 DOM 创建


    ROW = createDOMFunc('row');
    CELL = createDOMFunc('cell');
    newRow = function(cells) {
        return ROW({'type':'name'}, map(partial(CELL, null), cells));
    };
    addRow = function() {
        fn = ['John','Jane','Jim','Jill','June'][randint(5)];
        ln = ['Wu','Williams','Wegner','Wulu','Watanabi'][randint(5)];
        dn = ['gnosis.cx','google.com','gmail.com',
                   'gnu.org','groklaw.net'][randint(5)];
        appendChildNodes(getRows(), newRow([fn,ln,dn]));
    };


    可以看到增加的行毫无意义:为每个字段随机排列了几种可能的值,只要添加的行互不相同就足够了。戏法来自很酷的 DOM 函数 ROW() 和 CELL(),特别是他们在 newRow() 函数中的快速组合。仅仅为了说明有这种可能,我为每个 <row> 添加了 type="name" 属性,如果传递词典而不是 null,就会创建一组属性。


     回页首


    结束语

    本文的介绍很简短。MochiKit 和 MochiKit.DOM 的功能远比这里提到的多,但我相信对于说明一个好的包装器能够在多大程度上简化 W3C DOM 调用已经足够了。虽然仅仅是管中窥豹,但也能看到 MochiKit.DOM 小心地将实际传递给其函数的参数转化成该函数使用的形式。比如,命名 id 属性的字符串通常与节点本身能够互换。在需要的时候可直接使用序列和迭代器。

    撰写本文过程中发现的另一个便利之处是称为 FireBug 的 Firefox 插件(请参阅参考资料)。本文不打算讨论,不过 FireBug 为一般的 JavaScript、XML 和 Web 页面调试提供了一个丰富的环境。也许 FireBug 中最好的特性是其交互控制台支持试验 JavaScript 命令(比方说,包括 MochiKit 的改进),其方式和在 Python 交互外壳中试验命令相同。此外,FireBug 还包括一个调试器和一个查看器(能够查看当前 DOM 和分析 XMLHttpRequest() 结果,从而理解 Ajax 应用程序)。


       收藏   分享  
    顶(0)
      




    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/2/4 17:02:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 DTD/XML Schema 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/19 21:17:15

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    78.125ms