8

我正在使用 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

4 回答 4

14

我也会尝试将createXMLStreamWriter()与输出参数一起使用。

[编辑] 尝试过,它通过更改 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();
    }
  }
}
于 2010-05-31T14:11:40.290 回答
6

这应该有效:

// ...
Writer writer = new OutputStreamWriter(new FileOutputStream(fileName), "UTF-8");
XMLStreamWriter xtw = xof.createXMLStreamWriter(writer);
xtw.writeStartDocument("UTF-8", "1.0");
// ...
于 2010-06-01T19:46:16.597 回答
2

从代码中很难确定,但如果您依赖 JDK 1.6 提供的默认 Stax 实现(Sun sjsxp),我建议升级以使用Woodstox。众所周知,它的 bug 比 Sjsxp 少,支持整个 Stax2 API,并且一直在积极开发和支持(而 Sun 版本刚刚编写,并且修复的 bug 数量有限)。

但是您的代码中的错误是这样的:

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

您依赖于默认平台编码(必须是 CP-1252,windows?)。您应该始终明确指定您正在使用的编码。Stream writer 只是在验证您没有做危险的事情,并发现可能导致文档损坏的不一致。非常聪明,这实际上表明这不是默认的 Stax 处理器。:-)

(另一个答案也指出了一个正确的解决方法,只需传递 OutputStream 和编码以让 XMLStreamWriter 做正确的事情)

于 2011-01-13T19:10:31.227 回答
0

如果使用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.");
    }
}
于 2015-07-03T18:54:55.880 回答