新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   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 文档 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 6540 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: 技巧: 使用 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 文档时,XMLEventReader 实例通过它的 next() 方法向客户传递事件对象,文档中的每个语法单位都有一个事件。但是,应用程序不一定愿意接受所有的事件类;只查看 XML 元素及其属性的应用程序并不关心代表注释和处理指令的事件。幸运的是,StAX 允许您通过实现事件过滤器忽略某些事件类。

    清单 1 给出了一个忽略所有 XML 处理指令的事件过滤器。这些事件没有传递给事件阅读器的 hasNext()、next() 或 peek() 方法。向给定的事件阅读器增加过滤器,必须构造一个新的阅读器,可以通过工厂方法 createFilteredReader() 完成。该方法接收原来的阅读器和 EventFilter 作为参数。接下来我使用这个新的事件过滤阅读器解析文档。

    清单 1. 过滤 XML 事件

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

    public class ParseFilteredByEvent {

       public static void main(String[] args)
          throws FileNotFoundException, XMLStreamException {
          // Use  reference implementation
          System.setProperty(
             "javax.xml.stream.XMLInputFactory",
             "com.bea.xml.stream.MXParserFactory");
          // Create the XML input factory
          XMLInputFactory factory = XMLInputFactory.newInstance();
          // Create event reader
          FileReader reader = new FileReader("somefile.xml");
          XMLEventReader eventReader = factory.createXMLEventReader(reader);
          // Create a filtered reader
          XMLEventReader filteredEventReader =
             factory.createFilteredReader(eventReader, new EventFilter() {
             public boolean accept(XMLEvent event) {
                // Exclude PIs
                return (!event.isProcessingInstruction());
             }
          });
          // Main event loop
          while (filteredEventReader.hasNext()) {
             XMLEvent e = filteredEventReader.next();
             System.out.println(e);
          }
       }
    }

    用同样的方式,你可以从主应用程序逻辑隐藏其他事件类。您甚至可以通过分层的方式组合几个 EventFilter,在另一个事件过滤阅读器的基础上构建新的过滤阅读器。

    隐藏文档分支
    在下面的例子中,我要介绍的过滤器能够忽略 XML 文档的整个分支。这一次我使用基于指针的 API 和流过滤阅读器而不是事件阅读器,因为我发现复杂的过滤器最好用流过滤器实现。与上面的例子类似,新的流过滤阅读器建立在基本流阅读器的基础上:

    清单 2. 创建流过滤阅读器

          // Create stream reader
          XMLStreamReader xmlr =
             xmlif.createXMLStreamReader(new FileReader("somefile.xml"));

          // Create a filtered stream reader
          XMLStreamReader xmlfr = xmlif.createFilteredReader(xmlr, filter);

    其中第二个参数所用的 StreamFilter 由清单 3 给出。在 XML 元素开始和结束的时候,它把相应的元素名和一个路径片段进行比较。路径作为一个 QName 数组实现,指定应该忽略文档的哪些部分。在这个例子中,路径 invoice/item 中的所有元素将被忽略。

    实现这种过滤器必须要知道,每次激活 hasNext()、next() 或 peek() 方法时都会调用过滤器的 accept() 方法。因此,同一个事件可能多次调用 accept() 方法。在这里,我保证对每个事件过滤逻辑只执行一次,只有当文档中的字符位置发生变化时才会执行。

    清单 3. 流过滤器

       // Exclusion path
       private static QName[] exclude = new QName[] {
          new QName("invoice"), new QName("item")};

       private static StreamFilter filter = new StreamFilter() {
          // Element level
          int depth = -1;
          // Last matching path segment
          int match = -1;
          // Filter result
          boolean process = true;
          // Character position in document
          int currentPos = -1;
          
          public boolean accept(XMLStreamReader reader) {
             // Get character position
             Location loc = reader.getLocation();
             int pos = loc.getCharacterOffset();
             // Inhibit double execution
             if (pos != currentPos) {
                currentPos = pos;
                switch (reader.getEventType()) {
                   case XMLStreamConstants.START_ELEMENT :
                      // Increment element depth
                      if (++depth < exclude.length && match == depth - 1) {
                         // Compare path segment with current element
                         if (reader.getName().equals(exclude[depth]))
                            // Equal - set segment pointer
                            match = depth;
                      }
                      // Process all elements not in path
                      process = match < exclude.length - 1;
                      break;
                   // End of XML element
                   case XMLStreamConstants.END_ELEMENT :
                      // Process all elements not in path
                      process = match < exclude.length - 1;
                      // Decrement element depth
                      if (--depth < match)
                         // Update segment pointer
                         match = depth;
                      break;
                }
             }
             return process;
          }
       };

    下一步
    这篇技巧示范了在 StAX 解析器中使用过滤器。在下一篇技巧中,我将介绍如何利用这些技术和其他技术来有效地筛选(screen)XML 文档。


       收藏   分享  
    顶(0)
      




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

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

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

     *树形目录 (最近20个回帖) 顶端 
    主题:  技巧: 使用 StAX 部分解析 XML 文档(4869字) - anchen0617,2004年11月13日

    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.500ms