任何人都知道使用SAX框架(或类似的东西)和Java编写XML的好教程(或有一个很好的例子)?搜索在有用结果方面收效甚微。我正在尝试从Android应用程序导出,并希望避免尽可能多的内存开销。
答案 0 :(得分:33)
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();
答案 1 :(得分:16)
通过 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解析器将采用的任何内容处理程序,例如pretyy打印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);
<强>更新强>
其他几个参考文献:
对评论的几点回应:
这是事实,但上面描述的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工程师视为滥用。我们的项目非常成功,可以帮助我们满足我们的要求而没有明显的缺点,因此我将在我的工具箱中保留这种方法,以便将来有用。
答案 2 :(得分:5)
下面的回答
我不确定你是否已经完成了这件事。但我真的很喜欢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
答案 3 :(得分:4)
请参阅我的个人博文:XML Generation In Java - 具体来说,The SAX method。它引用了一些与此有关的文章,提供了一个具体的例子,并将SAX与其他流行的API进行了比较,以便从Java生成XML。
(意识到这是一个较旧的问题,但认为有必要为可能有同样问题的其他人添加此问题。)
答案 4 :(得分:3)
还要考虑使用JAXB来编写/读取XML。
答案 5 :(得分:1)
您也可以通过以下方式与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));
}