【问题标题】:Generating XML using SAX and Java [closed]使用 SAX 和 Java 生成 XML [关闭]
【发布时间】:2011-02-04 13:40:11
【问题描述】:

任何人都知道使用 SAX 框架(或类似的框架)和 Java 编写 XML 的好教程(或有一个很好的例子)吗?搜索在有用的结果方面几乎没有产生什么。我正在尝试从 Android 应用程序导出,并希望尽可能避免内存开销。

【问题讨论】:

  • SAX 是一个解析器,它不会生成任何东西 :)
  • 除非您绝对想使用 SAX(在处理管道时可能偶尔会出现这种情况),否则您可能会问更通用的术语——也就是说,您想要实现什么,而不是到“我如何使用这个工具”?
  • 我真正在寻找的是生成 XML 时尽可能少的内存开销。我已经看到了一些使用 SAX 框架的示例,但对于像我这样的 Java 新手来说,没有什么具体的东西能找到有用的。

标签: java xml sax


【解决方案1】:

请参考我的个人博文:XML Generation In Java - 具体来说,The SAX method。它引用了其他几篇与此相关的文章,提供了一个具体示例,并将 SAX 与其他流行的用于从 Java 生成 XML 的 API 进行了比较。

(意识到这是一个较老的问题,但觉得有必要为可能有相同问题的其他人添加此问题。)

