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

    >> 本版讨论DOM, SAX, XPath等。
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - XML技术『 DOM/SAX/XPath 』 → SAX教程系列六(序列化 SAX 流)------来源:IBM developerWorks 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 6364 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: SAX教程系列六(序列化 SAX 流)------来源:IBM developerWorks 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     yuji1998 帅哥哟,离线,有人找我吗?魔羯座1981-12-22
      
      
      威望:5
      头衔:蓝色先锋
      等级:大二(研究C++)
      文章:212
      积分:1059
      门派:XML.ORG.CN
      注册:2004/4/10

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给yuji1998发送一个短消息 把yuji1998加入好友 查看yuji1998的个人资料 搜索yuji1998在『 DOM/SAX/XPath 』的所有贴子 访问yuji1998的主页 引用回复这个贴子 回复这个贴子 查看yuji1998的博客楼主
    发贴心情 SAX教程系列六(序列化 SAX 流)------来源:IBM developerWorks

    欢迎您通过电子邮件nicholas@nicholaschase.com直接与作者 Nicholas Chase 联系。
          注:本教程仅供本站成员的学习和研究使用,严禁用于商业目的!


          到目前为止的例子已考察了使用数据的基础,但这只是简单地考查 SAX 所能做的事情。可以将数据指引到另一个 SAX 进程、转换,当然还可以指引到某个文件。 本节将展示这其中的一些选项。
    将 SAX 事件流输出到文件的过程称为序列化。您可以自己编写文件,但是使用 Serializer 对象要简单得多:
    import org.apache.xalan.serialize.Serializer;
    import org.apache.xalan.serialize.SerializerFactory;
    import org.apache.xalan.templates.OutputProperties;
    import java.io.FileOutputStream;
    public static void main (String args[]) {
       XMLReader xmlReader = null;
       try {
          SAXParserFactory spfactory = SAXParserFactory.newInstance();
          spfactory.setValidating(false);
          SAXParser saxParser = spfactory.newSAXParser();
          xmlReader = saxParser.getXMLReader();
          Serializer serializer = SerializerFactory.getSerializer(
                   OutputProperties.getDefaultMethodProperties("xml"));      
          serializer.setOutputStream(new FileOutputStream("output.xml"));
          xmlReader.setContentHandler(
          serializer.asContentHandler()
    );
          InputSource source = new InputSource("surveys.xml");
          xmlReader.parse(source);
       } catch (Exception e) {
             System.err.println(e);
             System.exit(1);
       }
    }
    创建 Serializer 对象(OutputProperties 可接受的值为 xml、text 和 html),并设置它的 OutputStream。这个流几乎可以是任何流类型的对象,比如文件(本例中就是这样)或者 System.out。
    您可以将 Serializer 设置为解析器的内容处理程序,以便在解析器解析文件时,它就是接收事件的 Serializer。

          XMLFilters
    由于 SAX 涉及在读取数据时分析数据(而不是在存储之后再分析),您可能认为没有办法在分析数据之前更改数据。
    这就是 XMLFilter 要解决的问题。尽管它们是 SAX 2.0 版中新引入的,但实际上聪明的程序员在 1.0 版中就已经在使用它了,他们认识到能够将 SAX 流“链接”在一起,从而能够在数据到达最终目的地之前有效地操作它们。
    基本上,它像下面这样工作:
    创建 XMLFilter。这通常是一个简单的类。
    创建 XMLFilter 的一个实例,并将它的父亲设置为通常负责解析文件的 XMLReader。
    将过滤器的内容处理程序设置为通常的内容处理程序。
    解析文件。 过滤器介于 XMLReader 和内容处理程序之间。
          创建过滤器
    现在您需要创建一个过滤器,以允许您丢弃用户的原先答案,而相反地使用修订过的答案。为此,您需要删除原先的答案,然后更改修订答案的名称空间,以便 SurveyReader 能够选取它们。
    这是通过创建一个扩展 XMLFilterImpl 的新类来实现的。
    考察一下这里发生了什么事情。当 startElement() 事件被激发时,它将检查原先的名称空间 URI。如果这是 revised 元素,名称空间将被改为默认名称空间。如果不是这个元素,则元素名称实际上将被更改,以便原先的记录例程(在 SurveyReader 中)不会将它识别为一个问题,从而不会对答案计数。
    修改过的数据将被传递给父亲(原先的 XMLReader)的 startElement(),以便内容处理器将负责处理它。
    import org.xml.sax.helpers.XMLFilterImpl;
    import org.xml.sax.XMLReader;
    import org.xml.sax.SAXException;
    import org.xml.sax.Attributes;

    public class SurveyFilter extends XMLFilterImpl
    {
      public SurveyFilter ()
      {
      }
      public SurveyFilter (XMLReader parent)
      {
        super(parent);
      }
      public void startElement (String uri,
                                String localName,
                                String qName,
                                Attributes atts)
                                     throws SAXException
      {
          if (uri == "http://www.nicholaschase.com/surveys/revised/") {
              uri = "http://www.nicholaschase.com/surveys/";
              qName = "question";
          } else {
              localName = "REJECT";
          }
          super.startElement(uri, localName, qName, atts);
      }

    }
          调用过滤器
          现在是该使用过滤器的时候了。要做的第一件事情是创建一个新实例,然后将原先的 XMLReader 指定为父亲。
    接下来设置过滤器的内容和错误处理程序,而不是设置读取器。最后使用过滤器而不是 XMLReader 来解析文件。
    由于 XMLReader 被指定为过滤器的父亲,它仍然要处理信息。
    ...
    public static void main (String args[]) {

       XMLReader xmlReader = null;
          
       try {

          SAXParserFactory spfactory =
                 SAXParserFactory.newInstance();
          spfactory.setValidating(false);
          SAXParser saxParser =
                        spfactory.newSAXParser();

          xmlReader = saxParser.getXMLReader();

          SurveyFilter xmlFilter = new SurveyFilter();
          xmlFilter.setParent(xmlReader);

          
          xmlFilter.setContentHandler(new SurveyReader());

          xmlFilter.setErrorHandler(new SurveyReader());
      
          InputSource source = new InputSource("surveys.xml");

          xmlFilter.parse(source);  

          } catch (Exception e) {
                System.err.println(e);
                System.exit(1);
          }
       }
    ...
    这些特性能够嵌套的深度是无限的。 从理论上讲,您可以创建过滤器的一个很长的链,每个过滤器都调用下一个过滤器。
          使用 XMLFilter 来转换数据
    XMLFilters 还可用来方便快捷地使用 XLST 转换数据。转换本身超出了本教程的范围,不过下面将简要考察一下如何应用它:
    import javax.xml.transform.stream.StreamSource;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.sax.SAXTransformerFactory;
    import org.xml.sax.XMLFilter;
    public static void main (String args[]) {

       XMLReader xmlReader = null;
          
       try {
          SAXParserFactory spfactory = SAXParserFactory.newInstance();
          spfactory.setValidating(false);
          SAXParser saxParser = spfactory.newSAXParser();

          xmlReader = saxParser.getXMLReader();

          TransformerFactory tFactory = TransformerFactory.newInstance();
          SAXTransformerFactory
                      saxTFactory = ((SAXTransformerFactory) tFactory);
         
          XMLFilter xmlFilter =
                      saxTFactory.newXMLFilter(new StreamSource("surveys.xsl"));

          xmlFilter.setParent(xmlReader);
            

          Serializer serializer =
              SerializerFactory.getSerializer(
                      OutputProperties.getDefaultMethodProperties("xml"));        
          serializer.setOutputStream(System.out);
          xmlFilter.setContentHandler(
          serializer.asContentHandler());
          InputSource source = new InputSource("surveys.xml");
          xmlFilter.parse(source);

       } catch (Exception e) {
             System.err.println(e);
             System.exit(1);
       }
    }
    ...
    首先,您需要创建一个过滤器 —— 但是不是从头创建,而是创建一个专门设计用于根据样式表执行转换的过滤器。
    然后,就像您在直接输出文件时所做的那样,创建一个 Serializer 来输出转换结果。
    基本上,过滤器执行转换,然后将事件移交给 XMLReader。然而最终的目的地是序列化器。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    私人网站:蓝尚WEB商务平台http://www.lanshang.com     建站黄页:http://www.lanshang.com/link.asp WEB技术文库:http://www.lanshang.com/wenzhang/ 
    电子书籍: http://www.lanshang.com/ebook/  技术交流:http://www.lanshang.com/bbs/

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/5/31 0:28:00
     
     GoogleAdSense魔羯座1981-12-22
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 DOM/SAX/XPath 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/4/24 1:08:21

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

     *树形目录 (最近20个回帖) 顶端 
    主题:  SAX教程系列六(序列化 SAX 流)------来源:IBM de..(6632字) - yuji1998,2004年5月31日

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