跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

技巧: 用于灵活处理的 SAX 过滤器

创建 XML 处理链

Uche Ogbuji (uche.ogbuji@fourthought.com), 首席顾问, Fourthought, Inc.
Uche Ogbuji 的照片
Uche Ogbuji 是 Fourthought Inc.的顾问兼共同创始人,该公司是专为企业知识管理提供 XML 解决方案的软件供应商和咨询公司。Fourthought 开发了 4Suite,它是一个用于 XML、RDF 和知识管理应用程序的开放源码平台。Ogbuji 先生是一位出生于尼日利亚的计算机工程师和作家,他现在美国科罗拉多州博耳德(Boulder)生活和工作。可以通过 uche.ogbuji@fourthought.com与 Ogbuji 先生联系。

简介: SAX 过滤器允许您从简单的独立模块构造复杂的 XML 处理。在这篇技巧文章中,Uche Ogbuji 介绍了这一重要的 XML 处理技术。

发布日期: 2003 年 7 月 01 日
级别: 中级
访问情况 : 1120 次浏览
评论: 


Simple API for XML(SAX)是一种非常有效的 XML 处理方法。在 SAX 处理中,解析器向应用程序传递一个代表 XML 内容的事件流。SAX 的一个重要方面在于用户创建 SAX 过滤器的能力,这种过滤器接受 SAX 事件流,然后传递经过修改的流。例如,有些 XML 化的 HTML 使用了不好的 HTML 习惯(如 <center> ),您可能会使用 SAX 过滤器来将其作为输入,然后传递正确的 XHTML 形式(如 <div style="align: center"> )。随后可以非常方便地将这类过滤器重用于各种应用程序,因为它执行的任务单一且专一,并有意和系统上行分开,也使下行和过滤器分开。

如果您不熟悉 SAX,那么请参阅 参考资料中所提及的一些入门资料。

一个选择英文部分的 SAX 过滤器

XML 1.0 允许您使用 xml:lang 属性逐个元素地指定元素内容中所使用的语言(请在 参考资料中参阅我以前的技巧文章“Localization within a document format”,以获取更多这方面的信息)。我将在这里用 Python 创建一个 SAX 过滤器,它将所有已知的非英文内容剥去;换句话说,过滤器保留所有不带 xml:lang 指定或带有以 en 打头的指定的内容。

大多数基于对象的 SAX 系统中的 SAX 过滤器实现都是作为专门的处理程序类。所有 SAX 处理程序都从上行源接受 SAX 事件,而这个上行源可能直接就是 XML 解析器。SAX 过滤器也是 SAX 处理程序类,但它也有自己的特点,即它所做的操作是通过对给定的实例调用适当的方法来生成进一步的 SAX 事件,这个实例就是过滤器链中的下行 SAX 处理程序。 清单 1是一个 SAX 过滤器实例。


清单 1. 一个除去非英文内容的过滤器(en-filter.py)
import xml.sax
from xml.sax.saxutils import XMLFilterBase, XMLGenerator
#Define constants for the two states we care about
ALLOW_CONTENT = 1
SUPPRESS_CONTENT = 2
class EnglishOnlyFilter(XMLFilterBase):
    def __init__(self, upstream, downstream):
        XMLFilterBase.__init__(self, upstream)
        self._downstream = downstream
        return
    def startDocument(self):
        #Set the initial state, and set up the stack of states
        self._state = ALLOW_CONTENT
        self._state_stack = [ALLOW_CONTENT]
        return
    def startElement(self, name, attrs):
        #Check if there is any language attribute
        lang = attrs.get('xml:lang')
        if lang:
            #Set the state as appropriate
            if lang[:2] == 'en':
                self._state = ALLOW_CONTENT
            else:
                self._state = SUPPRESS_CONTENT
        #Always update the stack with the current state
        #Even if it has not changed
        self._state_stack.append(self._state)
        #Only forward the event if the state warrants it
        if self._state == ALLOW_CONTENT:
            self._downstream.startElement(name, attrs)
        return
    def endElement(self, name):
        self._state = self._state_stack.pop()
        #Only forward the event if the state warrants it
        if self._state == ALLOW_CONTENT:
            self._downstream.endElement(name)
        return
    def characters(self, content):
        #Only forward the event if the state warrants it
        if self._state == ALLOW_CONTENT:
            self._downstream.characters(content)
        return
