Java解析XML ~~系列3

一列简单的Java对象
  对于更加复杂的XML文档,我们需要映射一系列的对象到Java。映射一系列对象就像做酒吧服务生一样:当一个服务生要倒满一排啤酒时,他通常让酒桶龙头一直开着,他则只是讯速地把杯子依次接到龙头下面。这正是我们捕获一系列对象时所要做的。我们无法控制到来的SAX事件;它们就像不能关闭的龙头里流出来的啤酒一样。为了解决问题,我们需要提供空的容器,让它们充满,不停的替换它们。
  我们下一个例子说明这一技术。用一个XML文档表示一个虚拟的定购客户,我们将把代表一系列定购商品的XML映射到一个Java的定购商品向量表中。实现这一想法的关键是“当前的商品”。每次我们得到一个事件表明一件新的定购商品(OrderItem标签的startElement),我们就创建一个空的order-item对象,将它加入定购商品列表中,并以它为当前定购商品。余下的工作由XML解析器完成。
  首先,这里有代表我们的虚拟顾客的XML文档:
  <?xml version="1.0"?>
  <CustomerOrder>
   <Customer>
   <FirstName> Bob </FirstName>
   <LastName> Hustead </LastName>
   <CustId> abc.123 </CustId>
   </Customer>
   <OrderItems>
   <OrderItem>
   <Quantity> 1 </Quantity>
   <ProductCode> 48.GH605A </ProductCode>
   <Description> Pet Rock </Description>
   <Price> 19.99 </Price>
   </OrderItem>
   <OrderItem>
   <Quantity> 12 </Quantity>
   <ProductCode> 47.9906Z </ProductCode>
   <Description> Bazooka Bubble Gum </Description>
   <Price> 0.33 </Price>
   </OrderItem>
   <OrderItem>
   <Quantity> 2 </Quantity>
   <ProductCode> 47.7879H </ProductCode>
   <Description> Flourescent Orange Squirt Gun </Description>
   <Price> 2.50 </Price>
   </OrderItem>
   </OrderItems>
  </CustomerOrder>
  又是我们的简单顾客类:
  package common;
  import java.io.*;
  // Customer是一个包含一名虚拟顾客的属性的简单类。
  // 它有一个简单的方法把自已打印到一个打印流。
  public class Customer {
   // Customer成员变量
   public String firstName = "";
   public String lastName = "";
   public String custId = "";
   public void print( PrintStream out ) {
   out.println( "Customer: " );
   out.println( " First Name -> " + firstName );
   out.println( " Last Name -> " + lastName );
   out.println( " Customer Id -> " + custId );
   }
  }
  Next, a simple class to represent an order item:
  package common;
  import java.io.*;
  // Customer是一个包含一名虚拟顾客的属性的简单类。
  // 它有一个简单的方法把自已打印到一个打印流。
  public class OrderItem {
   // OrderItem member variables.
   public int quantity = 0;
   public String productCode = "";
   public String description = "";
   public double price = 0.0;
   public void print( PrintStream out ) {
   out.println( "OrderItem: " );
   out.println( " Quantity -> " + Integer.toString(quantity) );
   out.println( " Product Code -> " + productCode );
   out.println( " Description -> " + description );
   out.println( " price -> " + Double.toString( price ) );
   }
  }
  现在,我们把注意力转移到SAX解析器例四,它将映射顾客和商品:
  import org.xml.sax.*;
  import org.xml.sax.helpers.*;
  import java.io.*;
  import java.util.*;
  import common.*;
  public class Example4 extends DefaultHandler {
   // 用于收集customer的XML数据的本地Customer变量
   private Customer cust = new Customer();
   // 定购对象的本地向量表...
   private Vector orderItems = new Vector();
   // 当前定购对象的本地引用...
   private OrderItem currentOrderItem;
   // 用于从"characters" SAX事件中收集数据的缓存。
   private CharArrayWriter contents = new CharArrayWriter();
   // 重载DefaultHandler类以拦截SAX事件的方法。
   //
   // 头于所有有效事件的详细内容,参见org.xml.sax.ContentHandler。
   //
   public void startElement( String namespaceURI,
   String localName,
   String qName,
   Attributes attr ) throws SAXException {
   contents.reset();
   // 新添加的代码...
   if ( localName.equals( "OrderItem" ) ) {
   currentOrderItem = new OrderItem();
   orderItems.addElement( currentOrderItem );
   }
   }
   public void endElement( String namespaceURI,
   String localName,
   String qName ) throws SAXException {
   if ( localName.equals( "FirstName" ) ) {
   cust.firstName = contents.toString();
   }
   if ( localName.equals( "LastName" ) ) {
   cust.lastName = contents.toString();
   }
   if ( localName.equals( "CustId" ) ) {
   cust.custId = contents.toString();
   }
   if ( localName.equals( "Quantity" ) ) {
   currentOrderItem.quantity = Integer.valueOf(contents.toString().trim()).intValue();
   }
   if ( localName.equals( "ProductCode" ) ) {
   currentOrderItem.productCode = contents.toString();
   }
   if ( localName.equals( "Description" ) ) {
   currentOrderItem.description = contents.toString();
   }
   if ( localName.equals( "Price" ) ) {
   currentOrderItem.price = Double.valueOf(contents.toString().trim()).doubleValue();
   }
   }
   public void characters( char[] ch, int start, int length )
   throws SAXException {
   contents.write( ch, start, length );
   }
   public Customer getCustomer() {
   return cust;
   }
   public Vector getOrderItems() {
   return orderItems;
   }
   public static void main( String[] argv ){
   System.out.println( "Example4:" );
   try {
   // 创建SAX 2解析器...
   XMLReader xr = XMLReaderFactory.createXMLReader();
   // 安装ContentHandler...
   Example4 ex4 = new Example4();
   xr.setContentHandler( ex4 );
   // 解析文件...
   xr.parse( new InputSource(
   new FileReader( "Example4.xml" )) );
   // 将customer显示到标准输出...
   Customer cust = ex4.getCustomer();
   cust.print( System.out );
   // 把所有的定购商品显示到标准输出...
   OrderItem i;
   Vector items = ex4.getOrderItems();
   Enumeration e = items.elements();
   while( e.hasMoreElements()){
   i = (OrderItem) e.nextElement();
   i.print( System.out );
   }
   }catch ( Exception e ) {
   e.printStackTrace();
   }
   }
  }
  这里是我们的Customer与OrderItems对象产生的输出:
  Example4:
  Customer:
   First Name -> Bob
   Last Name -> Hustead
   Customer Id -> abc.123
  OrderItem:
   Quantity -> 1
   Product Code -> 48.GH605A
   Description -> Pet Rock
   price -> 19.99
  OrderItem:
   Quantity -> 12
   Product Code -> 47.9906Z
   Description -> Bazooka Bubble Gum
   price -> 0.33
  OrderItem:
   Quantity -> 2
   Product Code -> 47.7879H
   Description -> Fluorescent Orange Squirt Gun
   price -> 2.5
  当XML文档的结构变得更复杂时,真正的因难是管理创建用于容纳SAX 事件所产生的数据流的空对象。对于简单的对象容器,这个管理工作并不复杂。但是,我们正是要开发一种复杂嵌套的容器,比方容器的容器和包含拥有容器成员对象的容器。
Tags: 

延伸阅读

最新评论

发表评论