技巧:使用SAXTransformerFactory--利用XSLT实现更好的灵活性和方便

2002-8-21 13:54:33【作者】 畅享网 【进入论坛】
广告

技巧:使用SAXTransformerFactory
 
 --利用XSLT实现更好的灵活性和方便


Benoit Marchal(bmarchal@pineapplesoft.com

顾问,Pineapple Software

2001 年 8 月

在这篇详细的技巧说明中,Benoit Marchal 说明了当保存 XML 文件时,SAXTransformerFactory — 直接在 XSLT 处理器中提供 SAX 事件的类 — 如何带给您更好的灵活性。几段可重用 Java 代码样本演示了该技术,这些代码样本需要使用 TrAX。

我使用的大多数 Java 应用程序都将其数据保存成 XML 格式。我喜欢 XML 的原因之一就是使用 XSLT 后处理文件很容易。例如,我通常以 XML 格式保存原始数据,并使用一两个样式表来生成 HTML、PDF 和 SVG 格式的报表。

我过去常常使用单独的应用程序来后处理文件,但用户逐渐要求使用一个集成的解决方案来模拟他们熟悉的商业生产应用程序中的“导出...”或“另存为...”菜单命令。

在搜寻好的解决方案的过程中,我最终找到了 SAXTransformerFactory。对于本讨论的其余部分,我假设您已经了解 SAX 语法分析、TrAX(XSLT 处理器的标准 Java API)和 XSLT。如果需要了解一些背景知识,请参阅参考资料以获取参照。

SAX 和 XSLT 处理器

您知道,SAX 语法分析要求您编写处理语法分析器事件的 ContentHandler。SAXTransformerFactory 实质上是将 XSLT 处理器转换成 ContentHandler。

您也许会问,为什么要那么麻烦?毕竟,TrAX 还支持 SAXSource 以便与 SAX 语法分析器结合。的确,如果使用成熟的 SAX 语法分析器,SAXTransformerFactory 就没什么用处了。但我发现,在没有语法分析器的情况下,从我的应用程序生成那些事件还是合算的。

请考虑图 1。其中发生了两件事:首先应用程序将数据写入 XML 文件,然后 XSLT 处理器(另一个应用程序)将数据整理成 HTML 格式。

图 1. 典型的 XML 和 XSLT 应用程序


如果将 XSLT 处理器集成到应用程序中,会发生什么?仍必须向它提供 XML 文档。为满足该目的,大多数应用程序都使用临时文件或字符串。我相信, ContentHandler 更具有吸引力。

的确,在第一种情况中,应用程序编写了 XSLT 处理器可以立即分析的 XML 文档(通常通过 SAX 语法分析器)。如图 2 所示,如果应用程序发出 SAX 事件本身,是否会更有效呢?在图 2 中,应用程序并没有写到文件中,而是直接调用处理器的 ContentHandler,有效地模拟了语法分析器。

第二种模式更有效,它使用较少的内存,并省去了创建和删除临时文件的烦恼。

图 2. 应用程序模拟语法分析器


模拟语法分析器

此外,它使模拟语法分析器变得很简单。应用程序很可能已经拥有了写开始标记、结束标记和转义符的功能。它可以将它们替换成 SAX 等价物,分别替换成 startElement()、endElement() 和 characters()。换句话说,代码 writer.write("") 变成
contentHandler.startElement ("
http://www.psol.com/2001/08/dw/tip","key","ps:key",attributes)。它也许会更长,但写起来不会很费劲。

asXML() 方法将 Properties 对象写成 XML 格式,但它没有写到文件中;而是使用 ContentHandler。

如果没有名称空间,代码会很简单。经验显示发出 startPrefixMapping() 并将 xmlns 声明当作常规属性传送会更安全。

清单 1. asXML() 模拟 SAX 语法分析器

protected static void asXML(Properties properties,ContentHandler contentHandler)

  throws SAXException

{

   AttributesImpl attributes = new AttributesImpl();

  contentHandler.startDocument();

   contentHandler.startPrefixMapping("ps",

       "http://www.psol.com/2001/08/dw/tip");

   attributes.addAttribute("","ps","xmlns:ps","CDATA",

       "http://www.psol.com/2001/08/dw/tip");

   contentHandler.startElement("http://www.psol.com/2001/08/dw/tip",

       "properties","ps:properties",attributes);

   attributes.clear();

   Enumeration enumeration = properties.propertyNames();

   while(enumeration.hasMoreElements())

   {

      String name = (String)enumeration.nextElement(),

             value = properties.getProperty(name);

      contentHandler.startElement("http://www.psol.com/2001/08/dw/tip",

           "property","ps:property",new AttributesImpl());

      contentHandler.startElement("http://www.psol.com/2001/08/dw/tip",

           "key","ps:key",attributes);

      contentHandler.characters(name.toCharArray(),0,name.length());

      contentHandler.endElement("http://www.psol.com/2001/08/dw/tip",

           "key","ps:key");

      contentHandler.startElement("http://www.psol.com/2001/08/dw/tip",

           "value","ps:value",attributes);

      contentHandler.characters(value.toCharArray(),0,value.length());

      contentHandler.endElement("http://www.psol.com/2001/08/dw/tip",

           "value","ps:value");

      contentHandler.endElement("http://www.psol.com/2001/08/dw/tip",

           "property","ps:property");

   }

   contentHandler.endElement("http://www.psol.com/2001/08/dw/tip",

       "properties","ps:properties");

   contentHandler.endPrefixMapping("ps");

   contentHandler.endDocument();

}

调用 XSLT 处理器

要对 asXML() 的结果应用样式表,请使用清单 2 中的代码。首先,就象常规 TrAX 一样,创建 TransformerFactory。接着,通过调用 getFeature() 确保它与 SAXTransformerFactory 兼容,如果成功,将它强制类型转换成 TransformerFactory。

最后,使用 newTransformerHandler() 来请求 TransformerHandler 对象。该方法使用样式表的 URI 作为参数。TransformerHandler 实现了 ContentHandler,并且可以作为参数传递给 asXML()。

如果熟悉 TrAX,您也许想要知道在哪里调用 transform()。答案是不必这样做。TransformerHandler 在接受 SAX 事件时会应用样式表。

HTML 样式表

TransformerHandler 是常规 XSLT 处理器;它对样式表没有限制。

Key Value 
 
整理成原始 XML

如果不想要 HTML,而更喜欢原始 XML 文档,会发生什么?最简单的解决方案是提供一个额外的样式表,该样式表不修改输入。

高性能的序列化程序

如果您关心性能,那么会首选使用序列化程序。序列化程序是 ContentHandler,它将其输入写入 XML 文档。如果您的 XSLT 处理器是 Xalan,请使用 org.apache.xalan.serialize.Serializer。由于它是 ContentHandler,它会直接使用 asXML()。

SAXTransformerFactory 的其它应用程序

如果分几个阶段来处理 XML 文档,SAXTransformerFactory 也会有用。例如,我最近在所谓的“管道”中实现了它,该“管道”通过 XSLT 样式表和定制过滤器的组合来转换输入文档。

参考资料

Xalan 是支持 SAXTransformerFactory 的开放源码 XSLT 处理器

SAX,功能强大的 API,这是从作者著作 XML by Example 第二版中摘录的一章,Que Publishing 将在 2001 年 9 月发行该书,该书详细地讨论了 SAX。

Brett McLaughlin 撰写的 Sun's Java API for XML Parsing, Version 1.1,此文介绍了结合了 SAX、TrAX 和 DOM 的 JAXP 1.1。请转向 Sun 公司的官方网页 Java Technology and XML

David Mertz 撰写的使用 XSLT 转换 DocBook 文档是学习 XSLT 的一个好的起点。

Michael Kay 撰写的 Saxon: 剖析 XSLT 处理器是关于 XSLT 处理器最有趣的讨论。

IBM FAQs 回答了关于 XML 和 IBM 产品的常见问题。

The XML certification guidelines 提供了掌握在 IBM Certified Developer Program 中进行 XML 开发需要的详细技术。

关于作者
 

Beno顃 Marchal 是住在比利时那慕尔的顾问和作家。他是 XML by Example Applied XML SolutionsXML and the Enterprise 的作者。同时是 Gamelan 的专栏作家。marchal.com 上有其最新项目的详细信息。可以通过 bmarchal@pineapplesoft.com 与 Beno顃 联系。

作者在此向 Fr閐閞ic George 表示特别感谢,因为是他向作者介绍了SAXTransformerFactory

 

如果您希望与本文章的作者或其所在机构,进一步交流,请联系:畅享网 姜小姐
jill.jiang@amt.com.cn | 021-51096826-112 | 在线联系
企业信息化杂谈[原创]企业信息化的价值点探讨

我们都知道,信息技术是企业经营管理目标的手段之一。通俗点说,信息技术对企业而言就是一个工具。

IT管理—君无心[原创]文档信息安全简谈

文档信息安全工作要根据自身的需求来具体部署,也就是量体裁衣。信息安全等级划分、企业商业机密等是不同的概念。

第二届中国管理软件与IT服务年会—2..

“第二届中国管理软件与IT服务年会”于2008年7月23日-25日举行,由AMT集团与畅享网共同主办,无锡扬名高新技术产业园特别赞助支持。

CIO职场,强者生存?

在2008年,我们将继续看到CIO向商业运营方向发展。与此同时,我们也会看到商业管理人员将与技术管理人员一起竞争CIO岗位。 IT领导者的就职机会虽有不少,但其难度将会大幅提高。2……