DOM4J 解析 XML 之忽略转义字符

栏目: 编程语言 · XML · 发布时间: 5年前

内容简介:项目开发需要手动合入几十种语言的翻译到 string.xml 中,这是一件非常痛苦的事情:Copy、Paste,Copy、Paste,Copy、Paste... 人都快疯了!被逼无奈写了个自动替换翻译的工具。原理很简单:解析 Excel中的翻译,替换到 Xml 中。Excel 解析用 jxl.jar,Xml 解析与修改用 DOM,一顿操作,一天就写完了!正高兴呢,赶紧使用 git diff 查看修改对比,一看坏事了:“坑爹呢!一点也不完美啊!原字符串中的转义字符全被转义了好嘛!难道还要手动还回去嘛!像我这样

项目开发需要手动合入几十种语言的翻译到 string.xml 中,这是一件非常痛苦的事情:Copy、Paste,Copy、Paste,Copy、Paste... 人都快疯了!被逼无奈写了个自动替换翻译的工具。原理很简单:解析 Excel中的翻译,替换到 Xml 中。Excel 解析用 jxl.jar,Xml 解析与修改用 DOM,一顿操作,一天就写完了!正高兴呢,赶紧使用 git diff 查看修改对比,一看坏事了:“坑爹呢!一点也不完美啊!原字符串中的转义字符全被转义了好嘛!难道还要手动还回去嘛!像我这样优(懒)秀(惰)的人根本无法容忍好嘛!” 所以,本文记录如何使用 DOM4J(上面不是说用 DOM 解析吗?这里怎么又成 DOM4J 了?忽悠谁呢!) 解析 XML 并让其忽略转义字符。

为什么不用 DOM

谁说我没用 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"));
    }

}
复制代码

strings.xml:

DOM4J 解析 XML 之忽略转义字符

解析日志:

DOM4J 解析 XML 之忽略转义字符

strings_copy.xml:

DOM4J 解析 XML 之忽略转义字符

DOM 解析保存 XML 文件的问题:

document.setXmlStandalone(true);

所以,我不用 DOM,而是用 DOM4J。用了 DOM4J 这些问题都将成为浮云!

DOM4J 解析

太简单啦!直接阅读官方指南即可!我从未见过如此简洁明了的 API 文档!

DOM4J 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:

DOM4J 解析 XML 之忽略转义字符

怎么样?看看这输出,一点毛病没有!

忽略转义字符

其实这是 SAX(Simple Application Interface For Xml) 解析的问题,SAX 解析 XML 时,会自动将元素文本中的转义字符转义,导致最后将 Document 对象保存为文件时,无法将原转义字符写回:

原文件:

DOM4J 解析 XML 之忽略转义字符

DOM4J 解析再写回:

DOM4J 解析 XML 之忽略转义字符

所以,我们需要实现一个过滤器,每当 SAX 解析一个转义字符,我们就将其原样写回:

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); 即可原样输出原 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();
复制代码

测试结果:

DOM4J 解析 XML 之忽略转义字符

日志:

DOM4J 解析 XML 之忽略转义字符

strings_dom4j.xml:

DOM4J 解析 XML 之忽略转义字符

其它的转义字符也是同样的处理方法。可以将要忽略的转义字符放到配置文件中,做 工具 的时候从配置中读取要忽略的转义字符,这样更灵活。

总结

本文只写了最终的解决方案,实际上探索这个解决方案的过程还是比较复杂的。需求小众,没什么资料,只能看源码,猜接口,反正我是不相信这样的解析框架是没有暴露用户自行处理字符串的接口的。果然还是可以通过 characters() 方法,只是 SAXReader 没有暴露 ContentHandler 接口,内部封装成了 SAXContentHandler,characters() 方法则暴露到了 XMLFilter 接口中,哈,一番好找。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

图灵的秘密

图灵的秘密

Charles Petzold / 杨卫东 / 人民邮电出版社 / 2012-11 / 69.00元

图灵机是英国数学家阿兰•图灵提出的一种抽象计算模型,本书深入剖析了图灵这篇描述图灵机和可计算性的原始论文《论可计算数及其在判定性问题上的应用》。书中在详解论文的同时,也附带了大量的历史背景资料、图灵的个人经历,以及图灵机对于人们理解计算机、人类意识和宇宙所产生的影响。 本书适合所有计算机科学专业的学生、程序员或其他技术人员,同时也适合欲了解图灵生平及其构建图灵机的思维的读者阅读。一起来看看 《图灵的秘密》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具