Я редактирую xml-файл с исходной кодировкой ASCII в объявлении. В результирующем файле я хочу, чтобы кодировка была UTF-8, чтобы писать шведские символы, такие как åäö, чего я не могу сделать в данный момент.Редактировать кодировку объявления xml с помощью java
Пример файла, эквивалентного моему файлу, можно найти по адресу 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);
}
}
}
UPDATE: Использование 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);
}
Это работает, но кажется, уродливые решения. Я был бы очень благодарен, если бы кто-нибудь знал лучший способ.
Возможно, это может вам помочь: http://stackoverflow.com/questions/3578395/java-xml-documentbuilder-setting-the-encoding-when-parsing – Berger
@Berger Спасибо за ваш совет. Однако я не думаю, что это решает мою проблему. OutputFormat кажется устаревшим, и я уже использовал transformer.setOutputProperty (OutputKeys.ENCODING, кодирование). Я думаю, мне нужно отредактировать декларацию документа, но я не знаю, как это сделать. – ostid
Кажется, что это должно работать («DocumentBuilder» должен соблюдать декларацию xml). Это заставляет меня думать, что ваш документ может быть не совсем в порядке. Не могли бы вы проверить, действительно ли ваш базовый файл является ASCII-документом (не только он говорит это в своем прологе XML, но это действительно так, если вы посмотрите на фактические байты?). – GPI