Java XML解析之 StAX

原帖http://blog.csdn.net/andyxhua/archive/2008/01/24/2063784.aspx

StAX:Streaming API for XML ,如同字面意思,是基于流的API,相对于传统的DOM和SAX,StAX在性能和易用性上取得了很好的平衡。StAX是基于SAX的,同样将XML作为一组事件来处理,不过与SAX不同的是,StAX是采用拉(Pull)的方式来处理事件, 允许应用程序从事件流中拉出事件,而不是提供从解析器中接收事件的回调程序程序。

StAX 包括两套处理 XML 的 API,分别提供了不同程度的抽象。一种是基于指针的 API, 提供应用程序把 XML 作为一个标记(或事件)流来处理,这是一种低层 API,效率高,抽象程度低。另一种是较为高级的基于迭代器的 API, 提供应用程序把 XML 作为一系列事件对象来处理,每个对象和应用程序交换 XML 结构的一部分,应用程序直接处理这些代表了XML结构一部分的事件对象。

StAX在JDK6中已经内置了,或许就是以后的标准。

下面以一个简单的例子示范基于指针的API的使用。例子说明:从一个xml结构的订单信息中parse出Java对象,修改这个对象,然后输出为一个xml文件。

一、xml文件内容

 

<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE po SYSTEM "src/sample.dtd" >
< po  id ="po121"  submitted ="2001-10-05"
    xmlns
="http://www.csdn.net" >
    
< billTo  id ="addr-1" >
        
< company > The Redzero Cop. </ company >
        
< street > Jianguo Road 1ST </ street >
        
< street > Building 1 </ street >
        
< city > Haidian </ city >
        
< state > Beijing </ state >
        
< postalCode > 100071 </ postalCode >
    
</ billTo >
    
< shipTo  href ="addr-1" />
    
< order >
        
< item  sku ="o318-BP"  quantity ="5" >
            
< description > J2EE programmic </ description >
        
</ item >
        
< item  sku ="o947-TI"  quantity ="12" >
            
< description > Java WEB Service </ description >
        
</ item >
        
< item  sku ="o008-PR"  quantity ="133" >
            
< description > C++ develop </ description >
        
</ item >
    
</ order >
</ po >

二、Java对象结构 

public   class  Order
{
    List items 
= new ArrayList();
    
public void addItem(Item item)
    
{
        items.add(item);
    }

    @Override
    
public String toString()
    
{
        StringBuffer buf 
= new StringBuffer();
        buf.append(
"order ");
        
for (Iterator itr = items.iterator();itr.hasNext();)
        
{
            Item item 
= (Item)itr.next();
            buf.append(
"item ");
            buf.append(
"sku=").append(item.getSku()).append(" ").append("quantity=").append(item.getQuantity()).append(" ")
            .append(
"description=").append(item.getDescription()).append(" ");
        }

        
return buf.toString();
    }
    
}


public   class  Item
{
    String sku;
    
int quantity;
    String description;
    
public String getDescription()
    
{
        
return description;
    }

    
public void setDescription(String description)
    
{
        
this.description = description;
    }

    
public int getQuantity()
    
{
        
return quantity;
    }

    
public void setQuantity(int quantity)
    
{
        
this.quantity = quantity;
    }

    
public String getSku()
    
{
        
return sku;
    }

    
public void setSku(String sku)
    
{
        
this.sku = sku;
    }

}

三、解析示例,注意代码注释

解析

 

     /**
     * 解析XML文档,把数据绑定到Java对象上
     * 
@param in
     * 
@return
     
*/

    
public  Order parse(InputStream in)
    
{
        Stack stack 
= new Stack();
        
try
        
{
            
//1.得到XMLStreamReader
            XMLInputFactory inputFactory = XMLInputFactory.newInstance();
            XMLStreamReader reader 
= inputFactory.createXMLStreamReader(in);
            
while (reader.hasNext())
            
{
                
//2.根据事件类型做相应的处理,对于多数应用来说,处理完成可以直接break,跳出循环,提高性能
                switch (reader.getEventType())
                
{
                
case XMLStreamReader.START_ELEMENT:
                    String name 
= reader.getLocalName();
                    
if ("order".equals(name))
                    
{
                        Order order 
= new Order();
                        stack.push(order);
                    }
 else if ("item".equals(name))
                    
{
                        Item item 
= new Item();
                        String sku 
= reader.getAttributeValue(0);
                        String quantity 
= reader.getAttributeValue(1);
                        item.setSku(sku);
                        item.setQuantity(Integer.parseInt(quantity));
                        stack.push(item);
                    }
 else if ("description".equals(name))
                    
{
                        String desc 
= reader.getElementText();
                        Item item 
= (Item) stack.pop();
                        item.setDescription(desc);
                        Order order 
= (Order) stack.peek();
                        order.addItem(item);
                    }

                    
break;
                }

                reader.next();
//获取下一个解析事件
            }

        }
 catch (XMLStreamException e)
        
{            
            e.printStackTrace();
        }

        
if (!stack.empty())
        
{
            
return (Order) stack.pop();
        }
 else
        
{
            
return null;
        }

    }

输出

     /**
     * 使用StAX接口输出XML文档,无法自动输出格式良好的文档,必须自己控制文档的排版
     * 
@param order
     * 
@return
     
*/

    
public  String write(Order order)
    
