Опыт проекта, если нужно перепечатать, просьба указать автора: Yuloran (t.cn/EGU6c76)
задний план
При разработке проекта приходится вручную сливать переводы десятков языков в string.xml, что очень мучительно: Копировать, Вставить, Копировать, Вставить, Копировать, Вставить... Люди сходят с ума! Я был вынужден написать инструмент, который автоматически заменяет перевод. Принцип прост: парсить перевод в Excel и заменять в Xml. Парсинг Excel использует jxl.jar, парсинг и модификация Xml использует DOM, одна операция, один день! Я был счастлив, поэтому быстро использовал git diff для проверки сравнения модификаций и увидел что-то нехорошее: «Что за дурак! Это совсем не идеально! Все escape-символы в исходной строке были экранированы! вернуть его? Такие люди, как я, которые превосходны (ленивы) и показывают (ленивы), вообще не могут этого терпеть!" Поэтому в этой статье описано, как использовать DOM4J (разве выше не говорится о парсинге DOM? Почему DOM4J здесь снова Кто это!) XML и игнорировать escape-символы.
Почему бы не использовать ДОМ
Кто сказал, что я не использовал DOM, я использовал DOM, как только придумал! В конце концов, JDK поставляется вместе с ним! Но после его использования пользовательский опыт плохой! Немного о том, как его использовать:
package com.yuloran;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
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.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, TransformerException {
// 1. 解析
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
Document document = documentBuilder.parse(new InputSource(new InputStreamReader(new FileInputStream("strings.xml"), "UTF-8")));
// 2. 遍历
NodeList strings = document.getElementsByTagName("string");
for (int i = 0; i < strings.getLength(); i++) {
Node item = strings.item(i);
System.out.print(String.format("Element:[tag:%s, content:%s] ", item.getNodeName(), item.getTextContent()));
NamedNodeMap attributes = item.getAttributes();
for (int j = 0; j < attributes.getLength(); j++) {
Node attr = attributes.item(j);
System.out.println(String.format("Attr:[key:%s, value:%s]", attr.getNodeName(), attr.getNodeValue()));
}
}
// 3. 保存
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(document), new StreamResult("strings_copy.xml"));
}
}
строки.xml:
Разобрать журнал:
strings_copy.xml:
Проблемы с разбором DOM при сохранении файлов XML:
- standalone="no" автоматически добавляется в объявление XML-документа, доступ к которому можно получить через
document.setXmlStandalone(true);
удалить, но тогда отступ не удастся! - Новые строки файлов автоматически заменяются новыми строками там, где находится операционная система!
Итак, вместо DOM я использую DOM4J. С DOM4J эти проблемы станут облаками!
Разбор DOM4J
Это очень просто! читать напрямуюОфициальное руководствоВот и все! Я никогда не видел документации по API такой четкой и лаконичной!
Пакет JAR DOM4J и загрузка зависимостей:
-
Нажмите на меня, чтобы скачать dom4j-2.1.0.jar
Взгляните на скриншот:
Если dom4j является зависимостью от maven в проекте, нет необходимости загружать jaxen.jar вручную. Если это jar-зависимость, вам также необходимо скачать jaxen.jar, иначе класс не будет найден при компиляции.
Пример использования DOM4J
package com.yuloran;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;
import java.io.*;
import java.util.List;
public class Main {
public static void main(String[] args) throws DocumentException, IOException {
// 1. 解析
SAXReader reader = new SAXReader();
Document document = reader.read(new InputSource(new InputStreamReader(new FileInputStream("strings.xml"), "UTF-8")));
// 2. 遍历
List<Node> list = document.selectNodes("/resources/string[@name]");
for (Node node : list) {
System.out.print(String.format("Element:[tag:%s, content:%s] ", node.getName(), node.getText()));
System.out.println(String.format("Attr:[name@%s]", node.valueOf("@name")));
}
// 3.保存
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("strings_dom4j.xml"), "UTF-8");
XMLWriter xmlWriter = new XMLWriter(writer);
// 忽略 Element 对象中的转义字符
xmlWriter.setEscapeText(false);
xmlWriter.write(document);
xmlWriter.close();
}
}
strings_dom4j.xml:
как насчет этого? Посмотрите на этот вывод, в нем нет ничего плохого!
игнорировать escape-символы
На самом деле это проблема синтаксического анализа SAX (Simple Application Interface For Xml).Когда SAX анализирует XML, он автоматически экранирует escape-символы в тексте элемента, так что, когда объект документа, наконец, будет сохранен в виде файла, исходный escape-символы не могут быть записаны.
Исходный файл:
Разбор DOM4J и обратная запись:
Итак, нам нужно реализовать фильтр, который всякий раз, когда SAX анализирует escape-символ, записывает его как есть:
reader.setXMLFilter(new XMLFilterImpl() {
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String text = new String(ch, start, length);
System.out.println("text is: " + text);
if (length == 1) {
if ((int) ch[0] == 160) {
char[] escape = " ".toCharArray();
super.characters(escape, 0, escape.length);
return;
}
}
super.characters(ch, start, length);
}
});
ПеределкаxmlWriter.setEscapeText(false);
Вы можете вывести escape-символы в исходном файле Xml так, как они есть:
// 3.保存
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("strings_dom4j.xml"), "UTF-8");
XMLWriter xmlWriter = new XMLWriter(writer);
xmlWriter.setEscapeText(false);
xmlWriter.write(document);
xmlWriter.close();
Результаты теста:
журнал:
strings_dom4j.xml:
Другие escape-символы обрабатываются таким же образом. Вы можете поместить управляющие символы, которые будут игнорироваться в файле конфигурации, и прочитать управляющие символы, которые будут игнорироваться, из конфигурации при создании инструментов, что является более гибким.
Суммировать
В этой статье написано только окончательное решение, и процесс изучения этого решения на самом деле довольно сложен. Спрос небольшой, а информации нет.Можно только посмотреть исходный код и угадать интерфейс.В любом случае, я не верю, что такой фреймворк парсинга не выставляет интерфейс для самостоятельной обработки строк пользователями. Разумеется, по-прежнему можно передавать метод character(), но SAXReader не предоставляет интерфейс ContentHandler. найти.