什么是 XML?
- XML 指可扩展标记语言(EXtensible Markup Language)
- XML 是一种标记语言,很类似 HTML
- XML 的设计宗旨是传输数据,而非显示数据
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
- XML 是 W3C 的推荐标准
对于xml文件,没有被定义好的标签,所有的标签都是用户自己定义,在读取解析的时候,根据标签可以获得想要的值
解析xml文件一共有四种方式,分别是:
- DOM
- SAX
- JDOM
- DOM4J
下面详细的介绍这几种方式:
一、DOM(Document Object Model)
Dom解析是将xml文件全部载入,组装成一颗DOM树(树状结构),然后通过节点以及节点之间的关系来解析xml文件,下面结合这个xml文件来进行dom解析。由于DOM这种在加载的时候需要把文件全部加载进内存才可以进行解析的方式,也带来了问题,在xml文件小的情况下可以使用,当一个xml文件相当大的时候,对计算机资源的消耗也是一个不小的开销
xml文件:
<school><student><no>1001</no><name>小明</name><score>20</score></student><student><no>1002</no><name>小红</name><score>80</score></student>
</school>
实例:
package demo_xml;import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;public class Dom {public static void main(String[] args) {try {//创建解析器DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();//把xml文件加载进内存Document document = db.parse("E:\\IntelliJ IDEA\\jvm\\src\\test.xml");//获取文件中的根节点NodeList root = document.getChildNodes();for (int i = 0; i < root.getLength(); i++) {Node childNodes = root.item(i);//通过根节点获取子节点NodeList childNodes1 = childNodes.getChildNodes();for (int j = 0; j < childNodes1.getLength(); j++) {Node node = childNodes1.item(j);//获取子节点的子节点NodeList value = node.getChildNodes();//遍历各个节点的属性值for (int k = 0; k < value.getLength(); k++) {if(value.item(k).getNodeName() != "#text") {System.out.println(value.item(k).getNodeName()+ ":" + value.item(k).getTextContent());}}System.out.println();}}} catch (ParserConfigurationException e) {e.printStackTrace();} catch (SAXException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
二、SAX(Simple API for XML)
sax这种解析方式在官方的解释是类似于流媒体的方式。我们可以简单的总结为,sax方式可以做到一边扫面文档,一边解析文档,不用把文件加载到内存中,相比于DOM解析方式,SAX方式对于大型的文件是一种很好的解决办法,减少了对内存的消耗。还有就是SAX解析方式是一种基于事件的方式,在解析xml文件的时候就是触发了一系列的事件,当遇到用户给定的标签的时候,会停止解析,这样在时间和空间上都是优于DOM解析的(DOM解析需要把文档全部加载进内存才能开始解析)
要使用SAX解析首先要创建触发器这个类,要创建这个类首先需要继承DefaultHandler,重写方法
xml文件被SAX解析器载入,由于SAX解析是按照xml文件的顺序来解析,当最开始读取xml文档的时候,会调用startDocument()方法,当读入<school>的时候,由于它是个ElementNode,所以会调用startElement(String uri, String localName, String qName, Attributes attributes) 方法,其中第二个参数就是节点的名称,注意:由于有些环境不一样,有时候第二个参数有可能为空,所以可以使用第三个参数,因此在解析前,先调用一下看哪个参数能用,第4个参数是这个节点的属性。这里我们不需要这个节点,所以从<student>这个节点开始,当读入时,调用startElement(....)方法,然后在no标签的地方会调用characters(char[] ch, int start, int length)方法,Sax解析器会把它认为是一个TextNode。但是这个空白不是我们想要的数据,我们是想要<no>节点下的文本信息。这就要定义一个记录当上一节点的名称的TAG,在characters(.....)方法中,判断当前节点是不是name,是再取值,才能取到值
代码:
package demo_xml;import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;public class Sax {public static void parserXml(String fileName) {SAXParserFactory saxfac = SAXParserFactory.newInstance();try {SAXParser saxparser = saxfac.newSAXParser();InputStream is = new FileInputStream(fileName);saxparser.parse(is, new MySaxHandler());} catch (ParserConfigurationException e) {e.printStackTrace();} catch (SAXException e) {e.printStackTrace();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {Sax.parserXml("E:\\IntelliJ IDEA\\jvm\\src\\test.xml");}
}
class MySaxHandler extends DefaultHandler {boolean hasAttribute = false;Attributes attributes = null;@Overridepublic void startDocument() throws SAXException {System.out.println("文档解析");}@Overridepublic void endDocument() throws SAXException {System.out.println("文档结束");}@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {if (qName.equals("users")) {return;}if (qName.equals("user")) {return;}if (attributes.getLength() > 0) {this.attributes = attributes;this.hasAttribute = true;}}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {if (hasAttribute && (attributes != null)) {for (int i = 0; i < attributes.getLength(); i++) {System.out.print(attributes.getQName(0) + ":"+ attributes.getValue(0));}}}@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {System.out.print(new String(ch, start, length));}
}
三、JDOM(Java-based Document Object Model)
JDOM也是将xml文件构建成一个树状结构,实现解析,所以代码和DOM很像,但是 JDOM自身不包含解析器。它通常使用SAX2解析器来解析和验证输入XML文档,所以可以说JDOM是DOM和SAX的一个结合体也差不多,把SAX和DOM的功能有效地结合起来。实现了解析xml文档的功能。在代码中我们可以看到SAX和DOM解析代码的片段
package demo_xml;import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;import java.util.List;public class Jdom {public static void main(String[] args) throws Exception {//构建加载器,加载xml文档SAXBuilder builder = new SAXBuilder();Document document = builder.build("E:\\IntelliJ IDEA\\jvm\\src\\test.xml");//获取根节点Element root = document.getRootElement();//通过根节点获取子节点的集合List childList = root.getChildren("student");//遍历集合for (int i = 0; i < childList.size(); i++) {Element childs = (Element) childList.get(i);//通过上一级节点获取子节点List child = childs.getChildren();for (int j = 0; j < child.size(); j++) {System.out.println(((Element) child.get(j)).getName()+ ":" + ((Element) child.get(j)).getValue());}System.out.println();}}
}
四、DOM4J(Document Object Model for Java)
DOM4J是目前使用最广泛的,hibernate框架使用的解析方式就是DOM4J,DOM4J使用接口和抽象基本类方法,在代码上也容易理解(在使用DOM4J时需要下载jar包)
package demo_xml;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import java.io.File;
import java.net.MalformedURLException;
import java.util.Iterator;public class Dom4j {public static void main(String[] args) {//加载解析器File inputXml = new File("E:\\IntelliJ IDEA\\jvm\\src\\test.xml");SAXReader saxReader = new SAXReader();try {//获取文档内容Document document = saxReader.read(inputXml);//获取根节点Element root = document.getRootElement();for (Iterator i = root.elementIterator(); i.hasNext();) {Element childList = (Element) i.next();for (Iterator j = childList.elementIterator(); j.hasNext();) {Element node = (Element) j.next();System.out.println(node.getName() + ":" + node.getText());}System.out.println();}} catch (DocumentException e) {System.out.println(e.getMessage());} catch (MalformedURLException e) {e.printStackTrace();}}
}