XML文件解析

作者:xcbeyond
疯狂源自梦想,技术成就辉煌!微信公众号:《程序猿技术大咖》号主,专注后端开发多年,拥有丰富的研发经验,乐于技术输出、分享,现阶段从事微服务架构项目的研发工作,涉及架构设计、技术选型、业务研发等工作。对于Java、微服务、数据库、Docker有深入了解,并有大量的调优经验。












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 文档的步骤如下:
创建 SAXParserFactory 的实例
创建 SAXParser 的实例
创建 SAXParserHandler 类
使用 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 编码模式,用以来弥补DOM及SAX在实际应用当中的不足之处。
这些不足之处主要在于SAX没有文档修改、随机访问以及输出的功能,而对于DOM来说,在使用时来用起来不太方便。
在 JDOM 中,XML 元素就是 Element 的实例,XML 属性就是 Attribute 的实例,XML 文档本身就是 Document 的实例。
因为 JDOM 对象就是像 Document、Element 和 Attribute 这些类的直接实例,因此创建一个新 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.dom的jar包
1.实例化一个合适的解析器对象
SAXBuilder builder = new SAXBuilder();
2.构建一个文档对象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是一个Java的XML API,类似于jdom,用来读写XML文件的。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。

1.读取并解析XML文档:
读写XML文档主要依赖于org.dom4j.io包,其中提供DOMReader和SAXReader两类不同方式,而调用方式是一样的。这就是依靠接口的好处。 // 从文件读取XML,输入文件名,返回XML文档
public Document read(String fileName) throws MalformedURLException, DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(fileName));
return document;
}
2、取得Root节点
  public Element getRootElement(Document doc){
return doc.getRootElement();
}

3、遍历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....
       }
  }
 }
获取节点数量,包含自身。 这个方法所遍历出来的对象是多种的,node,namespace,text等类型的。 if(element instanceof Element) 条件 element.nodeCount()==1 表示当前元素是子元素

4. 创建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;
}
5字符串与XML的转换
有时候经常要用到字符串转换为XML或反之
// XML转字符串
Document document = ...;
String text = document.asXML();
// 字符串转XML
String text = <name>James</name>   
Document document = DocumentHelper.parseText(text);
6文件输出
一个简单的输出方法是将一个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();
}