在XMLEventWriter中编码属性换行符

时间:2016-09-14 22:17:10

标签: java xml stax

我正在使用XMLEventReaderXMLEventWriter进行一些外科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&#10;b&#10;c&#10;\"/>" +
                "   <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保留非语义格式,但有没有办法阻止它实质上更改我的属性值?

2 个答案:

答案 0 :(得分:0)

好吧,我建议你实现自己的作家:

public class EscappingNLWriter extends FilterWriter
{
    public EscappingNLWriter(Writer out) {super(out);}

    public void write(c)
    {
        if (c=='\n')
        {
            out.write("&#10;");
        }
        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对象。