【问题标题】:Edit xml declaration encoding with java使用 java 编辑 xml 声明编码
【发布时间】:2016-11-06 08:22:10
【问题描述】:

我正在编辑声明中带有原始编码 ASCII 的 xml 文件。在生成的文件中,我希望编码为 UTF-8,以便编写像 åäö 这样的瑞典字符,这是我目前无法做到的。

可以在archivematica wiki 找到与我的文件等效的示例文件。

使用上述示例文件的副本运行我的程序后得到的 SIP.xml 可以通过this link 访问。添加的带有 åäö 文本的标签位于文档的最后。

如下面的代码所示,我尝试在转换器上设置编码,并尝试使用 OutputStreamWriter 来设置编码。 最后,我将原始文件中的声明编辑为 UTF-8,最后写出了 åäö。所以问题似乎是原始文件的编码。如果我没记错的话,将声明从 ASCII 更改为 UTF-8 应该不会造成任何问题,问题是,如何在我的程序中执行此操作?我可以在将其解析为 Document 对象之后执行此操作,还是在解析之前需要做一些事情?

package provklasser;

import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

/**
 *
 * @author 
 */
public class Provklass {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            File chosenFile = new File("myFile.xml");
            //parsing the xml file
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document metsDoc = builder.parse(chosenFile.getAbsolutePath());

            Element agent = (Element) metsDoc.getDocumentElement().appendChild(metsDoc.createElementNS("http://www.loc.gov/METS/","mets:agent"));
            agent.appendChild(metsDoc.createTextNode("åäö"));

            DOMSource source = new DOMSource(metsDoc);

            // write the content into xml file
            File newFile = new File(chosenFile.getParent(), "SIP.xml");

            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

            StreamResult result = new StreamResult(newFile);

            //Writer out = new OutputStreamWriter(new FileOutputStream("SIP.xml"), "UTF-8");
            //StreamResult result = new StreamResult(out);
            transformer.transform(source, result);

        } catch (ParserConfigurationException ex) {
            Logger.getLogger(Provklass.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(Provklass.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Provklass.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerConfigurationException ex) {
            Logger.getLogger(Provklass.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerException ex) {
            Logger.getLogger(Provklass.class.getName()).log(Level.SEVERE, null, ex);
        }

    }



}

更新: 使用 metsDoc.getInputEncoding() 返回 UTF-8,而 metsDoc.getXmlEncoding() 返回 ASCII。如果我在保存后解析新文件并创建一个新文档,我会得到相同的结果。所以文档似乎有正确的编码,但xml声明不正确。

现在我在解析之前将 xml 编辑为文本文件,将上面的解析部分替换为 parseXML(chosenFile.getAbsoutePath()); 并使用以下方法:

private String withEditedDeclaration(String fileName) {
    StringBuilder text = new StringBuilder();
    try {

        String NL = System.getProperty("line.separator");
        try (Scanner scanner = new Scanner(new FileInputStream(fileName))) {
            String line = scanner.nextLine();
            text.append(line.replaceFirst("ASCII", "UTF-8") + NL);
            while (scanner.hasNextLine()) {

                text.append(scanner.nextLine() + NL);
            }
        }

    } catch (FileNotFoundException ex) {
        Logger.getLogger(MetsAdaption.class.getName()).log(Level.SEVERE, null, ex);
    } 
    return text.toString();
}

private void parseXML(String fileName) throws SAXException, IOException, ParserConfigurationException {
    String xmlString = withEditedDeclaration(fileName);

    //parsing the xml file
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    DocumentBuilder builder = factory.newDocumentBuilder();
    InputSource is = new InputSource();
    is.setCharacterStream(new StringReader(xmlString));
    metsDoc = builder.parse(is);
}

它有效,但它似乎是一个丑陋的解决方案。如果有人知道更好的方法,我将不胜感激。

【问题讨论】:

  • 也许这可以帮助你:stackoverflow.com/questions/3578395/…
  • @Berger 谢谢你的小费。但是,我认为这不能解决我的问题。 OutputFormat 似乎已被弃用,我已经使用了 transformer.setOutputProperty(OutputKeys.ENCODING, encoding)。我想我需要编辑文档的声明,但我不知道该怎么做。
  • 看起来这应该可以工作(DocumentBuilder 应该尊重 xml 声明)。这使我认为您的文档可能不正确。您能否检查您的基本文件是否真的是 ASCII 文档(不仅在其 XML 序言中这么说,而且如果您查看实际字节,这实际上是真的吗?)。
  • @GPI 谢谢。根据 Firefox,原始文档是 Windows-1252,所以也许这就是问题所在。
  • @GPI 如果我将原始文档的声明更改为 Windows-1252,我仍然会在解析后得到输入编码 UTF-8(xml 编码 Windows-1252),你知道是什么原因造成的吗? DocumentBuilder 的默认编码是 UTF-8 吗?我找不到这方面的任何信息。我可以以某种方式设置 DocumentBuilder 使用的编码吗?

标签: java xml encoding utf-8 xml-declaration


【解决方案1】:

我在最初的 xml 声明中遇到了类似的问题:

<?xml version="1.0" encoding="windows-1252"?>

但是在解析为 Document 然后返回 XMLUTF-8 后,编码保持为 windows-1252,即使字节本身位于 UTF-8。我最终发现TransformerFactory 的实现是com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl 将其更改为:

org.apache.xalan.processor.TransformerFactoryImpl

来自 Apache Xalan Java 2.7.1 导致 XML 减速中的字符集被正确设置,现在我有了:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

【讨论】:

    猜你喜欢
    • 2011-11-25
    • 2014-10-18
    • 1970-01-01
    • 2020-04-23
    • 2019-07-26
    • 1970-01-01
    • 2018-05-11
    • 2015-02-01
    相关资源
    最近更新 更多