【讨论】:

    【解决方案2】:

    有一种非常有用的技术可以通过SAX 框架(不是SAX 解析器,而是SAX 框架)直接从POJO 中生成 XML。此技术可用于生成 XML 文档

    从任意数据结构生成 XML
    http://download.oracle.com/javaee/1.4/tutorial/doc/JAXPXSLT5.html

    本质上,您向 POJO 添加方法或为 POJO 编写实用程序类,将它们变成 SAX 事件发射器(在解析 XML 文档时通常会像 SAX 解析器一样发出事件)。现在,您的“SAX 事件生成器”看起来就像 SAX 解析器的输出端,并且可以为 SAX 解析器提供任何内容处理程序,例如可以打印 XML 的内容处理程序。但它也可以馈送到 DOM 解析器以生成 DOM 树或馈送到 XSLT 引擎以生成 HTML 或进行真正的 XSL 转换,而无需首先从 POJO 生成中间 XML 文档。

    例如,一个 Person 类可能有一个包含以下行的 emitXML() 方法:

    handler.startElement(nsu, PERSON_TAG, PERSON_TAG, NO_ATTRIBUTES);
    
    handler.startElement(nsu, FIRSTNAME_TAG, FIRSTNAME_TAG, atts);
    handler.characters(this.firstName.toCharArray(), 
            0,
            this.firstName.length());
    handler.endElement(nsu, FIRSTNAME_TAG, FIRSTNAME_TAG);
    
    ... emit more instance variables
    
    ... emit child object like: homeAddress.emitXML(handler, ...);
    
    handler.endElement(nsu, PERSON_TAG, PERSON_TAG);
    

    更新:

    其他几个参考:


    对 cme​​ts 的一些回应:

    确实如此,但是上面描述的 XMLStreamWriter 接口更加用户友好。 – Michael Kay 3 小时前

    是的,但我想我并不清楚。我可以轻松地遍历层次结构并使用XMLStreamWriter 将 XML 文档直接输出到流中。 然而,这些文章展示了一种强大的技术来遍历层次结构并生成 SAX 事件,而不是直接输出 XML 文档。现在我可以插入不同的内容处理程序来执行不同的操作或生成不同版本的 XML。 我们还可以将我们的对象层次结构提供给任何接受 SAX 解析器的工具,例如 XSLT 引擎。它实际上只是利用了 SAX 框架建立的访问者模式:我们将遍历层次结构与输出 XML 分开。输出 XML 的部分,即内容处理程序,如果它们的目的是编写 XML 流,当然应该使用XMLStreamWriter

    例如,在我们的程序中,我们通过分布式组件之间的网络套接字发送 XML 消息,并且我们还使用 XSLT 生成我们的 HTML 页面。以前,我们遍历层次结构以生成 XML 文档(字符串),然后将该 XML 文档写入网络套接字或将该文档提供给 XSLT 引擎(本质上只是再次解析它)。使用这种技术之后,我们基本上可以将我们的对象层次结构(使用这个 SAX 适配器)直接提供给 XSLT 引擎,而不需要中间的 XML 字符串。能够使用一个内容处理程序为网络流生成紧凑的 XML 表示,并使用不同的内容处理程序生成打印精美的 XML 文档以写入日志文件,这也很方便。

    此外,使用 SAX 解析器 API 编写 XML 是对 API 的滥用,恕我直言。 – Puce 49 分钟前

    也许,但我认为这取决于您的需求。如果 OP 的要求只是写出一个特定的 XML 文档,那么这绝对是矫枉过正。但是,我认为值得一提的是,如果 OP 在他的项目中以他没有提到的其他方式使用 XML。提出另一种想法并没有什么坏处。

    称其为滥用可能有点强,但我同意你有权发表你的意见。它记录在 Oracle 教程中,因此它不被 Sun/Oracle 工程师视为滥用。在我们的项目中非常成功地帮助我们满足了我们的要求,并且没有明显的缺点,所以我会将这种方法保留在我的工具箱中,以备将来使用时使用。

    【讨论】:

    • 确实如此,但是上面描述的 XMLStreamWriter 接口对用户来说更加友好。
    • 此外,使用 SAX 解析器 API 编写 XML 是对 API 的滥用,恕我直言。
    • @Michael Kay - 感谢您的评论。我试图在上面的编辑中澄清。
    • 除了其他 cmets,我建议如果你想要 POJO->xml,使用 JAXB 将是显而易见的方式。它确实在底层使用了基于 SAX/Stax 的编写器,因此性能非常好(唯一需要注意的是,Stax impl 1.6 附带的编写器性能很差;请改用 Woodstox)。
    • 不经常,但有时您真的非常想创建一个 SAX 事件流,您的解决方案展示了如何创建。这种方法在网上并不容易找到,感谢您提供的解释和示例。
    【解决方案3】:

    SAX 解析是用于读取文档,而不是写入文档。

    您可以使用 XMLStreamWriter 编写 XML:

    OutputStream outputStream = new FileOutputStream(new File("doc.xml"));
    
    XMLStreamWriter out = XMLOutputFactory.newInstance().createXMLStreamWriter(
                    new OutputStreamWriter(outputStream, "utf-8"));
    
    out.writeStartDocument();
    out.writeStartElement("doc");
    
    out.writeStartElement("title");
    out.writeCharacters("Document Title");
    out.writeEndElement();
    
    out.writeEndElement();
    out.writeEndDocument();
    
    out.close();
    

    【讨论】:

    • 我喜欢这个答案,不幸的是,该软件包在 Android 中不可用。我没有提到这一点是我的错。 D:
    • 好的,您当然也可以手动打印 XML。 out.print("<doc><tag>value</tag></doc>"); 等。但您必须确保正确转义这些值。这可以通过 apache commons StringEscapeUtils.escapeXML() 来完成。或者其他一些方法。这取决于可能的值,也许你可以用正则表达式来做。
    【解决方案4】:

    以下回答“使用 SAX 解析器和 Java 编写 XML 的好教程”部分问题

    我不确定你是否经历过这个。但我真的很喜欢Java's Really Big Index of Everything

    通过这个:http://download.oracle.com/javase/tutorial/jaxp/index.html

    最终,这是:http://download.oracle.com/javase/tutorial/jaxp/sax/index.html

    【讨论】:

    • 感谢 Nishant。这是完整的信息!这就是我一直在寻找的。​​span>
    【解决方案5】:

    还可以考虑使用 JAXB 来写入/读取 XML。

    【讨论】:

      【解决方案6】:

      您也可以通过以下方式连接到 trax:

      public abstract class PipedSAXSource extends SAXSource {
        protected PipedSAXSource() {
          setXMLReader(new CallWriteDuringSax());
        }
      
        protected abstract void writeTo(ContentHandler sink)
            throws IOException, SAXException;
      
        private class CallWriteDuringSax extends XMLFilterImpl {
          @Override
          public void parse(InputSource ignored) throws IOException, SAXException {
            writeTo(getContentHandler());
          }
      
          @Override
          public void setFeature(String name, boolean value) {}
        }
      }
      

      这样使用:

        public static void main(String[] args) throws Exception {
          Source in = new PipedSAXSource() {
            @Override
            protected void writeTo(ContentHandler sink) throws SAXException {
              sink.startDocument();
      
              sink.startElement("", "root", "root", new AttributesImpl());
              sink.endElement("", "root", "root");
      
              sink.endDocument();
            }
          };
      
          Transformer identity = TransformerFactory.newInstance().newTransformer();
          identity.transform(in, new StreamResult(System.out));
        }
      

      【讨论】:

        猜你喜欢
        • 2012-11-27
        • 1970-01-01
        • 1970-01-01
        • 2012-07-24
        • 2013-06-05
        • 2011-08-02
        • 2016-04-11
        • 2011-06-29
        • 2010-10-29
        相关资源
        最近更新 更多