Stax 事件 reader 跳过白色 space
Stax event reader skipping white space
我正在编写一个实用程序来使用 STAX 事件模型更改 XML 文件中的文本实体。我发现源文档中的一些白色 space 没有被复制到输出中。我写了这个示例程序:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import javax.xml.stream.*;
import javax.xml.stream.events.*;
public class EventCopy {
private static final String INPUT =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<foo><bar>baz</bar></foo>\n";
public static void main(String[] args) throws XMLStreamException, IOException {
InputStream reader = new ByteArrayInputStream(INPUT.getBytes(StandardCharsets.UTF_8));
OutputStream writer = new ByteArrayOutputStream();
XMLInputFactory input = XMLInputFactory.newInstance();
XMLEventReader xmlReader = input.createXMLEventReader(reader, "UTF-8");
try {
XMLOutputFactory output = XMLOutputFactory.newInstance();
XMLEventWriter xmlWriter = output.createXMLEventWriter(writer, "UTF-8");
try {
while (xmlReader.hasNext()) {
XMLEvent event = xmlReader.nextEvent();
System.out.print(event.getEventType() + ",");
xmlWriter.add(event);
}
} finally {
xmlWriter.close();
}
} finally {
xmlReader.close();
}
System.out.println("\n[" + writer.toString() + "]");
}
}
使用 Oracle Java 7 附带的默认 Stax 实现,输出:
7,1,1,4,2,2,8,
[<?xml version="1.0" encoding="UTF-8"?><foo><bar>baz</bar></foo>]
XML 序言之后和输入末尾的换行符已消失。似乎 reader 甚至没有为他们生成事件。
我认为 XML reader 可能会将输入流留在最后一个 XML 标记的末尾,并尝试添加代码以从输入中复制尾随字符到输出:
...
} finally {
xmlReader.close();
}
int ii;
while (-1 != (ii = reader.read())) {
writer.write(ii);
}
但这没有任何效果。
有没有办法让 STAX 更忠实地复制这个 XML?不同的 STAX 实现在这里会有不同的行为吗?
参考:XML spec
格式良好的XML文档遵循规范语法:
[1] document ::= prolog element Misc*
[22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
[23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
[27] Misc ::= Comment | PI | S
[3] S ::= (#x20 | #x9 | #xD | #xA)+
[39] element ::= EmptyElemTag
| STag content ETag
[40] STag ::= '<' Name (S Attribute)* S? '>'
[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
[14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
[42] ETag ::= '</' Name S? '>'
XMLDecl
和根元素之间的换行符,以及根元素之后的换行符,只是S
解析器允许自己忽略的。
让我举一个不同的白色的例子space。假设你有一个稍微不同的 XML:
private static final String INPUT =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<foo>\n<bar>baz</bar></foo>\n";
<foo>
和 <bar>
之间的换行是 CharData
。请注意,StAX 会为此角色正确生成一个事件。
如果您真的想保留 S
,那么您需要阅读 INPUT
作为文本而不是 XML 文档。请注意,两个 XML 文档实例,一个具有这两个特定 S
字符,一个不具有它们,是等价的。
我正在编写一个实用程序来使用 STAX 事件模型更改 XML 文件中的文本实体。我发现源文档中的一些白色 space 没有被复制到输出中。我写了这个示例程序:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import javax.xml.stream.*;
import javax.xml.stream.events.*;
public class EventCopy {
private static final String INPUT =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<foo><bar>baz</bar></foo>\n";
public static void main(String[] args) throws XMLStreamException, IOException {
InputStream reader = new ByteArrayInputStream(INPUT.getBytes(StandardCharsets.UTF_8));
OutputStream writer = new ByteArrayOutputStream();
XMLInputFactory input = XMLInputFactory.newInstance();
XMLEventReader xmlReader = input.createXMLEventReader(reader, "UTF-8");
try {
XMLOutputFactory output = XMLOutputFactory.newInstance();
XMLEventWriter xmlWriter = output.createXMLEventWriter(writer, "UTF-8");
try {
while (xmlReader.hasNext()) {
XMLEvent event = xmlReader.nextEvent();
System.out.print(event.getEventType() + ",");
xmlWriter.add(event);
}
} finally {
xmlWriter.close();
}
} finally {
xmlReader.close();
}
System.out.println("\n[" + writer.toString() + "]");
}
}
使用 Oracle Java 7 附带的默认 Stax 实现,输出:
7,1,1,4,2,2,8,
[<?xml version="1.0" encoding="UTF-8"?><foo><bar>baz</bar></foo>]
XML 序言之后和输入末尾的换行符已消失。似乎 reader 甚至没有为他们生成事件。
我认为 XML reader 可能会将输入流留在最后一个 XML 标记的末尾,并尝试添加代码以从输入中复制尾随字符到输出:
...
} finally {
xmlReader.close();
}
int ii;
while (-1 != (ii = reader.read())) {
writer.write(ii);
}
但这没有任何效果。
有没有办法让 STAX 更忠实地复制这个 XML?不同的 STAX 实现在这里会有不同的行为吗?
参考:XML spec
格式良好的XML文档遵循规范语法:
[1] document ::= prolog element Misc* [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' [27] Misc ::= Comment | PI | S [3] S ::= (#x20 | #x9 | #xD | #xA)+ [39] element ::= EmptyElemTag | STag content ETag [40] STag ::= '<' Name (S Attribute)* S? '>' [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) [42] ETag ::= '</' Name S? '>'
XMLDecl
和根元素之间的换行符,以及根元素之后的换行符,只是S
解析器允许自己忽略的。
让我举一个不同的白色的例子space。假设你有一个稍微不同的 XML:
private static final String INPUT =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<foo>\n<bar>baz</bar></foo>\n";
<foo>
和 <bar>
之间的换行是 CharData
。请注意,StAX 会为此角色正确生成一个事件。
如果您真的想保留 S
,那么您需要阅读 INPUT
作为文本而不是 XML 文档。请注意,两个 XML 文档实例,一个具有这两个特定 S
字符,一个不具有它们,是等价的。