XML 文件解析 | Java Debug 笔记

1,118 阅读6分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看<活动链接>

在实际工作中,对 XML 文件的操作是非常常见的,在此将对 XML 文件的解析展开讨论,与大家分享一下,希望以后工作中遇到能够快速上手。

XML解析

xml 文件中由于更多的是描述信息的内容,所以在得到一个xml文档之后应该利用程序按照里面元素的定义名称取出对应的内容,这一过程就称为xml解析。

解析xml文件的4种方式:

  1. DOM         
  2. SAX
  3. JDOM    
  4. DOM4J

文档对象模型(DOM)

  • DOM ---对象化的 XML数据接口

它定义了XML文档的逻辑结构,给出了一种访问和处理XML文档的方法。利用DOM,程序开发人员可以动态地创建文档,遍历文档结构,添加、修改、删除文档内容,改变文档的显示方式等等。

  • DOM

DOM 这个层次的结构是一棵根据 XML 文档生成的节点树。在这棵节点树中,有一个根节点--Document节点,所有其他的节点都是根节点的后代节点。节点树生成之后,就可以通过 DOM 接口访问、修改、添加、删除、创建树中的节点和内容。

读入xml:

DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
// 获取解析器
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析xml文档
Document doc = builder.parse(new File("src\\dom.xml"));
Element root = builder.getDocumentElement();//获得根元素
写回xml:
TransformerFactory tfactory=TransformerFactory.newInstance();
Transformer tformer = tfactory.newTransformer();
tformer.transform(new DOMSource(doc), new StreamResult(new FileOutputStream("src\\dom1.xml")));

得到文档模型的根元素
Element root = doc.getDocumentElement();  
元素Element的函数:
String getTagName()   -得到标签的名字
String getAttribute(“unit”) -得到元素的unit属性值
节点Node的函数:
NodeList  getChildNodes()   - 得到子节点的集合
Node getFirstChild()         - 得到第一个子节点
Node getLastChild()        - 得到最后一个子节点

节点Node的函数:
Node getNextSibling() - 得到下一个兄弟节点
Node getPreviousSibling()   - 得到前一个兄弟结点
Node getParentNode()     - 得到父节点
NamedNodeMap getAttributes()  - 得到所有的属性集合
String getNodeName()         - 得到当前节点的名字
String getNodeValue()   - 得到当前节点的值
NodeList的函数
int getLength()    -得到集合长度
Node item(int index)  - 得到集合中的一个元素

写XML文档函数
DocumentBuilder 的函数:
Document doc = builder.newDocument(); -新建一个模型
Document 的函数:
Element createElement(String name) – 建立一个元素
Text createTextNode(String data)-创建一个文本节点
Node的函数:
Node appendChild(Node child)  - 添加一个子节点
Element 的函数:
void setAttribute(String name, String value)  - 设置元素的一个属性和属性值

简单应用程序接口(SAX)

SAX 是一种事件驱动的接口,它的基本原理是由接口的用户提供符合定义的处理器,XML 分析时遇到特定的事件,就去调用处理器中特定事件的处理函数。

捕获和响应各个事件:

  • startDocument( ) endDocument( ) 事件是在文档的起始处和结束处被激发的
  • startElement( ) endElement( ) 事件是在遇到起始标记和结束标记时被激发的
  • characters( ) 事件是在遇到字符数据时被激发的

使用 SAX 解析 XML 文档的步骤如下:

(1)创建 SAXParserFactory 的实例

(2)创建 SAXParser 的实例

(3)创建 SAXParserHandler

(4)使用 parse() 方法解析 XML 文档

SAXParserFactory spfactory = SAXParserFactory.newInstance();
// 生成SAX解析对象
SAXParser parser = spfactory.newSAXParser();
// 指定XML文件,进行XML解析
 parser.parse(new File("src\\dom.xml"), new SaxReader());

Jdom

JDOM 使用标准的 Java 编码模式,用以来弥补 DOMSAX 在实际应用当中的不足之处。

这些不足之处主要在于 SAX 没有文档修改、随机访问以及输出的功能,而对于 DOM 来说,在使用时来用起来不太方便。

JDOM 中,XML 元素就是 Element 的实例,XML 属性就是 Attribute 的实例,XML 文档本身就是 Document 的实例。

因为 JDOM 对象就是像 DocumentElementAttribute 这些类的直接实例,因此创建一个新 JDOM 对象就如在 Java 语言中使用 new 操作符一样容易。而不使用复杂的工厂化模式,使对象操作更为方便。

Document类操作:

Element root=new Element("GREETING");
Document doc=new Document(root);
root.setText("HelloJDOM!");

Attribute 类操作:

Attribute rootAttri = new Attribute("comment","introduce myself");//创建名为 commnet,值为 introduce myself 的属性。
rootElement.setAttribute(rootAttri);//将刚创建的属性添加到根元素。

Element 类操作:

Element root=doc.getRootElement();//获得根元素element
List allChildren=root.getChildren();//获得所有子元素的一个list
List namedChildren=root.getChildren("name");//获得指定名称子元素的list
Element child=root.getChild(“name”);//获得指定名称的第一个子元素
allChildren.remove(3);//删除第四个子元素
allChildren.removeAll(root.getChildren("jack"));//删除叫“jack”的子元素
root.removeChildren("jack");//便捷写法
allChildren.add(new Element("jane"));//加入
root.addContent(new Element(“jane”));//便捷写法
Element nameElement = new Element("name");//创建 name 元素
nameElement.addContent("kingwong");//将kingwong作为content添加到name元素
rootElement.addContent(nameElement);//将name元素作为content添加到根元素 getAttributeValue("name") 返回指定属性名字的值。如果没有该属性则返回null,有该属性但是值为空,则返回空字符串。
getChildText("childname") 返回指定子节点的内容文本值。  
root.getChild("book").getChild("name").getText();
root.getChild("book").getChild("name").setText("dsgdghdgasg");

解析xml:

使用 Jdom 解析 xml 要导入 org.domjar

  1. 实例化一个合适的解析器对象
SAXBuilder builder = new SAXBuilder();
  1. 构建一个文档对象doc
Document doc = builder.build(new File("src\\dom.xml"));

XML 文档输出:

XMLOutputter outputter=new XMLOutputter();
outputter.output(doc,new FileOutputStream("src\\dom.xml"));

Dom4j

Dom4j 是一个 JavaXML API,类似于 jdom,用来读写 XML 文件的。它应用于 Java 平台,采用了 Java 集合框架并完全支持DOMSAXJAXP

  1. 读取并解析 XML 文档:

读写 XML 文档主要依赖于 org.dom4j.io 包,其中提供 DOMReaderSAXReader 两类不同方式,而调用方式是一样的。这就是依靠接口的好处。

// 从文件读取XML,输入文件名,返回XML文档
public Document read(String fileName) throws MalformedURLException, DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(fileName));
return document;
}
  1. 取得 Root 节点
public Element getRootElement(Document doc){
     return doc.getRootElement();
}
  1. 遍历 XML
for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
    // 枚举所有子节点
    Element element = (Element) i.next();
}
for ( Iterator i = root.elementIterator(foo); i.hasNext();) {
    // 枚举名称为foo的节点
    Element foo = (Element) i.next();
}

// 枚举属性
for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
    Attribute attribute = (Attribute) i.next();
}

递归也可以采用 Iterator 作为枚举手段,但文档中提供了另外的做法

public void treeWalk() {
         treeWalk(getRootElement());
 }
 public void treeWalk(Element element) {
       for (int i = 0, size = element.nodeCount(); i < size; i++) {
           Node node = element.node(i);
          if (node instanceof Element) {
              treeWalk((Element) node);
         }   else { // do something....
       }
  }
 }

获取节点数量,包含自身。 这个方法所遍历出来的对象是多种的,nodenamespacetext 等类型的。 if(element instanceof Element) 条件 element.nodeCount()==1 表示当前元素是子元素

  1. 创建XML
public Document createDocument() {
 Document document = DocumentHelper.createDocument();
 Element root = document.addElement(root);
 Element author1 =root.addElement(author).addAttribute(name, James)
  .addAttribute(location, UK).addText(James Strachan);
 Element author2 =root.addElement(author).addAttribute(name, Bob)
  .addAttribute(location, US).addText(Bob McWhirter);
 return document;
}
  1. 字符串与XML的转换

有时候经常要用到字符串转换为XML或反之.

// XML转字符串
Document document = ...;
String text = document.asXML();
// 字符串转XML
String text = <name>James</name>   
Document document = DocumentHelper.parseText(text);
  1. 文件输出

一个简单的输出方法是将一个Document或任何的Node通过write方法输出。

FileWriter out = new FileWriter( foo.xml );
document.write(out);
// 美化输出或缩进格式,可以用XMLWriter类 
public void write(Document document) throws IOException {
// 读取文件
FileWriter fileWriter = new FileWriter("src\\dom2.xml");
//OutputFormat xmlFormat = OutputFormat.createPrettyPrint();// 缩减型格式
OutputFormat xmlFormat =OutputFormat.createCompactFormat();//紧凑型格式
//format.setTrimText(false);//设置text中是否要删除其中多余的空格
xmlFormat.setEncoding("gb2312");// 设置编码
// 创建写文件方法
XMLWriter xmlWriter = new XMLWriter(fileWriter, xmlFormat);
// 写入文件
xmlWriter.write(document);
// 关闭
xmlWriter.close();
}