StAX - установка версии и кодировки с использованием XMLStreamWriter - PullRequest
7 голосов
/ 31 мая 2010

Я использую StAX для создания файлов XML, а затем проверяю файл с помощью и XSD.

При создании файла XML появляется ошибка:

javax.xml.stream.XMLStreamException: Underlying stream encoding 'Cp1252' and input paramter for writeStartDocument() method 'UTF-8' do not match.
        at com.sun.xml.internal.stream.writers.XMLStreamWriterImpl.writeStartDocument(XMLStreamWriterImpl.java:1182)

Вот фрагмент кода:

XMLOutputFactory xof =  XMLOutputFactory.newInstance();

try{

  XMLStreamWriter xtw = xof.createXMLStreamWriter(new FileWriter(fileName));
  xtw.writeStartDocument("UTF-8","1.0");} catch(XMLStreamException e) {
  e.printStackTrace();

} catch(IOException ie) {

  ie.printStackTrace();

}

Я использую этот код в Unix. Кто-нибудь знает, как установить версию и стиль кодирования?

Ответы [ 4 ]

14 голосов
/ 31 мая 2010

Я бы тоже попытался использовать createXMLStreamWriter() с выходным параметром.

[EDIT] Пробовал, работает, изменяя строку createXMLStreamWriter:

XMLStreamWriter xtw = xof.createXMLStreamWriter(new FileOutputStream(fileName), "UTF-8");

[РЕДАКТИРОВАТЬ 2] Сделано немного более сложный тест, для записи:

String fileName = "Test.xml";
XMLOutputFactory xof =  XMLOutputFactory.newInstance();
XMLStreamWriter xtw = null;
try
{
  xtw = xof.createXMLStreamWriter(new FileOutputStream(fileName), "UTF-8");
  xtw.writeStartDocument("UTF-8", "1.0");
  xtw.writeStartElement("root");
  xtw.writeComment("This is an attempt to create an XML file with StAX");

  xtw.writeStartElement("foo");
  xtw.writeAttribute("order", "1");
    xtw.writeStartElement("meuh");
    xtw.writeAttribute("active", "true");
      xtw.writeCharacters("The cows are flying high this Spring");
    xtw.writeEndElement();
  xtw.writeEndElement();

  xtw.writeStartElement("bar");
  xtw.writeAttribute("order", "2");
    xtw.writeStartElement("tcho");
    xtw.writeAttribute("kola", "K");
      xtw.writeCharacters("Content of tcho tag");
    xtw.writeEndElement();
  xtw.writeEndElement();

  xtw.writeEndElement();
  xtw.writeEndDocument();
}
catch (XMLStreamException e)
{
  e.printStackTrace();
}
catch (IOException ie)
{
  ie.printStackTrace();
}
finally
{
  if (xtw != null)
  {
    try
    {
      xtw.close();
    }
    catch (XMLStreamException e)
    {
      e.printStackTrace();
    }
  }
}
5 голосов
/ 01 июня 2010

Это должно работать:

// ...
Writer writer = new OutputStreamWriter(new FileOutputStream(fileName), "UTF-8");
XMLStreamWriter xtw = xof.createXMLStreamWriter(writer);
xtw.writeStartDocument("UTF-8", "1.0");
// ...
2 голосов
/ 13 января 2011

По коду это трудно понять наверняка, но если вы полагаетесь на стандартную реализацию Stax, которую предоставляет JDK 1.6 (Sun sjsxp), я бы порекомендовал обновить ее до Woodstox . Известно, что он менее глючит, чем Sjsxp, поддерживает весь API Stax2 и активно разрабатывается и поддерживается (тогда как версия Sun была только что написана и количество исправлений ошибок было ограничено).

Но ошибка в вашем коде такова:

XMLStreamWriter xtw = xof.createXMLStreamWriter(new FileWriter(fileName));

вы полагаетесь на кодировку платформы по умолчанию (которая должна быть CP-1252, windows?). Вы всегда должны явно указывать кодировку, которую вы используете. Stream Writer просто проверяет, что вы не делаете чего-то опасного, и обнаруживает несогласованность, которая может привести к повреждению документа. Довольно умный, что фактически говорит о том, что это не стандартный процессор Stax. : -)

(другой ответ также указывает на правильный обходной путь, просто передавая OutputStream и кодировку, чтобы XMLStreamWriter делал правильные вещи)

0 голосов
/ 03 июля 2015

Если используется значение по умолчанию XMLStreamWriter в комплекте с Oracle JRE / JDK, вы должны всегда

  • создать XMLStreamWriter, явно указав кодировку символов: xmlOutputFactory.createXMLStreamWriter(in, encoding)
  • запустить документ и явно указать кодировку: xmlStreamWriter.writeStartDocument(encoding, version). Автор не достаточно умен, чтобы помнить кодировку, установленную при создании автора. Однако он проверяет, совпадают ли эти кодировки. Смотрите код ниже.

Таким образом, кодировка вашего файла и объявление XML всегда синхронизированы. Хотя указание кодировки в объявлении XML является необязательным, рекомендуется всегда указывать код XML.

Это код из реализации Oracle (Sun) (Sjsxp):

String streamEncoding = null;
if (fWriter instanceof OutputStreamWriter) {
    streamEncoding = ((OutputStreamWriter) fWriter).getEncoding();
}
else if (fWriter instanceof UTF8OutputStreamWriter) {
    streamEncoding = ((UTF8OutputStreamWriter) fWriter).getEncoding();
}
else if (fWriter instanceof XMLWriter) {
    streamEncoding = ((OutputStreamWriter) ((XMLWriter)fWriter).getWriter()).getEncoding();
}

if (streamEncoding != null && !streamEncoding.equalsIgnoreCase(encoding)) {
    // If the equality check failed, check for charset encoding aliases
    boolean foundAlias = false;
    Set aliases = Charset.forName(encoding).aliases();
    for (Iterator it = aliases.iterator(); !foundAlias && it.hasNext(); ) {
        if (streamEncoding.equalsIgnoreCase((String) it.next())) {
            foundAlias = true;
        }
    }
    // If no alias matches the encoding name, then report error
    if (!foundAlias) {
        throw new XMLStreamException("Underlying stream encoding '"
                + streamEncoding
                + "' and input paramter for writeStartDocument() method '"
                + encoding + "' do not match.");
    }
}
...