if __name__ == "__main__":
    parser = xml.sax.make_parser()
    #XMLGenerator is a special SAX handler that merely writes
    #SAX events back into an XML document
    downstream_handler = XMLGenerator()
    #upstream, the parser, downstream, the next handler in the chain
    filter_handler = EnglishOnlyFilter(parser, downstream_handler)
    import sys
    #The SAX filter base is designed so that the filter takes
    #on much of the interface of the parser itself, including the
    #"parse" method
    filter_handler.parse(sys.argv[1])

Python 提供了一个实用程序类 — XMLFilterBase ,可以从这个类派生 SAX 过滤器。我将 EnglishOnlyFilter 定义为过滤器,它获取一个上行 SAX 事件源(解析器或另一个过滤器)以及一个下行 SAX 过滤器或其它处理程序。许多 SAX 处理程序都充当状态机,即它们根据进入的事件流管理一些变量,并根据这些变量更改行为。 EnglishOnlyFilter 被设置为两种状态之一:一种状态是内容被传递给下行处理程序,而另一种状态是内容被阻截。这种状态在 self._state 实例变量中标记。状态最初设置为 ALLOW_CONTENT ,如果过滤器碰到一个表示非英文(可以根据标准语言代码规则检查值的前两个字符来做到这点)的 xml:lang 属性,状态就会改为 SUPPRESS_CONTENT

XML 语言规范是 限定了作用域的。请参阅 清单 2这个示例,可以从中看出这到底指的是什么。


清单 2. 带有多种语言的样本 XML 文件(listing2.xml)
<?xml version="1.0" encoding="utf-8"?>
<menu>
  <item id="A" xml:lang="en">Orange juice</item>
  <item id="A" xml:lang="es">Jugo de naranja</item>
  <item id="B" xml:lang="en">Toast</item>
  <item id="B" xml:lang="es">Pan tostada
    <note xml:lang="en">Wheat bread only, please</note>
  </item>
</menu>

在上面的示例中,字符串“Pan tostada”位于带有属性 xml:lang="es" 的元素的作用域内,因此它被标记为西班牙语字符串。但是,整个 note 元素被标记为英文内容,因为它的 xml:lang="en" 属性覆盖了前面的属性。这种作用域限定要求我在 SAX 过滤器中维持一个状态堆栈,即 self._state_stack 实例变量。准确地说, self._state_stack 变量使得 self._state 不再是必需的 — 我本可以从堆栈顶部读取当前状态 — 但是为了更加清晰,我还是将它留下了。对这个样本 XML 运行过滤器代码会产生下面的输出。

$ python en-filter.py listing2.xml
<menu>
  <item xml:lang="en" id="A">Orange juice</item>
  <item xml:lang="en" id="B">Toast</item>
  <note xml:lang="en">Wheat bread only, please</note>
</menu>


结束语

SAX 的速度已经很快了,而 SAX 过滤器又增加了一些灵活性。随着您越来越多地使用 SAX,您可能会发现您有了一个给人留下深刻印象的 SAX 过滤器库,它可以用于各种处理任务。


参考资料

关于作者

Uche Ogbuji 的照片

Uche Ogbuji 是 Fourthought Inc.的顾问兼共同创始人,该公司是专为企业知识管理提供 XML 解决方案的软件供应商和咨询公司。Fourthought 开发了 4Suite,它是一个用于 XML、RDF 和知识管理应用程序的开放源码平台。Ogbuji 先生是一位出生于尼日利亚的计算机工程师和作家,他现在美国科罗拉多州博耳德(Boulder)生活和工作。可以通过 uche.ogbuji@fourthought.com与 Ogbuji 先生联系。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML
ArticleID=21942
ArticleTitle=技巧: 用于灵活处理的 SAX 过滤器
publish-date=07012003
author1-email=uche.ogbuji@fourthought.com
author1-email-cc=uche.ogbuji@fourthought.com

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。