清单 4.从 XML 文件构建 AXIOM
File file = new File("line-item.xml");
FileInputStream fis = new FileInputStream(file);
XMLInputFactory xif = XMLInputFactory.newInstance();
XMLStreamReader reader = xif.createXMLStreamReader(fis);
StAXOMBuilder builder = new StAXOMBuilder(reader);
OMElement lineItem = builder.getDocumentElement();
lineItem.serializeWithCache(writer);
writer.flush();
OMAttribute quantity = lineItem.getFirstAttribute(
new QName("http://openuri.org/easypo", "quantity"));
System.out.println("quantity= " + quantity.getValue());
OMElement price = lineItem.getFirstChildWithName(
new QName("http://openuri.org/easypo", "price"));
System.out.println("price= " + price.getText());
OMElement description = lineItem.getFirstChildWithName(
new QName("http://openuri.org/easypo", "description"));
System.out.println("description= " + description.getText());
AXIOM 最好的一点是,努力在延迟构造这类高端技术上提供用户友好的 API。但是要充分发挥其潜能,必须了解底层体系结构。
进一步考察 AXIOM
缓冲是 AXIOM 的核心概念之一。但是,要理解缓冲必须在树的延迟构造和 AXIOM API 上下文中来思考。AXIOM 提供多种访问底层 XML Infoset 的 API。上面使用的是基于树的 API,所有其他竞争的对象模型如 DOM 和 JDOM 都提供了这样的 API。但是,AXIOM 还允许通过 SAX 或 StAX API 访问信息。如图 1 所示。

图 1. AXIOM,输入和输出
如果要使用一种 XML 解析 API,为何还要构造对象模型呢?为了使用不同 API 访问对象模型的不同部分。比如,考虑 SOAP 栈的情况:SOAP 消息在被目标服务消费之前可能会经过多个处理程序的处理。这些处理程序通常使用基于树的 API(特别是 SOAP with Attachments API for Java,或 SAAJ)。服务实现还可能使用数据绑定工具将 SOAP 消息负荷中的 XML 文档转化成对象,如 POJO。因为用户不使用基于树的对象模型来访问这部分文档,所以构造完整的树会因为数据重复而浪费内存。最直接的解决方法是向数据绑定工具公开底层的原始 XML 流。这就是 AXIOM 的闪光之处。
