Закодировать атрибуты новой строки в XMLEventWriter

2

Я делаю некоторые хирургические преобразования XML с использованием XMLEventReader и XMLEventWriter. По большей части я просто пишу эти события, когда они читаются:

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 вместо этого будет нормализован для abc этим потребителем (и даже самим StAX), если я возьму этот вывод и верну его обратно в ту же программу, во второй раз он выведет baz="abc ").

Хотя я отказался от XMLEventWriter сохраняющего не-семантическое форматирование, существует ли способ предотвратить существенное изменение моих значений атрибутов?

Теги:
stax

2 ответа

0

Если вам нужна абсолютная точность о том, где избежать новых строк в XML, а где нет (т.е. Вам нужно избегать новых строк только внутри атрибутов, а не в другом месте), у меня есть другое предложение, сложное немного сложнее:

Посмотрите на свой код:

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, вы будете перезаписывать Attribute.getValue() чтобы вернуть значение, соответствующее escapped.

Но есть дополнительное усложнение: XMLEvents, возвращаемые XMLEventReader, обычно не включают события атрибутов: Атрибуты включены в соответствующие события StartElement. Таким образом, вам нужен еще один уровень инкапсуляции: объекты StartElement, а затем содержащиеся объекты Attribute.

0

Ну, я предлагаю вам реализовать свой собственный Writer:

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());
  • 0
    Привет, спасибо за внимание и ответ! Я не уверен, насколько это будет практично, потому что он также заменит новые строки в тегах (например, между атрибутами в тегах), а не только в символьных данных. Действительно ли безопасно / эквивалентно заменять все новые строки, встречающиеся в документе, на числовые ссылки?
  • 0
    Да все. Числовые объекты лексически эквивалентны представленным символам в любом месте файла XML.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню