在连续吹了好几天的JSON,但最终还是低头了。太多原始开发和老旧的API依旧使用,W3C这一大腿还真是抱的的爽,虽然吐槽其笨重但是必要的解析还是要会。我们基本上在Java当中有三种办法可以解决这次的问题 。
DOM解析
在Java当中DOM 是 W3C 处理 XML 的标准 API,它是许多其它与 XML 处理相关的标准的基础,不仅是 Java,其它诸如 Javascript,PHP,MS .NET 等等语言都实现了该标准, 成为了应用最为广泛的 XML 处理方式。当然,为了能提供更多更加强大的功能,Java 对于 DOM 直接扩展工具类有很多,比如很多 Java 程序员耳熟能详的 JDOM,DOM4J 等等, 它们基本上属于对 DOM 接口功能的扩充,保留了很多 DOM API 的特性。所以一般意义来讲一个具有通行标准的方法值得去关注。
处理方式:
将XML整个作为类似树结构的方式读入内存中以便操作及解析,因此支持应用程序对XML数据的内容和结构进行修改,但是同时由于其需要在处理开始时将整个 XML 文件读入到内存中去进行分析,因此其在解析大数据量的 XML 文件时会遇到类似于内存泄露以及程序崩溃的风险。根据DOM,XML被文档视为一种树结构。这种树结构被称为节点树。文档中的每个成分都是一个节点(Node)。可通过这棵树访问所有节点。可以修改或删除它们的内容,也可以创建新的元素。
上面也有说到是按照节点处理:XML 文档的 documentElement 属性是根节点。而旗下就有更多东西了,而在Java当中拥有众多方法来帮你完成解析大部分的工作,在解析过程当中,我们规定NodeType为1则是元素 ,属性 2 ,文本 3 ,注释 8 ,文档 9 这样来定义,而更其NodeName更是只对应相应类型的名字。
适用范围:
小型 XML 文件解析、需要全解析或者大部分解析 XML、需要修改 XML 树内容以生成自己的对象模型
在Java当中的使用方法:
//javax.xml.parsers 包中的 DoumentBuilder 和DocumentBuilderFactory 用于解析 XML 文档生成对应的 DOM Document 对象。 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //创建文档创建器 DocumentBuilder builder = dbf.newDocumentBuilder(); //创建Dom文档 Document dom = builder.parse(new File(fileName)); //javax.xml.transform.dom 和 javax.xml.transform.stream 包中 DOMSource 类和 StreamSource 类,用于将更新后的 DOM 文档写入 XML 文件 DOMSource source = new DOMSource(d); Transformer trans = TransformerFactory.newInstance() .newTransformer(); StreamResult result = new StreamResult( new FileOutputStream(new File(fileName))); trans.transform(source, result);
这样我们可以用DOM来解析:
public static void DomXMl() throws Exception {
Map<String, Double> tknine = new HashMap<String, Double>();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
Document doc = db.parse(new File("src/user.xml"));
Element root = doc.getDocumentElement();
NodeList cls = root.getChildNodes();
for (int i = 0; i < cls.getLength(); i++) {
Node node = cls.item(i);
if (node.getNodeType() == 1) {
NamedNodeMap map = node.getAttributes();
NodeList tk = node.getChildNodes();
for (int j = 0; j < tk.getLength(); j++) {
Node tkj = tk.item(j);
Node tks = map.item(j);
if (!tknine.containsKey(tks.getNodeValue())) {
tknine.put(tks.getNodeValue(),
Double.parseDouble(tkj.getTextContent()));
} else if (tknine.containsKey(tks.getNodeValue())) {
double ks = tknine.get(tks.getNodeValue());
tknine.put(tks.getNodeValue(),
Double.parseDouble(tkj.getTextContent()) + ks);
}
}
}
}
for (String ks : tknine.keySet()) {
System.out.println(ks + "消费了:" + tknine.get(ks));
}
}
利用DOM进行写入:
public static void WriteByDom() throws Exception {
Document doc = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
Element root = doc.createElement("records");
for (String ks : tknine.keySet()) {
Element record = doc.createElement("record");
Element name = doc.createElement("name");
Element price = doc.createElement("price");
name.setTextContent(ks);
price.setTextContent("" + tknine.get(ks));
root.appendChild(record);
record.appendChild(name);
record.appendChild(price);
}
doc.appendChild(root);
TransformerFactory tff = TransformerFactory.newInstance();
Transformer tf = tff.newTransformer();
tf.setOutputProperty(OutputKeys.INDENT, "yes");// huanhang
tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");//滑稽 控制格式输出
DOMSource sourse = new DOMSource(doc);
Result result = new StreamResult(new File("src/writeByDom.xml"));
tf.transform(sourse, result);
}
被操作的xml:
<?xml version="1.0" encoding="UTF-8"?> <users> <user name ="tom">26.5</user> <user name ="jack">126.5</user> <user name ="tom">29.5</user> <user name ="terry">66.5</user> <user name ="marry">29.5</user> <user name ="ody">95.5</user> <user name ="jack">96.5</user> <user name ="tom">46.5</user> </users>

JDOM解析
一款蛮针对Java的解析办法(创作者就是Java开发者),它简化了DOM更迅速,利用大量接口尤其collections,熟悉Java语言的话是要比DOM好用几倍的(这里说下特点吧)
JDOM 与 DOM 主要有两方面不同。首先,JDOM 仅使用具体类而不使用接口。这在某些方面简化了 API,但是也限制了灵活性。第二,API 大量使用了 Collections 类,简化了那些已经熟悉这些类的 Java 开发者的使用。
JDOM 文档声明其目的是“使用 20%(或更少)的精力解决 80%(或更多)Java/XML 问题”(根据学习曲线假定为 20%)。JDOM 对于大多数 Java/XML 应用程序来说当然是有用的,并且大多数开发者发现 API 比 DOM 容易理解得多。JDOM 还包括对程序行为的相当广泛检查以防止用户做任何在 XML 中无意义的事。然而,它仍需要您充分理解 XML 以便做一些超出基本的工作(或者甚至理解某些情况下的错误)。这也许是比学习 DOM 或 JDOM 接口都更有意义的工作。
JDOM 自身不包含解析器。它通常使用 SAX2 解析器来解析和验证输入 XML 文档(尽管它还可以将以前构造的 DOM 表示作为输入)。它包含一些转换器以将 JDOM 表示输出成 SAX2 事件流、DOM 模型或 XML 文本文档。JDOM 是在 Apache 许可证变体下发布的开放源码。(段落转自:http://blog.csdn.net/shijinupc/article/details/7653945,里面描述了各种解析办法之间的不同和优缺点)
DOM4j解析
DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,是jdom的升级品,大量使用接口(个人感觉最op//同样都是小文件的话)在开源项目当中大量使用。其解析办法(依旧针对以上的xml文件):
public static void SaxXMl() throws Exception {
SAXReader reader = new SAXReader();
Document dom = reader.read(new File("src/user.xml"));
Element root = dom.getRootElement();
List<Element> child = root.elements();
for (Element e : child) {
List<Attribute> rs = e.attributes();
for (Attribute aks : rs)
if (!tknine.containsKey(aks.getValue())) {
tknine.put(aks.getValue(),
Double.parseDouble(e.getTextTrim()));
} else if (tknine.containsKey(aks.getValue())) {
double ks = tknine.get(aks.getValue());
tknine.put(aks.getValue(),
Double.parseDouble(e.getTextTrim()) + ks);
}
}
for (String ks : tknine.keySet()) {
System.out.println(ks + "消费了:" + tknine.get(ks));
}
}
而写入在这里:
public static void WriteByDom4j() throws Exception {
Document doc = DocumentFactory.getInstance().createDocument();
Element root = doc.addElement("records");
for (String ks : tknine.keySet()) {
Element record = root.addElement("record");
Element name = record.addElement("name");
Element price = record.addElement("price");
name.setText(ks);
price.setText("" + tknine.get(ks));
}
OutputFormat of = new OutputFormat();
of.setNewlines(true);
of.setIndent("\t");
FileWriter fw = new FileWriter("src/writerByDom4J.xml");
XMLWriter writer = new XMLWriter(fw, of);
writer.write(doc);
fw.close();
writer.close();
}
SAX解析
通过类似于流解析的技术,通读整个 XML文档树,通过事件处理器来响应程序员对于 XML数据解析的需求(所以说sax是基于事件处理的)。由于其不需要将整个XML文档读入内存当中,它对系统资源的节省是十分显而易见的,它在一些需要处理大型XML文档以及性能要求较高的场合有起了十分重要的作用
适用范围:大型 XML 文件解析、只需要部分解析或者只想取得部分 XML 树内容、有 XPath 查询需求、有自己生成特定 XML 树对象模型的需求
显然面对大文件时SAX的优势一显无疑,事件处理给予SAX更强的能力,但是编码困难就不吐槽了(对于新手极不友好
)
综述
以上有四种解析方法,在小文档情况下还值得考虑使用 DOM 和 JDOM。另外,DOM 仍是一个非常好的选择。DOM 实现广泛应用于多种编程语言。它还是许多其它与 XML 相关的标准的基础,在某些类型的项目中可能也需要它(如在 javascript 中使用 DOM)。SAX解析大文件较强,这要依赖于它特定的解析方式。一个 SAX 检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。最后在这四种中强烈推DOM4j(今天编程过程愉悦且人性)。溜啦=-=