CRUD:
C:create R:retrieve U:update D:delete
XML解析方式分为两种:DOM方式和SAX方式
两种解析方式的优缺点:
首先DOM解析XML也是在内存中形成一个树状结构。
DOM解析:
把整个XML文档先加载到内存中,形成树状结构。
缺点:如果文档非常大,加载到内存中容易产生内存溢出的问题。
优点:因为节点与节点之间有关系,进行增删改非常方便。
SAX解析:
基于事件驱动的,边读边解析。
缺点:不能进行增删改的操作。
优点:文档大也不会有内存溢出的问题,
JAXP:(JAVA API for XML Processing)开发包是JavaSE的一部分,它由以下几个包及其子包组成:
获得JAXP中的DOM解析器
DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)
在DOM中,节点之间的关系如下:
具体步骤如下:
<span style="font-size:18px;"><span style="font-size:18px;">public static void getNodeName(Node node){ if(node.getNodeType() == Node.ELEMENT_NODE){ System.out.println(node.getNodeName()); } NodeList nodeList = node.getChildNodes(); for(int i=0;i<nodeList.getLength();i++){ Node child = nodeList.item(i); getNodeName(child); } } </span></span>JAXP的DOM方式更新XML文档
javax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换成某种格式后进行输出,例如把XML文件应用样式表后转成一个HTML文档。利用这个对象,当然也可以把Document对象又重新写入到一个XML文件中。
Transformer类通过transform方法完成转换操作,该方法接收一个源和一个目的地。我们可以通过:
示例如下:
book2.xml
<span style="font-size:18px;"><span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8" standalone="no"?><书架> <书 编号="b2"> <书名>javaweb开发大全</书名> <作者>班长</作者> <售价>99.8元</售价> <简介>这是不错啊</简介> </书> <书> <书名>葵花宝典</书名> <作者>岳不群</作者> <售价>99.8两</售价> <简介>欲练此功...</简介> <猫>我是猫</猫></书> </书架></span></span>
JaxpDomTest.java
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast.jaxp; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import cn.itcast.utils.JaxpDomUtil; /** * JAXP的DOM解析XML * @author Administrator * */ public class JaxpDomTest { public static void main(String[] args) { try { run2(); } catch (Exception e) { e.printStackTrace(); } } /** * 获取作者的文本内容 * @throws Exception */ public static void run1() throws Exception{ // 获取解析器工厂类 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 获取解析器对象 DocumentBuilder builder = factory.newDocumentBuilder(); // 解析XML的文档,返回document对象 Document document = builder.parse("src/book2.xml"); // 获取作者元素对象的集合,返回NodeList NodeList nodeList = document.getElementsByTagName("作者"); // 循环遍历,拿到每一个作者,打印文本的内容,getTextContent() for(int i=0;i<nodeList.getLength();i++){ Node node = nodeList.item(i); System.out.println(node.getTextContent()); } } /** * 需求:在第二本下,在末尾添加子节点 * @throws Exception */ public static void run2() throws Exception{ // 获取工厂类 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 获取解析器 DocumentBuilder builder = factory.newDocumentBuilder(); // 解析xml,返回document对象 Document document = builder.parse("src/book2.xml"); // 获取第二本书 Node book2 = document.getElementsByTagName("书").item(1); // 创建元素对象 Element cat = document.createElement("猫"); // 设置文本内容 cat.setTextContent("我是猫"); // 把元素对象添加到第二本书下 book2.appendChild(cat); // 回写 // 创建回写类的工厂 TransformerFactory transformerFactory = TransformerFactory.newInstance(); // 获取回写类 Transformer transformer = transformerFactory.newTransformer(); // 调用回写的方法 transformer.transform(new DOMSource(document), new StreamResult("src/book2.xml")); } /** * 删除节点 * @throws Exception */ public static void run3() throws Exception{ String path = "src/book2.xml"; // 获取文档对象 Document document = JaxpDomUtil.getDocument(path); // 获取猫 Node cat = document.getElementsByTagName("猫").item(0); // 获取书(猫的父节点) Node book2 = cat.getParentNode(); // 通过书删除猫 book2.removeChild(cat); // 回写 JaxpDomUtil.writeXML(document, path); } }</span></span>封装回写和获取Document的工具类:JAXPDOMUtil.java
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast.utils; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; /** * JAPTDOM解析的工具类 * @author Administrator * */ public class JaxpDomUtil { /** * 通过path获取document对象 * @param path * @return * @throws Exception */ public static Document getDocument(String path) throws Exception{ // 获取工厂类 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 获取解析器对象 DocumentBuilder builder = factory.newDocumentBuilder(); // 解析xml return builder.parse(path); } /** * 回写方法 * @param document * @param path * @throws Exception */ public static void writeXML(Document document,String path) throws Exception{ // 获取回写类的工厂 TransformerFactory factory = TransformerFactory.newInstance(); // 获取回写类 Transformer transformer = factory.newTransformer(); // 回写 transformer.transform(new DOMSource(document), new StreamResult(path)); } } </span></span>
SAX 是事件驱动的 XML 处理方法
SAX 解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件
发生相应事件时,将调用一个回调方法
(1)使用SAXParserFactory创建SAX解析工厂
SAXParserFactory spf = SAXParserFactory.newInstance();
(2)通过SAX解析工厂得到解析器对象
SAXParser sp = spf.newSAXParser();
(3)通过解析器对象解析XML文件
xmlReader.parse("book.xml", new XMLContentHandler());
注意这里的XMLContentHandler继承DefaultHandler
SAX举例说明
public class XMLContentHandler extends DefaultHandler{
//当前元素中的数据
private String currentData;
//取得元素数据
public void characters(char[] ch, int start, int length)
throws SAXException {
currentData=new String(ch,start,length);
}
//在解析整个文档结束时调用
public void endDocument() throws SAXException {
System.out.println("结束文档");
}
//在解析元素结束时调用
public void endElement(String uri, String localName, String name)
throws SAXException {
System.out.println("节点数据 *************************"+this.currentData);
System.out.println("结束元素 ************"+name);
}
//在解析整个文档开始时调用
public void startDocument() throws SAXException {
System.out.println("开始文档");
}
//在解析元素开始时调用
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
System.out.println("开始元素 ************"+name);
}
}
JAXP的SAX解析XML文档示例如下:
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast.jaxp.sax; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * SAX的入门 * @author Administrator * */ public class JaxpSaxTest { public static void main(String[] args) { try { run1(); } catch (Exception e) { e.printStackTrace(); } } /** * 获取所有的解析的内容 * @throws Exception * @throws ParserConfigurationException */ public static void run1() throws Exception{ // 获取SAX的解析器工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); // 获取解析器 SAXParser parser = factory.newSAXParser(); // 解析 parser.parse("src/book2.xml", new MyHandler2()); } } /** * 获取作者标签的文本内容 * */ class MyHandler2 extends DefaultHandler{ // 如果解析到作者标签的时候,flag设置成true private boolean flag = false; private int count = 0; /** * 默认解析开始标签,默认调用该方法 */ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 如果要是作者标签,flag设置成true if("作者".equals(qName)){ flag = true; count++; } } /** * 能控制characters的输出,我只在解析作者标签的时候,才打印 */ public void characters(char[] ch, int start, int length) throws SAXException { // 如果flag是true,就打印 // 每一次都打印 if(flag && count == 1){ String str = new String(ch,start,length); System.out.println(str); } } /** * */ public void endElement(String uri, String localName, String qName) throws SAXException { // flag恢复成false flag = false; } } /** * 自己事件处理器 * 重写三方法 * @author Administrator * */ class MyHandler extends DefaultHandler{ /** * 只要一解析到开始标签的时候,默认调用该方法,把解析的内容赋值给参数。 */ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.println("开始标签:"+qName); } /** * 只要解析到文本的内容,默认调用该方法 */ public void characters(char[] ch, int start, int length) throws SAXException { String str = new String(ch,start,length); System.out.println(str); } /** * 解析到结束标签的时候,默认调用方法,把解析的内容赋值给参数。 */ public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println("结束标签:"+qName); } </span><h2><span style="font-size:18px;">}</span></h2></span>
提供了一种书写方式,可以很方便的找到XML标签(xpath属于第三方包可以通过xpath文档学习XPATH的语法)
(1)DOM4J使用XPATH有两种方法
jaxen-1.1-beta-6.jar
关于XPATH的语法实例如下(常用的有如下三个实例,具体的可以查询文档):
实例1:基本的XPath语法类似于在一个文件系统中定位文件,如果路径以斜线 / 开始, 那么该路径就表示到一个元素的绝对路径
实例二:如果路径以双斜线 // 开头, 则表示选择文档中所有满足双斜线//之后规则的元素(无论层级关系)
实例三:星号 * 表示选择所有由星号之前的路径所定位的元素
<?xml version="1.0" encoding="UTF-8"?> <书架> <书> <书名>javaweb开发大全</书名> <作者>班长</作者> <售价>99.8元</售价> <简介>这是不错啊</简介> </书> <书> <书名>葵花宝典</书名> <狗>小狗</狗> <作者>岳不群</作者> <售价>99.8两</售价> <简介>欲练此功...</简介> </书> </书架>
package cn.itcast.dom4j; import java.io.FileOutputStream; import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; /** * DOM4J的解析XML * @author Administrator * */ public class Dom4jTest { public static void main(String[] args) { try { run1(); } catch (Exception e) { e.printStackTrace(); } } /** * 对XPATH的支持 * @throws Exception */ public static void run6() throws Exception{ // 获取解析器对象 SAXReader reader = new SAXReader(); // 解析XML Document document = reader.read("src/book2.xml"); // List<Node> list = document.selectNodes("/书架/书/作者"); List<Node> list = document.selectNodes("//作者"); Node author2 = list.get(1); System.out.println(author2.getText()); } /** * 修改文本内容 * @throws Exception */ public static void run5() throws Exception{ // 获取解析器对象 SAXReader reader = new SAXReader(); // 解析XML Document document = reader.read("src/book2.xml"); // 获取根节点 Element root = document.getRootElement(); // 获取狗的节点 Element book2 = (Element) root.elements("书").get(1); Element dog = book2.element("狗"); dog.setText("小狗"); // 回写 // 回写 OutputFormat format = OutputFormat.createPrettyPrint(); // 回写 XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"),format); writer.write(document); writer.close(); } /** * 删除子节点 * 删除第二本书下的猫节点 */ public static void run4() throws Exception{ // 获取解析器对象 SAXReader reader = new SAXReader(); // 解析XML Document document = reader.read("src/book2.xml"); // 获取根节点 Element root = document.getRootElement(); // 获取猫 Element book2 = (Element) root.elements("书").get(1); Element cat = book2.element("猫"); // 通过猫获取猫的父节点 // cat.getParent(); // 通过父节点删除猫 book2.remove(cat); // 回写 OutputFormat format = OutputFormat.createPrettyPrint(); // 回写 XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"),format); writer.write(document); writer.close(); } /** * 在第二本书的作者标签之前添加团购价的标签 * @throws Exception */ public static void run3() throws Exception{ // List // 获取解析器对象 SAXReader reader = new SAXReader(); // 解析XML Document document = reader.read("src/book2.xml"); // 获取根节点 Element root = document.getRootElement(); // 获取第二本书 Element book2 = (Element) root.elements("书").get(1); // 获取书下的所有子节点,返回List集合 List<Element> list = book2.elements(); // 创建元素对象 DocumentHelper.createElement("狗") Element dog = DocumentHelper.createElement("狗"); dog.setText("大狗"); // list.add(index,Element); list.add(1, dog); OutputFormat format = OutputFormat.createPrettyPrint(); // 回写 XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"),format); writer.write(document); writer.close(); } /** * 在第二本书下添加子节点 */ public static void run2() throws Exception{ // 获取解析器对象 SAXReader reader = new SAXReader(); // 解析XML,返回Document对象 Document document = reader.read("src/book2.xml"); // 获取根节点 Element root = document.getRootElement(); // 获取第二本书 Element book2 = (Element) root.elements("书").get(1); // 可以直接在第二本书下添加子节点,设置文本内容 book2.addElement("猫").setText("我是猫"); // 回写 // 创建漂亮的格式 OutputFormat format = OutputFormat.createPrettyPrint(); //OutputFormat format = OutputFormat.createCompactFormat(); // 设置编码 format.setEncoding("UTF-8"); // 回写类 XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"),format); // 回写了文档对象 writer.write(document); // 关闭流 writer.close(); } /** * 获取第二本书作者的文本内容 * @throws Exception */ public static void run1() throws Exception{ // 获取解析器对象 SAXReader reader = new SAXReader(); // 解析XML,返回Document对象 Document document = reader.read("src/book2.xml"); // 获取根节点(书架标签) Element root = document.getRootElement(); // 获取书的节点,获取第二本书 List<Element> books = root.elements("书"); Element book2 = books.get(1); // 获取作者的标签 Element author2 = book2.element("作者"); // 获取文本内容 System.out.println(author2.getText()); } }
<?xml version="1.0" encoding="UTF-8" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www. itcast.cn" elementFormDefault="qualified"> <xs:element name='书架' > <xs:complexType> <xs:sequence maxOccurs='unbounded' > <xs:element name='书' > <xs:complexType> <xs:sequence> <xs:element name='书名' type='xs:string' /> <xs:element name='作者' type='xs:string' /> <xs:element name='售价' type='xs:string' /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
<?xml version="1.0" encoding="UTF-8"?> <itcast:书架 xmlns:itcast="http://www.itcast.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=“http://www.itcast.cn book.xsd"> <itcast:书> <itcast:书名>九阴真经</itcast:书名> <itcast:作者>郭靖</itcast:作者> <itcast:售价>28.00元</itcast:售价> </itcast:书> </itcast:书架>在XML Schema文档中声明名称空间。