{
        StringWriter buffer 
= new StringWriter();
        
try
        
{
            
//1.得到XMLStrreamWriter
            XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
            
//修复名称空间前缀。
            
//对于任何在范围内不具有名称空间声明的属性,自动名称空间声明。
            
//如果元素或属性名称具有前缀,但没有绑定到任何名称空间 URI,则前缀将在序列化时被删除。
            outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces",    new Boolean(true));
            XMLStreamWriter writer 
= outputFactory.createXMLStreamWriter(buffer);
            
//2.设置默认命名空间
            writer.setDefaultNamespace("http://www.csdn.net");
            
//3.开始输出文档
            writer.writeStartDocument("UTF-8""1.0");
            writer.writeCharacters(
" ");//换行,让输出的xml好看一点
            
//输出DTD
            writer.writeDTD("<!DOCTYPE po SYSTEM "src/sample.dtd">");
            writer.writeCharacters(
" ");
            
            
//输出xml文档的元素,输出一个start,必须要输出一个相应的end
            writer.writeStartElement("po");//开始根元素po
            
//输出元素属性
            writer.writeAttribute("id""20080124001");
            writer.writeAttribute(
"submitted""2008-01-24");
            writer.writeCharacters(
" ");
            
            writer.writeStartElement(
"billTo");//开始billTo元素
            writer.writeAttribute("id""addr-1");
            writer.writeCharacters(
" ");
            writer.writeStartElement(
"company");
            writer.writeCharacters(
"CSDN");
            writer.writeEndElement();
            writer.writeCharacters(
" ");
            writer.writeStartElement(
"street");
            writer.writeCharacters(
"朝阳区望京北路");
            writer.writeEndElement();
            writer.writeCharacters(
" ");
            writer.writeStartElement(
"city");
            writer.writeCharacters(
"朝阳区");
            writer.writeEndElement();
            writer.writeCharacters(
" ");
            writer.writeStartElement(
"state");
            writer.writeCharacters(
"北京");
            writer.writeEndElement();
            writer.writeCharacters(
" ");
            writer.writeStartElement(
"postalCode");
            writer.writeCharacters(
"100102");
            writer.writeEndElement();
            writer.writeCharacters(
" ");
            writer.writeEndElement();
//billTo元素结束
            
            writer.writeCharacters(
" ");
            writer.writeStartElement(
"shipTo");//开始shipTo元素
            writer.writeAttribute("href""addr-1");
            writer.writeEndElement();
//shipTo元素结束
            
            writer.writeCharacters(
" ");
            writer.writeStartElement(
"order");//开始order元素
            writer.writeCharacters(" ");
            
for (Iterator itr = order.items.iterator(); itr.hasNext();)
            
{
                Item item 
= (Item) itr.next();
                writer.writeStartElement(
"item");
                writer.writeAttribute(
"sku", item.getSku());
                writer.writeAttribute(
"quantity", String.valueOf(item
                        .getQuantity()));
                writer.writeCharacters(
" ");
                writer.writeStartElement(
"description");
                writer.writeCharacters(item.getDescription());
                writer.writeEndElement();
                writer.writeCharacters(
" ");
                writer.writeEndElement();
                writer.writeCharacters(
" ");
            }

            writer.writeEndElement();
//order元素结束
            
            writer.writeCharacters(
" ");
            writer.writeEndElement();
//po元素结束
            writer.writeEndDocument();
            writer.flush();
            writer.close();
        }
 catch (XMLStreamException e)
        
{
            e.printStackTrace();
        }

        
return buffer.toString();
    }

代码测试,其中TestStax类为包含了上面解析与输出代码的类

TestStax stax = new TestStax();
  Order order = stax.parse(XmlFile.getSample1Stream());
  System.out.println(order.toString());
  Item item = new Item();
  item.setSku("0123-BP");
  item.setQuantity(10);
  item.setDescription("Java XML 开发");
  order.addItem(item);
  String xml = stax.write(order);
  System.out.println("------------------------------");
  System.out.println(xml);

XML输出结果

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE po SYSTEM "src/sample.dtd">
<po xmlns="
http://www.csdn.net" id="20080124001" submitted="2008-01-24">
<billTo id="addr-1">
<company>CSDN</company>
<street>朝阳区望京北路</street>
<city>朝阳区</city>
<state>北京</state>
<postalCode>100102</postalCode>
</billTo>
<shipTo href="addr-1"></shipTo>
<order>
<item sku="o318-BP" quantity="5">
<description>J2EE programmic</description>
</item>
<item sku="o947-TI" quantity="12">
<description>Java WEB Service</description>
</item>
<item sku="o008-PR" quantity="133">
<description>C++ develop</description>
</item>
<item sku="0123-BP" quantity="10">
<description>Java XML 开发</description>
</item>
</order>
</po>

没有什么多于的介绍,基本上就是一个代码示范,我相信二八法则,20%的知识基本能够满足80%可能碰到的场景,呵呵,算是谬论吧。

详细的介绍在IBM网站上有一篇,个人觉得还不错

http://www.ibm.com/developerworks/cn/xml/x-stax1.html
http://www.ibm.com/developerworks/cn/xml/x-stax2.html
http://www.ibm.com/developerworks/cn/xml/x-stax3.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值