XML编程CRUD(包括JDK自带的DOM和SAX解析以及DOM4J第三方解析)
CRUD: C:create R:retrieve U:update D:delete XML解析技术概述XML解析方式分为两种:DOM方式和SAX方式
两种解析方式的优缺点: 首先DOM解析XML也是在内存中形成一个树状结构。 把整个XML文档先加载到内存中,形成树状结构。 基于事件驱动的,边读边解析。
JAXPJAXP:(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文件中。
示例如下: 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解析(JAVA中的JAXP有SAX解析)
SAX 是事件驱动的 XML 处理方法
SAX的事件驱动模型
SAX DocumentHandler示例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{ 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 qName,Attributes attributes) throws SAXException { // 如果要是作者标签,flag设置成true if("作者".equals(qName)){ flag = true; count++; } } /** * 能控制characters的输出,我只在解析作者标签的时候,才打印 */ public void characters(char[] ch,int length) throws SAXException { // 如果flag是true,就打印 // 每一次都打印 if(flag && count == 1){ String str = new String(ch,length); System.out.println(str); } } /** * */ public void endElement(String uri,String qName) throws SAXException { // flag恢复成false flag = false; } } /** * 自己事件处理器 * 重写三方法 * @author Administrator * */ class MyHandler extends DefaultHandler{ /** * 只要一解析到开始标签的时候,默认调用该方法,把解析的内容赋值给参数。 */ public void startElement(String uri,Attributes attributes) throws SAXException { System.out.println("开始标签:"+qName); } /** * 只要解析到文本的内容,默认调用该方法 */ public void characters(char[] ch,int length) throws SAXException { String str = new String(ch,length); System.out.println(str); } /** * 解析到结束标签的时候,默认调用方法,把解析的内容赋值给参数。 */ public void endElement(String uri,String qName) throws SAXException { System.out.println("结束标签:"+qName); } </span><h2><span style="font-size:18px;">}</span></h2></span> DOM4J解析XML文档
DOM4J的使用技巧一:查找标签文本
查找节点的文本内容(想要查找内容,需要一层一层的去查找内容,通过根节点去查找子节点,再查找子节点的子节点)查找方法如下:
DOM4J使用技巧二:在指定的节点中添加子节点
format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"),format); writer.write(document); writer.close(); DOM4J使用技巧三:在指定的位置新增节点
DOM4J使用技巧四:修改节点文本和删除节点
(1)修改指定节点的文本内容
(2)删除节点
DOM4J使用技巧五:DOM4J对XPATH的支持提供了一种书写方式,可以很方便的找到XML标签(xpath属于第三方包可以通过xpath文档学习XPATH的语法) (1)DOM4J使用XPATH有两种方法
jaxen-1.1-beta-6.jar 关于XPATH的语法实例如下(常用的有如下三个实例,具体的可以查询文档): 实例1:基本的XPath语法类似于在一个文件系统中定位文件,如果路径以斜线 / 开始,那么该路径就表示到一个元素的绝对路径
实例二:如果路径以双斜线 // 开头,则表示选择文档中所有满足双斜线//之后规则的元素(无论层级关系)
实例三:星号 * 表示选择所有由星号之前的路径所定位的元素
DOM4J使用技巧六:DOM4J获取Document对象
DOM4J中获得Document对象的方式有三种:
(1)读取XML文件,获得document对象
SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));
(2)解析XML形式的文本,得到document对象
String text = "<member></member>"
Document document = DocumentHelper.parseText(text);
(3)主动创建document对象
Document document = DocumentHelper.createDocument();
// 创建根节点
Element root = document.addElement("members");
DOM4J使用技巧七:节点对象
(1)获取文档的根节点:Element root = document.getRootElement();
(2)获取某个节点的子节点 Element element = node.element("书名");
(3)取得节点的文字 String text = node.getText();
(4)取得某节点下所有名为"member"的子节点,并进行遍历
List nodes = rootElm.elements("member");
for(Iterator it=nodes.iterator; it.hasNext();){
Element eLm = (Element)it.next();
// do someing
}
(5)对某节点下的所有子节点进行遍历
for(Iterator it=root.elementIterator();it.hasNext();){
Element element = (Element) it.next();
// do something
}
(6)在某节点下添加子节点Element ageElm = newMemberElm.addElement("age");
(7)设置节点文字 element.setText("XXXYYY");
(8)删除某节点
// childElm 是待删除的节点,parentElm是其父节点
parentElm.remove(childElm)
(9)添加一个CDATA节点
Element contentELm = infoElm.addElement("content");
contentElm.addCDATA(diary.getContent())
DOM4J使用技巧七:节点对象属性(1)取得某节点下的某属性
Element root = document.getRootElement();
// 属性名name
Attribute attribute = root.attribute("size");
(2)取得属性的文字
String text = attribute.getText();
(3)删除某属性
Attribute attribute = root.attribute("size");
root.remove(attribute);
(4)遍历某节点的所有属性
Element root=document.getRootElement();
for(Iterator it=root.attributeIterator();it.hasNext();){
Attribute attribute = (Attribute)it.next();
String text = attribute.getText();
System.out.println(text);
}
(5)设置某节点的属性和文字
newMemberElm.addAttribute("name","sitinspring");
(6)设置属性的文字
Attribute attribute = root.attribute("name");
attribute.setText("sitinspring");
DOM4J使用技巧八:将文档写入XML文件
(1)文档中全为英文,不设置编码,直接写入的形式
XMLWriter wriyer = new XMLWriter(new FileWriter("output.xml"));
writer.write(document);
writer.close();
(2)文档中含有中文,设置编码格式写入的形式
OutputFormat format=OutputFormat.createPrettyPrint();
//指定XML编码
format.setEncoding("GBK");
XMLWriter writer=new XMLWriter(new FileWriter("output.xml"));
writer.write(document);
writer.close();
DOM4J使用技九:在指定位置插入节点
(1)得到插入位置的节点列表(list)
(2)调用list.add(index,element),由index决定element的插入位置。
Element元素可以通过DocumentHelper对象得到。示例代码:
Element aaa=DocumentHelper.createElement("aaa");
aaa.setText("aaa");
List list = root.element("书").elements();
// 更新Document
DOM4J使用技十:字符串与XML转换
(1)将字符串转为XML
String text ="<members> <member>sitinspring</member></members>";
Document document=DocumentHelper.parseText(text);
(2)将文档或节点的XML转为字符串
SAXReader reader=new SAXReader();
Document document=reader.read(new File("input.xml"));
Element root=document.getRootElement();
String docXMLText = document.asXML();
Element memberElm = root.element("member");
String memberXmlText = memberElm.asXML();
Dom4J示例如下:
src/book2.xml
<?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 约束之SchemaXML Schema也是一种用于定义和描述XML文档结构与内容的模式语言,其出现是为了克服DTD的局限性。
XML Schema VS DTD:
(1)XML Schema语法符合XML语法结构。
(2)DOM、SAX等XML API很容易解析出XML Schema文档中的内容。
(3)XML Schema 对名称空间支持的非常好。
(4)XML Schema比XML DTD支持更多的数据类型,并支持用户自定义新的数据类型。
(5)XML Schema定义约束的能力非常强大,可以对XML实例文档作出细致的语义限制。
(6)XML Schema不能像DTD一样定义实体,比DTD更复杂,但XML Schema现在已经是W3C组织的标准,它在逐步替代DTD。
(7)XML Schema使用一套预先的XML元素和属性创建的,这些元素和属性定义了XML文档的结构和内容模式。XML Schema规定XML文档实例的结构和每个元素/属性的数据类型。
(8)Schema相对于DTD的明显好处是,XML Schema文档本身也是XML文档,而不是像DTD一样使用自成一体的语法。
Schema与DTD的区别:
XML从SGML中继承了DTD,并用它来定义内容的模型,验证和组织元素。同时它也有很多局限:
(1)DTD不可扩展。
(2)DTD不遵循XML语法。
(3)DTD不支持命名空间的应用。
(4)DTD没有提供强大的数据类型支持,只能表示很简单的数据类型。
Schema完全克服了这些弱点,使得基于web的应用系统交换XML数据更为容易。下面是它所展现的一些新特性:
(1)Schema完全基于XML语法,不需要再学习特殊的语法。
(2)Schema能用处理XML文档的工具处理,而不需要特殊的工具。
(3)Schema大大扩充了数据类型,支持booleans、numbers、dates and times、URIs、integers、decimal numbers 和real numbers等。
(4)Schema支持原型,也就是元素的继承。如:我们定义了一个"联系人" 数据类型,然后可以根据它产生“朋友联系人”和“客户联系人”两种数据类型。
(5)Schema支持属性组。我们一般声明一些公共属性,然后可以然后可以应用于所有元素,属性组允许把元素、属性关系放在外部定义、组合。
(6)开放性。原来的DTD只能有一个DTD应用于一个XML文档,现在可以有多个Schema运用于一个XML文档。
Schema的一些概念:
(1)XML Schema文件自身就是一个XML文件,但它的扩展名通常为.xsd
(2)和XML文件一样,一个XML Schema文档也必须有一个根节点,但是这个根结点的名称为schema
(3)应用schema约束开发XML过程
W3C预先定义元素和属性——>Schema文档(模式文档:约束文档)——>XML文档(实例文档)
(4)编写了一个XML Schema约束文档后,通常需要把这个文件中声明的元素绑定到一个URI地址上,把这个URI地址叫namespace名称空间,以后XML文件就可以通过这个URL(即名称空间)引用绑定指定名称空间的元素。
XMLSchema文档的基本结构:
(1)在W3CXML schema规范中规定:所有的Schema文档都使用<schema>作为根元素
<?xml version="1.0">
<xsd:schema>
......
</xsd:schema>
(2)<schema>元素可以包含一些属性。一个XML Schema声明看起来经常以如下的形式出现:
schema入门案例:book.xsd
<?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文档中声明名称空间。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www. itcast.cn" elementFormDefault="qualified" attributeFormDefault="qualified" > <xs:schema>
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |