JAXP使用Stax API时格式化输出XML
最近项目中需要生成XBRL instance,对于XML读写和验证进行了一些学习。由于Stax API不支持格式化输出,默认全都写在一行上,网上也没有搜到现成的东西,自己写了一个格式化输出的帮助类。
说明:
1. 使用了WoodStox 4.2.0的Stax实现来写XML,顺便提一下,经过比较JAXP默认实现(SJSXP),WoodStox,DOM4J, XOM(NUX)。发现WoodStox速度最快,通过自己扩展的Stax2 API,功能也比较强大。
2. 实现了特殊的XML验证,一般来说使用SAXParser来读入XML文件再进行验证,但是这里使用了边写边验证的功能,如果是不合法的写入就会失败,所以只要写完XML肯定就是合法的。这也是Stax2 API提供的功能。
关于XML验证有一个相当不错的链接:http://www.edankert.com/validate.html
3. 关于XMLPrettyFormatter的用法主要在三行代码上,XbrliWriterHelper类中的 formatter.writeStartElementIndention(), formatter.writeValueIndention(), formatter.writeEndElementIndention()。注意调用这三个函数一定要writer.writerXXX()的方法前面。
以下是主要代码,最后会附上整个工程(包含XSD文件等)。
(2014-04-18 15:00 编辑) 这个实现有一个问题,会导致没有值的节点也分开显示结束标签,新的版本解决了这个问题:
http://www.cnblogs.com/lyhtbc/p/3673192.html
入口类WoodstoxWriter:
public class WoodstoxWriter {
public static void main(String[] args) throws IOException, XMLStreamException {
Timer t = new Timer();
t.begin();
streamWriter();
t.end();
}
private static void streamWriter() throws IOException, XMLStreamException {
File xsdFile = new File("src/main/resources/book.xsd");
XMLValidationSchemaFactory xsdFactory = XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA);
XMLValidationSchema schema = xsdFactory.createSchema(xsdFile);
XbrliWriterBean writer = new XbrliWriterBean();
writer.init(schema);
writer.writeStartElement("bk", "books", Const.NSURI_BOOK);
writer.writeNamespace("bk", Const.NSURI_BOOK);
writer.writeNamespace("au", Const.NSURI_AUTHER);
for (int i = 0; i < Const.NODE_COUNTS_S; ++i) {
writer.writeStartElement("bk", "book", Const.NSURI_BOOK);
writer.writeAttribute("id", String.valueOf(i + 1));
writer.writeStartElement("bk", "name", Const.NSURI_BOOK);
String name = new StringBuilder("Name").append(i + i).toString();
writer.writeValue(name);
writer.writeEndElement();
writer.writeStartElement("au", "author", Const.NSURI_AUTHER);
writer.writeStartElement("au", "age", Const.NSURI_AUTHER);
writer.writeValue("30");
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndElement();
}
writer.writeEndElement();
writer.close();
}
}
XbrliWriterHelper:
public class XbrliWriterHelper {
private FileOutputStream out;
private XMLStreamWriter2 writer;
private XMLPrettyFormatter formatter;
public void init(XMLValidationSchema schema) throws IOException, XMLStreamException {
out = new FileOutputStream("Woodstox.xml");
XMLOutputFactory factory = XMLOutputFactory2.newInstance();
writer = (XMLStreamWriter2) factory.createXMLStreamWriter(out);
writer.validateAgainst(schema);
writer.writeStartDocument("UTF-8", "1.0");
formatter = new DefaultPrettyFormatter(writer);
// formatter = new DefaultPrettyFormatter(writer, " ");
// formatter = new EmptyPrettyFormatter(writer);
}
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
formatter.writeStartElementIndention();
writer.writeStartElement(prefix, localName, namespaceURI);
}
public void writeValue(String value) throws XMLStreamException {
formatter.writeValueIndention();
writer.writeCharacters(value.toCharArray(), 0, value.length());
}
public void writeEndElement() throws XMLStreamException {
formatter.writeEndElementIndention();
writer.writeEndElement();
}
public void writeAttribute(String localName, String value) throws XMLStreamException {
writer.writeAttribute(localName, value);
}
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
writer.writeNamespace(prefix, namespaceURI);
}
public void close() throws XMLStreamException, IOException {
writer.writeEndDocument();
writer.close();
out.close();
}
}
XMLPrettyFormatter:
public interface XMLPrettyFormatter {
enum NodeType {
ELEMENT, VALUE
}
String DEFAULT_INDENTION = "\t";
void writeStartElementIndention() throws XMLStreamException;
void writeValueIndention() throws XMLStreamException;
void writeEndElementIndention() throws XMLStreamException;
}
DefaultPrettyFormatter:
public class DefaultPrettyFormatter implements XMLPrettyFormatter {
private String indent = DEFAULT_INDENTION;
private int currentLevel = 0;
private NodeType nodeType;
private XMLStreamWriter2 writer;
public DefaultPrettyFormatter(XMLStreamWriter2 writer) {
this.writer = writer;
}
public DefaultPrettyFormatter(XMLStreamWriter2 writer, String indent) {
this.writer = writer;
this.indent = indent;
}
@Override
public void writeStartElementIndention() throws XMLStreamException {
nodeType = NodeType.ELEMENT;
writeLineBreaker();
for (int i = 0; i < currentLevel; ++i) {
writeIndention();
}
++currentLevel;
}
@Override
public void writeValueIndention() throws XMLStreamException {
nodeType = NodeType.VALUE;
}
@Override
public void writeEndElementIndention() throws XMLStreamException {
--currentLevel;
if (nodeType == NodeType.ELEMENT) {
writeLineBreaker();
for (int i = 0; i < currentLevel; ++i) {
writeIndention();
}
} else {
// after write value, the node type should back to element
nodeType = NodeType.ELEMENT;
}
}
private void writeLineBreaker() throws XMLStreamException {
writer.writeCharacters("\n");
}
private void writeIndention() throws XMLStreamException {
writer.writeCharacters(indent.toCharArray(), 0, indent.length());
}
}
工程下载:晕啊,找不到上传文件地方,记得以前弄过的。。。只有直接贴文件内容了
POM 依赖
<dependencies>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb1-impl</artifactId>
<version>2.2.5.1</version>
</dependency>
</dependencies>
book.xsd:
<xs:schema targetNamespace="http://www.test.com/book" xmlns="http://www.test.com/book" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:au="http://www.test.com/author"
elementFormDefault="qualified"> <xs:import namespace="http://www.test.com/author" schemaLocation="author.xsd" /> <xs:element name="books" type="booksType" />
<xs:element name="book" type="bookType" /> <xs:complexType name="booksType">
<xs:sequence>
<xs:element ref="book" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType> <xs:complexType name="bookType">
<xs:sequence>
<xs:element name="name" type="xs:string" />
<xs:element ref="au:author" type="xs:string" />
</xs:sequence>
<xs:attribute name="id" type="xs:string" />
</xs:complexType> </xs:schema>
author.xsd:
<xs:schema targetNamespace="http://www.test.com/author" xmlns="http://www.test.com/author" xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"> <xs:element name="author" type="authorType" /> <xs:complexType name="authorType">
<xs:sequence>
<xs:element name="age" type="xs:positiveInteger" />
</xs:sequence>
</xs:complexType> </xs:schema>
JAXP使用Stax API时格式化输出XML的更多相关文章
- JAXP使用Stax API时格式化输出XML 2
之前实现的一个版本:http://www.cnblogs.com/lyhtbc/p/jaxp-pretty-format-validate-validation-stax-stax2.html 这个版 ...
- XStream、JAXB 日期(Date)、数字(Number)格式化输出xml
XStream.Jaxb是java中用于对象xml序列化/反序列化 的经典开源项目,利用它们将对象转换成xml时,经常会遇到日期(Date).数字按指定格式输出的需求,下面是使用示例: 一.日期字段格 ...
- boost格式化输出xml
我的boost为1.56而不是1.55 boost在xml的例子给出了一段写xml文件的代码,我简化如下: void debug_settings::save(const std::string &a ...
- .NET宝藏API之:OutputFormatter,格式化输出对象
相信大家在项目中都用过统一响应参数模板. 先声明一个响应模板类: public class ResponseDto { public int code { get; set; } public str ...
- Java数字格式化输出时前面补0
Java数字格式化输出时前面补0 星期日 2014年11月30日| 分类: Java /** * 里数字转字符串前面自动补0的实现. * */ public class TestString ...
- 格式化输出io:format的奇技淫巧
格式化输出io:format是我接触Erlang使用的第一个库函数(io:format("Hello World")),随着学习的深入,它也是我debug优先选择最简单直接的工具. ...
- 《ASP.NET Core跨平台开发从入门到实战》Web API自定义格式化protobuf
<ASP.NET Core跨平台开发从入门到实战>样章节 Web API自定义格式化protobuf. 样章 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于 ...
- WPF中任意Object的XAML代码格式化输出
原文:WPF中任意Object的XAML代码格式化输出 有时候,我们需要将WPF中的控件自身的XAML代码输出成文本,那么,我们可以使用System.Windows.Markup.XamlWriter ...
- cout 格式化输出
一直习惯于C语言的printf函数来打印,突然有一天要用cout来打印,发现有点不适应. 原来cout也是有格式化输出的. 首先要引入头文件 #include<iostream> // 在 ...
随机推荐
- Lucene 的 Scoring 评分机制
转自: http://www.oschina.net/question/5189_7707 Lucene 评分体系/机制(lucene scoring)是 Lucene 出名的一核心部分.它对用户来 ...
- jquery 报错 $.cookie is not a function()
jquery 报错 $.cookie is not a function() ——我是之前可以运行的项目,突然报这个错误,很奇怪. 这是jquery的cookie插件报错. 插件名: jquery.c ...
- sql server 跨数据库调用存储过程
A库存储过程: create PROCEDURE [dbo].[spAAAForTest] ( ) =null , ) =null ) AS BEGIN select N'A' AS a , N'B' ...
- perl I/O和缓存的关系
最近在查看日志时,突然发现信息没有及时写入日志,研究了很久,突然醒悟:原来是print的缓存原因. 顺着这个详细了解了下perl里的IO缓存机制: 1.正常情况下,操作系统的读写都有缓存(buffer ...
- Java中字符串和byte数组之间的相互转换
1.将字符转换成byte数组 String str = "罗长"; byte[] sb = str.getBytes(); 2.将byte数组转换成字符 byte[] b={(by ...
- 【转】由浅入深探究mysql索引结构原理、性能分析与优化
摘要: 第一部分:基础知识 第二部分:MYISAM和INNODB索引结构 1.简单介绍B-tree B+ tree树 2.MyisAM索引结构 3.Annode索引结构 4.MyisAM索引与Inno ...
- git命令速记
对于不常写代码,有的时候又要提交点代码的人来说,git命令记了又忘,忘了又去花精力记住.有没有一种速记方法,来帮助我们记忆这些玩意呢? 纯属抄袭@_@! 除了几个很基本的命令,复杂一点的,我都要去查, ...
- 15 个有趣的 JS 和 CSS 库
开发者们,一起来看看有木有你需要的前端库. 1. DisplayJS DisplayJS 是一个帮助你渲染 DOM 的简易框架.使用它,你可以更容易地将 JS 变量遍历到特定的 HTML 元素中,类似 ...
- 微信小程序-----安装,编写第一个小程序和运行到手机端
第一步: 微信公众平台注册账号,并选择小程序,网址:mp.weixin.qq.com 填写相关信息,如:主体类型(个人或者企业) AppID 在开发中都是用的到的,服务器域名在网络请求也是用的到的. ...
- [转]RGB数据保存为BMP图片
转自:http://blog.csdn.net/yixianfeng41/article/details/52591585 一.BMP文件由文件头.位图信息头.颜色信息和图形数据四部分组成. 1.BM ...