Изменить кодировку декларации XML с помощью Java

Я редактирую xml-файл с оригинальной кодировкой ASCII в объявлении. В полученном файле я хочу, чтобы кодировкой была UTF-8, чтобы писать такие шведские символы, как åäö, чего я сейчас не могу сделать.

Пример файла, эквивалентный моему файлу, можно найти на сайте archivematica wiki.

Полученный файл SIP.xml, который я получаю после запуска моей программы с копией файла примера выше, можно найти по этой ссылке. Добавленный тег с текстом åäö находится в самом конце документа.

Как видно из кода ниже, я попытался установить кодировку на преобразователе, а также попытался использовать 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);
}

Это работает, но кажется уродливым решением. Я был бы очень признателен, если бы кто-нибудь знал лучший способ.

1 ответ

У меня была похожая проблема, где мое объявление XML было изначально:

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

Но после разбора на Document а затем вернуться к XML как UTF-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"?>
Другие вопросы по тегам