2016-11-20 3 views
1

Я пишу утилиту для изменения текстовых объектов в XML-файле с использованием модели событий STAX. Я обнаружил, что некоторая часть пробела в исходном документе не копируется на выход. Я написал эту программу примера:Чтение события Stax, пропуская пробел

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, это выводит:

7,1,1,4,2,2,8, 
[<?xml version="1.0" encoding="UTF-8"?><foo><bar>baz</bar></foo>] 

символа новой строки ниже в XML пролога и в конце ввода исчез , Кажется, читатель даже не создает для них событий.

Я подумал, что, может быть, читатель XML покидает входной поток, расположенный в конце последнего XML тега, и попытался добавить код, чтобы скопировать завершающие символы с входа на выход:

... 
    } finally { 
     xmlReader.close(); 
    } 
    int ii; 
    while (-1 != (ii = reader.read())) { 
     writer.write(ii); 
    } 

Но это не имеет никакого эффекта.

Есть ли способ заставить STAX скопировать этот XML более верно? Будет ли другая реализация STAX вести себя по-другому здесь?

+0

попробуйте использовать «
» вместо «\ n» –

ответ

0

Ссылка: 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, что анализатор позволяет себе игнорировать.

Позвольте мне привести пример другого пробела. Предположим, у вас есть немного другой 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 и один без них, эквивалентны.

+0

Я понял, что выход семантически эквивалентен входу. Это не то, что я ищу. Я обеспокоен тем, что мои пользователи будут жаловаться, если этот XML-фильтр сделает ненужные изменения в XML, и я бы предпочел не спорить с ними, что изменения не имеют значения. – Kenster

+0

@ Kenster Я думаю, что у вас нет вариантов. Затем прочитайте XML как текст. Я считаю, что большинство парсеров XML будут игнорировать эти пробелы – nandsito

Смежные вопросы