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

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

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 5977 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: XML 问题 #2 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     anchen0617 帅哥哟,离线,有人找我吗?双子座1983-6-17
      
      
      威望:5
      等级:大二(研究C++)
      文章:281
      积分:3413
      门派:XML.ORG.CN
      注册:2004/10/17

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

    在 David Mertz 新的有关“XML 问题”专栏的第二部分 -- 也是他对在 XML 和 Python 之间创建更加无缝的集成而不断进行探求的一部分 -- 中介绍了 xml_objectify 模块。 David 描述了如何使用 xml_objectify,以及将该“Python 化”模块用于作为对象的 XML 文档使用的好处。

    项目介绍
    XML 问题 #1 介绍了在 XML 和 Python 之间创建更加无缝和自然集成的项目。参考资料部分提供了到其它 developerWorks 文章的链接,在这些文章中,我讨论了一些常规 Python 编程技术和其它有关 XML/Python 的主题。

    获得兼容的 XML-SIG 更新
    XML-SIG 发行版在 beta 版本中更改相当频繁。这些更改往往影响到 xml_objectify 的功能。因此,可以从参考资料中下载已知与 xml_objectify 兼容的 XML-SIG 版本。


    当 XML-SIG 发行版正式发行并且/或者当 XML 软件包作为正式 Python 发行版的一部分时,当前的 xml_objectify 将进行更新以对正式发行版使用。有关当前 xml_objectify 的详细信息,请参阅参考资料。

    因为在 XML 和 Python 之间存在不对称性,所以该项目 -- 至少在最初时 -- 包含两个单独的模块: xml_pickle 和 xml_objectify,前者用于以 XML 表示任意的 Python 对象,后者用于将 XML 文档本机表示为 Python 对象。本文主要讨论 xml_objectify。

    在 Python 中,例如 xmllib、xml.sax、pyxie 和 xml.dom 这样的模块和软件包提供了处理 XML 社区中一些公共 XML 文档的方法。您可能熟悉应用于其它编程语言的类似模块和库。实际上,许多模块都基于语言中性的 XML 标准,它们通常实现以 XML 为中心的处理文档和对象的方法。

    常规 XML 协议的 Python 实现提供了以不同方法进行编程的灵活性。例如,可以使用如 DOM 这样的可移植标准,这样,使用一种语言的程序员可以方便地对以另一种语言编写的面向 DOM 的代码进行操作。不过, Python 程序员有时可能宁愿以更类似于“正常”Python 的方法进行编码。在许多情况下,XML 概念性框架看起来似乎更接近于 Python,而不是 Python 的一个组成部分。因此,我开发了一系列用于 XML 文档的“Python 化”模块。

    向前一步:如何使用 xml_objectify
    使用 xml_objectify 很简单,而且在模块 docstring 注释中有详细记载。让我们快速浏览一下一些样本代码:

    从 XML 文档创建 Python 对象

    from xml_objectify import XML_Objectify
    xml_obj = XML_Objectify('address.xml')
    py_obj = xml_obj.make_instance()

    如您所见,从常规 XML 文档创建本机 Python 对象有两个步骤。首先创建一个类似于 DOM 的中间工厂对象(即用于创建其它对象的对象)。然后,从 XML_Objectify 实例中生成一个或多个 Python 对象实例。请注意,应该使用 xml_pickler 来处理特殊的 PyObjects.dtd 格式文档。(请参阅 XML 问题 #1 了解有关 xml_pickle 的信息。)

    也可以在同一行上执行这两步。例如:

    在一行中创建 XML/Python 对象

    py_obj = XML_Objectify('address.xml').make_instance()

    当然,在后一种情况中,不保留工厂对象来产生更多本机对象,而且也将清除包含它的完整 DOM 实例的 ._dom 数据成员。

    为进行比较,下例显示了使用 Python 创建 DOM 对象有多简单:

    从 XML 文档创建 DOM 对象

    from xml.dom.utils import FileReader
    dom_obj =
    FileReader().readXml(open('address.xml'))

    FileReader().readXml() 需要实际的文件对象,而 XML_Objectify() 可以接受文件对象或者普通文件名。在这两种情况下,创建对象是一个两行的操作。

    使用 xml_objectify 模块和 xml.dom 软件包的不同之处在于最后得到的对象类型。Python DOM 对象是真正的 Python 对象,但它的属性和方法与原始 XML 文档的数据和结构对应程度并不象 XML_Objectify 对象那样接近。Python DOM 对象的属性通常嵌套了 .children 列表,这些列表在语义上并没有什么太大的帮助。要访问样本文档中同一个 XML 属性,可以使用 xml_objectify 的第一行,也可以使用 DOM 的以下四行。下面显示了这四行:

    使用 [xml.dom] 和 [xml_objectify] Python 对象

    print py_obj.person[1].address.city
    print dom_obj.get_childNodes()[1].get_childNodes()[3].\

    get_childNodes()[3].get_attributes()['city'].value
    print dom_obj._node.children[1].children[3].children[3].\
          attributes['city'].children[0].value

    DOM 树是按严格定序的节点树组织起来的。枚举这些节点并不困难,但要引用其中特定的节点就非常麻烦了。如果有些节点是空白文本和处理指令节点(您几乎不太关心它们),情况就更糟糕了,因此在节点列表中查找子标记多半要反复试验。在上例中,访问本机属性(例如 .children)和 DOM 样式的方法(例如 .get_childNodes())用在不同的 print 语句中。使用这两种方法时,要知道引用了 XML 文档中哪些数据都很不容易。

    相反,上例中第一个 print 语句非常好地文档化了自己。唯一需要注意的一个小问题是必须使用 Python 的基于 0 的列表索引。除此以外,这行只说: "Print the city of the address of the second person in the addressbook." ("New York" 是每个语句都要打印的。)为进一步帮助您理解,py_obj.__class__ 就是 "addressbook",与 XML 文档的根元素对应。每个不仅包含简单文本的属性都是特定类的实例;这个特定类是根据定义它的 XML 标记命名的。

    如您所见,xml.dom 使用起来通常比较难,它的语法也很模糊。本机 Python 对象使用起来就简单得多。请注意,xml_objectify 在内部广泛利用了 DOM。实际上,每个 XML_Objectify 实例都包含了一个 ._dom 属性,该属性是打开的 XML 文档的 DOM 树。不过,创建的实例 .make_instance 不包含任何 DOM,它是根标记的类类型。

    设计注意事项、限制和告诫
    代码自测
    使用 xml_objectify,可以利用所有现有的常规函数。pyobj_printer() 是个样本常规函数,其中包括 xml_objectify 模块。该函数产生所有 Python 对象可读的递归表示。通过将 XML 文档表示为本机 Python 文档,可以重用现有的、以抽象方式处理 Python 对象的函数。当然,DOM 对象勉强算得上是 Python 对象,但要对这些对象以有用的方式使用常规函数就比较困难。例如,因为 DOM 对象的属性嵌套了 .children 列表,所以使用例如 pyobj_printer() 这样的常规函数将不会产生非常有用的输出。

    使用类行为的技巧
    xml_objectify 提供了一种非常精妙的技巧,使用这种技巧,只有在没有定义类的情况下才动态地为属性值定义类。这可以让您定义具有复杂行为的类,和可以放入特定 XML 文档内容的属性。假设类 person 使用各种方法(如果需要,包括 .__init__() 方法)进行了预定义。导入到上例中 XML 地址簿中的每个 "person" 都将具有给予它的所有行为,包括对放入实例中的数据的操作方法。当然,如果在对文档运行 XML_Objectify() 之前没有进行预定义,类就只是用于在实际 XML 中定义的属性的容器。

    字符标记处理
    XML 标记通常是块级别的,但某些也属于字符级别。依我看,自然的 Python 表示在每种情况下各不相同。块级别的子标记易于通过父标记的属性表示,父标记是根据子标记命名的。子标记属性的值是新 Python 对象,它也是根据子标记命名的类型。例如,person 从层次上角度上考虑,可以具有 address 和 misc-info。使用 Python,可以用 person.address 和 person.misc_info 来引用它们。

    使用字符级别的标记时,标记的内容是文本数据和这些数据的标记(常常是排版方面的)的混合体,子标记在层次结构上不是父标记中的一部分。例如, misc_info 对象实际上没有 ital 属性。那么,下面的 XML 类型应该如何表示呢?

    <misc-info>One of the <ital>most</ital> talented
    actresses on TV.</misc-info>

    xml_objectify 将一个称为 ._XML 的特殊属性添加到看起来包含标记字符数据的对象/标记。这个属性在标记中包含文字 XML。例如,如果给定的嵌套对象有 ._XML 属性,pyobj_printer() 函数显示这个文字 XML 而不是递归属性。不过,仍然执行标准递归子标记-对象的创建,因此可以知道哪些属性和结构最适当。

    本机 Python 对象只包含根文档
    许多 XML 文档都伴随着标记和字符数据内容提供处理指令和/或注释。不过,由 XML_Objectify 对象的 .make_instance() 方法创建的本机 Python 对象只包含文档根标记的内容。而且将忽略 XML 注释;只表示标记属性和字符数据。

    在上面的从 XML 文档创建 Python 对象示例中,如果保留原始的 XML_Objectify 对象 (xml_obj),可以访问它的 .processing_instruction 属性,甚至可以访问它的 ._dom 属性来查看本机 Python 对象忽略了什么。

    属性类型简化
    所有 XML 属性都转换成字符串类型的 Python 对象属性。当前,Python 不表示属性的 XML 枚举或数字类型。在以后的版本中可能加入这样的能力,但这些通常需要 DTD,而 xml_objectify 不具有 DTD。

    子标记属性
    XML 子标记或者由对象类型的 Python 属性表示,或者由这种对象的列表表示,这要取决于是一个还是几个相同类型的子标记。即由包含相同类型多个子标记的特定标记决定。例如,在上面第一个 address.xml 示例中,一个人的联系信息可能包括 1 个家庭电话,而另一个人的联系信息可能包括 0 个或几个。相应地,一些 contact_info 对象没有 .home_phone 属性,一些具有包含一个 home_phone 对象的 .home_phone 属性,还有一些具有包含许多 home_phone 对象的 .home_phone 属性。尽管使用 DTD 的情况下有可能施加更多法则,但我认为,Python 应用程序需要这种动态能力。

    Python 名称空间限制
    要知道 Python 名称空间比 XML 名称空间小。因此,有时要修改标记或属性的 XML 名称。xml_objectify 将破折号、冒号和镑值/散列标志转换成下划线。该模块不处理任何其它名称空间冲突。例如,如果 XML 文档有标记 <spam-eggs>、<spam_eggs>、 <spam:eggs> 和 <spam#eggs>,那么 xml_objectify 所创建的 Python 对象就不能正确表示 XML 文档。在大多数情况下,这不是问题,因为人们不希望得到的 XML 文档具有这些冲突的标记。

    xml_objectify 的前景如何?
    目前,还不能将本机 Python 对象转回带有与读取的 XML 文档相同结构的 XML 文档。因为 xml_objectify 故意舍去 XML 文档中有关顺序的信息来产生更易理解的 Python 对象,所以可能发生问题。Python 属性没有任何预先确定的顺序,但需要 XML 标记和属性以特定的顺序排列。即使不需要 XML 标记来以特定的顺序出现,顺序在语义上还是很重要。(请注意在重复公共子标记的情况下,Python 列表维护顺序。)为了转换回 XML,我们需要或者选择任意顺序,或者保留本机 Python 对象中的顺序信息,使得它看上去不太象 Python。

    重新构造 Python 对象中已删除的信息的一个选择是在转换回 XML 时强制 DTD。即使我使用这一做法的,但在如何处理 Python 运行时添加、删除或修改的属性时,问题仍然存在。修改 Python 对象可能导致有些部分不符合原始 XML 文档的 DTD。不过,如果用户有特定需要,我会将这些能力添加到 xml_objectify。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    xml这门语言太好了,我们共同努力吧!!!!!

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

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

     *树形目录 (最近20个回帖) 顶端 
    主题:  XML 问题 #2(9006字) - anchen0617,2004年11月13日

    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    78.125ms