新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> DTD, XML Schema(XMLS), RELAX NG
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - XML技术『 DTD/XML Schema 』 → 技巧: 使用 StAX 合并 XML 文档 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 3303 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 技巧: 使用 StAX 合并 XML 文档 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     anchen0617 帅哥哟,离线,有人找我吗?双子座1983-6-17
      
      
      威望:5
      等级:大二(研究C++)
      文章:281
      积分:3413
      门派:XML.ORG.CN
      注册:2004/10/17

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给anchen0617发送一个短消息 把anchen0617加入好友 查看anchen0617的个人资料 搜索anchen0617在『 DTD/XML Schema 』的所有贴子 访问anchen0617的主页 引用回复这个贴子 回复这个贴子 查看anchen0617的博客楼主
    发贴心情 技巧: 使用 StAX 合并 XML 文档

    从输入文档派生新的 XML 文档是 Streaming API for XML (StAX) 的闪光点之一。这篇技巧探讨了客户应用程序如何利用基于事件的 API 有效地把两个输入 XML 文档合并成一个。
    在上一篇技巧中,“使用 StAX 编写 XML 文档”,我说明了如何使用底层的基于指针的 StAX API 通过编程方式创建 XML 文档。在这篇技巧中,我使用高层的基于事件的 API 演示如何建立一个程序,把两个输入的 XML 文档合并成一个。

    同时处理多个 XML 文档可能是一个很大的挑战。比如,SAX 解析器通过回调客户应用程序提交解析事件。因为 SAX 解析器控制了这个过程,客户应用程序实际上没有机会同步不同的输入源。因此,在需要处理多个文档时程序员常常求助于 DOM 解析器。但是,代价是额外的资源占用——所有输入文档的节点树必须都驻留在内存中。

    StAX 不存在这种缺陷。如它的名字所表明的那样,其目标就是像合并两个文档这样的流式应用程序。下面的例子说明了如何实现这种功能。假设您需要合并包含产品列表的两个文档。每个文档都有一个 <products> 元素,其中包含一个或多个 <product> 元素,根据 pid 属性按照字母顺序排序。清单 1 是一个这种文档的例子:

    清单 1. 产品列表

    <products>
       <product pid="01"/>
       <product pid="05"/>
       <product pid="09"/>
    </products>

    在清单 2 中,我使用传统的合并算法合并来自两个文档中的列表。通过比较来自两个文档的合并条件,决定从文档 1 还是文档 2 复制一个事件到输出文档。这项工作由 readToNextElement() 方法完成。该方法还有一些其他的逻辑,用于检查产品列表的结束。文档开始和文档结束都需要专门处理。

    清单 2. 合并文档

    import java.io.*;
    import javax.xml.namespace.QName;
    import javax.xml.stream.*;
    import javax.xml.stream.events.XMLEvent;

    public class Merger {

       private static final QName prodName = new QName("product");
       private static final QName pidName = new QName("pid");

       public static void main(String[] args)
          throws FileNotFoundException, XMLStreamException {
             
          // Use  the reference implementation for the  XML input factory
          System.setProperty(
             "javax.xml.stream.XMLInputFactory",
             "com.bea.xml.stream.MXParserFactory");
          // Create the XML input factory
          XMLInputFactory factory = XMLInputFactory.newInstance();
          // Create XML event reader 1
          XMLEventReader r1 =
             factory.createXMLEventReader(new FileReader("prodList1.xml"));
          // Create XML event reader 2
          XMLEventReader r2 =
             factory.createXMLEventReader(new FileReader("prodList2.xml"));

          // Create the output factory
          XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
          // Create XML event writer
          XMLEventWriter xmlw = xmlof.createXMLEventWriter(System.out);

          // Read to first <product> element in document 1
          // and output to result document
          String pid1 = readToNextElement(r1, xmlw, false);
          // Read to first <product> element in document 1
          // without writing to result document
          String pid2 = readToNextElement(r2, null, false);
          // Loop over both XML input streams
          while (pid1 != null || pid2 != null) {
             // Compare merge criteria
             if (pid2 == null || (pid1 != null && pid1.compareTo(pid2) <= 0))
                // Continue in document 1
                pid1 = readToNextElement(r1, xmlw, pid2 == null);
             else
                // Continue in document 2
                pid2 = readToNextElement(r2, xmlw, pid1 == null);
          }
          xmlw.close();
       }

       /**
        * @param reader - the document reader
        * @param writer - the document writer
        * @param processEnd - forces the document end to be written
        * @return - the next merge criterion value
        * @throws XMLStreamException
        */
       private static String readToNextElement(XMLEventReader reader,
             XMLEventWriter writer, boolean processEnd) throws XMLStreamException {
          // Nesting level
          int level = 0;
          while (true) {
             // Read event to be written to result document
             XMLEvent event = reader.next();
             // Avoid double processing of document end
             if (!processEnd)
                switch (event.getEventType()) {
                   case XMLEvent.START_ELEMENT :
                      ++level;
                      break;
                   case XMLEvent.END_ELEMENT :
                      if (--level < 0)
                         return null;
                      break;
                }
             // Output event
             if (writer != null)
                writer.add(event);
             // Look at next event
             event = reader.peek();
             switch (event.getEventType()) {
                case XMLEvent.START_ELEMENT :
                   // Start element - stop at <product> element
                   QName name = event.asStartElement().getName();
                   if (name.equals(prodName)) {
                      return event
                         .asStartElement()
                         .getAttributeByName(pidName)
                         .getValue();
                   }
                   break;
                case XMLEvent.END_DOCUMENT :
                   // Stop at end of document
                   return null;
             }
          }
       }
    }

    如您所见,基于事件的 API 非常适于从其他文档派生文档。如果使用底层的基于指针的 API,您还需要对不同的事件类型调用不同的方法,而使用基于事件的 API,只需要向事件编写器的 add() 方法 传递普通事件就可以了。

    结束语
    这篇技巧示范了在管道式 XML 应用程序中使用 StAX 的基于事件的 API,比如文档的合并。2003 年 11 月 3 日,StAX 通过了 Final JSR-0173 Approval Ballot。它将为每个 Java 程序员的工具箱中增加一些有用的东西。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    xml这门语言太好了,我们共同努力吧!!!!!

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/11/9 15:21:00
     
     sxhong 帅哥哟,离线,有人找我吗?天蝎座1983-11-9
      
      
      等级:大二(研究汇编)
      文章:38
      积分:213
      门派:XML.ORG.CN
      注册:2004/7/12

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给sxhong发送一个短消息 把sxhong加入好友 查看sxhong的个人资料 搜索sxhong在『 DTD/XML Schema 』的所有贴子 引用回复这个贴子 回复这个贴子 查看sxhong的博客2
    发贴心情 
    这个库在那里有呀?挺强的!

    ----------------------------------------------
    天这样蓝 树这样绿 生活原来可以 这样的安宁和 美丽 [EMAIL]sxhong_2003@yahoo.com.cn[/EMAIL]

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/11/11 23:55:00
     
     flyfoxs 帅哥哟,离线,有人找我吗?
      
      
      威望:5
      等级:研一(Artificial Intelligence期期不放过)
      文章:550
      积分:3935
      门派:XML.ORG.CN
      注册:2005/1/8

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给flyfoxs发送一个短消息 把flyfoxs加入好友 查看flyfoxs的个人资料 搜索flyfoxs在『 DTD/XML Schema 』的所有贴子 引用回复这个贴子 回复这个贴子 查看flyfoxs的博客3
    发贴心情 
    http://www.developer.com/java/ent/article.php/3351701

    http://jcp.org/aboutJava/communityprocess/final/jsr173/index.html

    花了好长时间找到了,不敢独享!

    ----------------------------------------------
    存在即是被搜索!

    BLOG =>  http://www.OpenJ.cn

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/9/6 20:31:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 DTD/XML Schema 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/17 7:35:37

    本主题贴数3,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    72.266ms