我正在使用XMLEventReader
和XMLEventWriter
进行一些外科XML转换。在大多数情况下,我只是在阅读时写下事件:
import javax.xml.stream.*;
import javax.xml.stream.events.XMLEvent;
import java.io.StringReader;
import java.io.StringWriter;
public class StaxExample {
public static void main(String[] args) throws XMLStreamException {
String inputXml =
"<foo>" +
" <bar baz=\"a b c \"/>" +
" <changeme/>" +
"</foo>";
StringWriter result = new StringWriter();
XMLEventReader reader = XMLInputFactory.newFactory().createXMLEventReader(new StringReader(inputXml));
XMLEventWriter writer = XMLOutputFactory.newFactory().createXMLEventWriter(result);
while (reader.hasNext()) {
XMLEvent event = reader.nextEvent();
//in real code, look for "changeme" and insert some stuff
writer.add(event);
}
System.out.println(result.toString());
}
}
我的问题是,这会产生:
<?xml version="1.0" ?><foo> <bar baz="a
b
c
"></bar> <changeme></changeme></foo>
虽然语法上有效的XML,但我必须(由于下游消费者)保留新行。上面的XML将被该消费者标准化为a b c
(事实上,通过StAX本身 - 如果我将此输出并将其反馈回同一程序,则第二次输出baz="a b c "
)。
虽然我已放弃XMLEventWriter
保留非语义格式,但有没有办法阻止它实质上更改我的属性值?
答案 0 :(得分:0)
好吧,我建议你实现自己的作家:
public class EscappingNLWriter extends FilterWriter
{
public EscappingNLWriter(Writer out) {super(out);}
public void write(c)
{
if (c=='\n')
{
out.write(" ");
}
else
{
out.write(c);
}
}
public void write(char[] buff, int offset, int len) throws IOException
{
// ...Same char filtering...
}
public void write(String str, int offset, int len) throws IOException
{
// ...Same char filtering...
}
}
然后用它来封装StringWriter:
Writer result = new EscappingNLWriter(new StringWriter());
答案 1 :(得分:0)
如果您需要绝对准确度关于,其中要转义XML中的换行符, 不要转义(即:您需要转义换行符)只有在属性范围内,而不是在其他地方),我还有一个更复杂的建议:
看看你的代码:
rigidbody
有一点可以在属性和作者之间插入:在初始化while (reader.hasNext()) {
XMLEvent event = reader.nextEvent();
//in real code, look for "changeme" and insert some stuff
writer.add(event);
}
之后,在将其传递给event
之前,您可以封装在您自己的writer.add
实现中的事件,以确保如果它是XMLEvent
的实例,您将覆盖javax.xml.stream.events.Attribute
以返回正确覆盖的值。
但是有一个额外的复杂性:XMLEventReader返回的XMLEvents通常不包含属性事件:属性包含在其相应的StartElement事件中。因此,您需要一个更高级别的封装:StartElement对象,然后是包含的Attribute对象。