簡體   English   中英

StAX - 使用XMLStreamWriter設置版本和編碼

[英]StAX - Setting the version and encoding using XMLStreamWriter

我使用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上運行這段代碼。 有誰知道如何設置版本和編碼樣式?

我會嘗試將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();
    }
  }
}

這應該工作:

// ...
Writer writer = new OutputStreamWriter(new FileOutputStream(fileName), "UTF-8");
XMLStreamWriter xtw = xof.createXMLStreamWriter(writer);
xtw.writeStartDocument("UTF-8", "1.0");
// ...

從代碼中可以肯定地知道,但如果您依賴於JDK 1.6提供的默認Stax實現(Sun sjsxp),我建議升級以使用Woodstox 眾所周知,它比Sjsxp更少,支持整個Stax2 API,並且一直在積極開發和支持(而Sun版本只是編寫而且修復的bug數量有限)。

但是代碼中的錯誤是這樣的:

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

您依賴於默認的平台編碼(必須是CP-1252,Windows?)。 您應該始終明確指定您正在使用的編碼。 流編寫器只是驗證您沒有做一些危險的事情,並發現可能導致文檔損壞的不一致。 非常聰明,這實際上表明這不是默認的Stax處理器。 :-)

(另一個答案指出了一個正確的解決方法,只需傳遞OutputStream和編碼讓XMLStreamWriter做正確的事)

如果使用與Oracle JRE / JDK捆綁在一起的默認XMLStreamWriter ,則應始終使用

  • 創建一個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.");
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM