1、目标
理解XML该你那及优势
回避那些格式良好的XML文档
了解XML中特殊字符的处理方式
了解解析器概念
了解DOM树节点构造
会使用Dom操作XML数据(添加/保存)
2、XML简介
XML(EXtensible Markup Language),可扩展标记语言,是一种简单的基于文本的语言,旨在以村文本格式存储和传输数据,他代表可扩展标记语言。
- XML 是一种标记语言。
- XML 是一种类似于 HTML 的基于标签的语言。
- XML 标记不像 HTML 那样预定义。
- 您可以定义自己的标签,这就是它被称为可扩展语言的原因。
- XML 标签被设计成自我描述的。
- XML 是用于数据存储和数据传输的 W3C 推荐标准。
特点
XML与操作系统、编程语言的开发平台无关
实现不同系统之间的数据交换
- 与技术无关 − 作为纯文本,XML 与技术无关。 它可以被任何技术用于数据存储和数据传输目的。
- 人类可读 − XML 使用简单的文本格式。 它是人类可读且易于理解的。
- 可扩展 − 在 XML 中,可以非常轻松地创建和使用自定义标签。
- 允许验证 − 使用 XSD、DTD 和 XML 结构可以很容易地进行验证。
作用
数据交互
配置应用程序和网站
Ajax基石
缺点
- 冗余语法 − 通常 XML 文件包含很多重复的术语。
- 冗长 − 作为一种冗长的语言,XML 文件的大小增加了传输和存储成本。
XML文档结构
<?xml version="1.0" encoding="UTF-8"?>
<books><!--图书信息 --><book id="bk101"><author>王珊</author><title>.NET高级编程</title><description>包含C#框架和网络编程等</description></book><book id="bk102"><author>李明明</author><title>XML基础编程</title><description>包含XML基础概念和基本作用</description></book>
</books>
XML标签
XML文档内容由一系列标签元素组成
<元素名 属性名="属性值">元素内容</元素名>
//空元素
<name> </name>
<name></name>
</name>
属性值用双引号包裹
一个元素可以有多个属性
属性值不能直接包含 <、"、&
不建议使用的字符 ‘、>
XML编写注意事项
所有XML元素都必须有结束标签
XML标签对大小写敏感
XML必须正确的嵌套
同级标签以缩进对齐
元素名称可以包含字母、数字、或其他的字符
元素名称不能以数字或者标点符号开始
元素名称不能包含空格
指出先民啊XML代码的错误
<title><name>XML编程</title></name> //标签嵌套错误
XML语法
XML语法由三大部分组成
文档头部声明
<?xml version="1.0" encoding="UTF-8"?>
文档类型声明(非必须)
对文件类型进行说明的语句,在一些其他技术使用xml文件进行操作时会使用到。例如MyBatis的xml映射以及http文件等。
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
文档体
使用 <label-name>message</lable-name>
方式构成的标签语句。
abel-name: 标签名称
message: 标签内容,标签内容可以使其他标签,也可以是单纯的文本字符串。
属性命名空间
<?xml version="1.0" encoding="UTF-8"?>
<batchCompany xmlns="http://www.Aptech_edu.ac"xmlns:tea="http://www.tea.org"><batch-list><batch type="thirdbatch">第三批次</batch><batch tea:type="thirdbatch">第三批茶</batch><batch>午班批次</batch></batch-list>
</batchCompany>
除非带有前缀,否则属性属于所属的元素的命名空间
XML解析器
解析器类型
非验证解析器
检查文档格式是否良好
验证解析器
使用DTD检查文档的有效性
XML命名空间
XML命名空间的作用
解决在复杂、大型XML文件中,出现名称相同,但是含义不同的元素
<?xml version="1.0" encoding="UTF-8"?>
<cameras xmlns:canon="http://www.canon"xmlns:nikon="http://www.nikon.com"><canon:camera prodID="P663" name="Camera傻瓜相机"/><nikon:camera prodID=“K29B3” name=“Camera超级35毫米相机"/>
</cameras>
解析XML技术
有四种:
内置:DOM(一般针对于小文件) 、SAX(大文件,以流式来进行处理)
内置的两种方式并不太行
扩展:JDOM(自己维护,缺乏团队,慢慢没落)、Dom4J()
DOM
基于XML文档树结构的解析
适用于多次访问的XML文档
特点:比较消耗资源
SAX
基于事件的解析
适用于大数据量的XML文档
特点:占用资源少,内存消耗小
DOM4J
非常优秀的Java XML API
性能优异、功能强大
开放源代码
Dom解析XMl
Dom介绍
文档对象模型(Document Object Model)
Dom吧XMl文档映射成一个倒挂的树
常用接口介绍
DOM解析包:org.w3c.dom
常用接口 | 常用方法 | 说明 |
Document:表示整个 XML 文档 | NodeList getElementsByTagName(String Tag) | 按文档顺序返回文档中指定标记名称的所有元素集合 |
Element createElement(String tagName) | 创建指定标记名称的元素 | |
Node:该文档树中的单个节点 | NodeList getChildNodes() | 获取该元素的所有子节点,返回节点集合 |
Element:XML 文档中的一个元素 | String getTagName() | 获取元素名称 |
访问DOM树节点
显示“收藏信息.XML”文件中收藏的手机品牌和型号
<?xml version="1.0" encoding="GB2312"?>
<PhoneInfo><Brand name="华为"><Type name="U8650"/><Type name="HW123"/><Type name="HW321"/></Brand><Brand name="苹果"><Type name="iPhone4"/></Brand>
</PhoneInfo>
DOM解析XML文件步骤1.创建解析器工厂对象2.解析器工厂对象创建解析器对象3.解析器对象指定XML文件创建Document对象4.以Document对象为起点操作DOM树
package Test;import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import sun.security.tools.keytool.Main;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.Node;
import javax.xml.soap.SAAJMetaFactory;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;/*** @Author: Insight* @Description: Dom解析XMl* @Date: 2024/9/11 15:50* @Version: 1.0*/public class Test {public static void main(String[] args) {try {//创建解析工厂对象DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();//解析器工厂对象创建解析器对象DocumentBuilder db = dbf.newDocumentBuilder();//解析器对象指定XML文件创建Document对象Document d = db.parse("./src/Test/cloth.xml");d.getDocumentElement().normalize();//以Document对象为起点操作Dom树//获取根节点Element element = d.getDocumentElement();//通过根节点获取子节点NodeList nodeList = element.getElementsByTagName("size");for (int i = 0;i<nodeList.getLength();i++){//获取子节点下的数据System.out.println(nodeList.item(i).getTextContent());}} catch (Exception e) {e.printStackTrace();}}
}
保存XML文件
package Test02;import org.w3c.dom.Document;
import org.w3c.dom.Element;import javax.print.Doc;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;/*** @Author: Insight* @Description: TODO* @Date: 2024/9/11 18:52* @Version: 1.0*/public class Test {public static void main(String[] args) {try {//创建工厂TransformerFactoryTransformerFactory tf = TransformerFactory.newInstance();//创建Transformer对象Transformer t = tf.newTransformer();//创建DOMSource对象,需要创建Document对象来创建新的XML文件DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();Document d = db.newDocument();//创建XML结构//创建根节点Element rootElement = d.createElement("root");//加入树中d.appendChild(rootElement);//创建子节点Element childElement = d.createElement("child");//设置属性名和属性值childElement.setAttribute("attr","value");//设置子节点文本内容childElement.appendChild(d.createTextNode("Text Content"));//加入根节点树中rootElement.appendChild(childElement);//将文件添加入DOMsource中DOMSource dom = new DOMSource(d);//设置输出属性//设置是否再XML中添加缩进t.setOutputProperty(OutputKeys.INDENT,"yes");//指定输出方法t.setOutputProperty(OutputKeys.METHOD, "xml");//编码格式t.setOutputProperty(OutputKeys.ENCODING,"UTF-8");//创建StreamResult对象StreamResult result = new StreamResult(new File("./src/Test02/output.xml"));// 7. 包含保存文件的信息// (StreamResult对象已经包含了文件信息)// 8. 将XML保存到指定文件中t.transform(dom,result);System.out.println("已保存文件");} catch (Exception e) {e.printStackTrace();}}
}
修改/删除DOM节点
给所有的Brand标签添加id属性
获取Brand标签
调用setAttribute()方法添加属性
删除Brand值为“华为”的标签
getElementsByTagName()方法获取Brand标签列表
获得Brand值为“华为”的标签对象
通过getParentNode()方法获得父节点对象
调用父节点的removeChild()方法删除节点
dom4j解析XML
1. 读取xml文件 SAXReader()
//将xml文件加载到内存中 XML解析器
SAXReader saxReader = new SAXReader();
//document 加载执行xml文档获取Document对象
Document document = saxReader.read(XML路径);
2. 获取XML根节点getRootElement()
Element rootElement = document.getRootElement();
3. 获取当前节点下所有子节点elements()
//获取根节点下所有子节点
List<Element> Elist = rootElement.elements();
4. 根据指定子元素名,获取元素下所有子节点
//获取节点名称为books下所有子节点
List<Element> Elist = rootElement.elements(“books”);
5. 根据指定子元素名,获取子元素对象,如果重复,则获取第一个
//获取节点名称为books下单个子节点
Element element= rootElement.element(“books”);
6. 设置元素文本内容setText()
newelement.setText("内容");
7. 获取当前节点文本内容getText()
elenent.getText()
8. 根据指定子元素名,获取元素中的文本
e.elementText(“book”)
9. 获取当前节点属性attributeValue(“属性名”)
e.attributeValue("name")
11.创建节点Element对象.addElement("节点名")
Element newelement = rootElement.addElement("span");
12.节点添加,修改属性Element对象.addAttribute("节点属性名",“属性值”)
newelement.addAttribute("type","属性值");
13.新XML添加Documen对象
通过DocumentHelper.creatDocument()创建一个Document对象
Document read = DocumentHelper.createDocument();
14.设置XML编码
通过OutputFormat的静态方法createPrettyPrint()创建OutputFormat对象,并设置编码集
OutputFormat outputFormat=OutputFormat.createPrettyPrint();
outputFormat.setEncoding("UTF-8");
15.写入XML文件
//写入XML文件的位置 以及指定的格式
XMLWriter xmlWriter=new XMLWriter(new FileWriter("cs.xml"),outputFormat);
//开始写入XML文件 写入Document对象
xmlWriter.write(document);
xmlWriter.close();
练习
练习一
需求说明将表中的数据用XML文档表示出来
学生姓名 | 预计得分 | 实际得分 |
王显明 | 75 | 80 |
宋佳 | 75 | 88 |
<?xml version="1.0" encoding="UTF-8" ?>
<students><student><name>王显明</name><prescore>75</prescore><actscore>80</actscore></student><student><name>宋佳</name><prescore>75</prescore><actscore>88</actscore></student>
</students>
练习二
显示“收藏信息.xml”文件中收藏的手机品牌和型号
<?xml version="1.0" encoding="GB2312"?>
<PhoneInfo><Brand name="华为"><Type name="U8650"/><Type name="HW123"/><Type name="HW321"/></Brand><Brand name="苹果"><Type name="iPhone4"/></Brand>
</PhoneInfo>
Test
package exercise01;import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.util.List;/*** @Author: Insight* @Description: 使用DOM操作XML* @Date: 2024/9/11 17:59* @Version: 1.0*/public class Test {public static void main(String[] args) {try {//创建工厂对象DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();//工厂对象创建解析器对象DocumentBuilder db = dbf.newDocumentBuilder();//创建Document读取XMLDocument d = db.parse("./src/exercise01/收藏信息.xml");//获取根节点Element element = d.getDocumentElement();// //检查根节点
// System.out.println(element);//根据根节点获取子节点NodeList nodeList = element.getElementsByTagName("Brand");//根据子节点再获取子节点,并输出信息for (int i = 0;i < nodeList.getLength();i++){Element el1 = (Element) nodeList.item(i);System.out.println("品牌:" + el1.getAttribute("name"));for (int j = 0;j < el1.getElementsByTagName("Type").getLength();j++){Element el2 = (Element) el1.getElementsByTagName("Type").item(j);System.out.println("型号:" + el2.getAttribute("name"));}}} catch (Exception e) {e.printStackTrace();}}
}
练习三
需求说明 添加新的Brand:三星给Brand节点添加新的子标签Type:Note4将Brand添加到DOM树中
package exercise03;import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.util.List;/*** @Author: Insight* @Description: 将手机收藏信息保存到文件中* @Date: 2024/9/11 19:12* @Version: 1.0*/public class Test {public static void main(String[] args) {//读取旧的文件try {DocumentBuilderFactory factory1 = DocumentBuilderFactory.newInstance();DocumentBuilder builder1 = factory1.newDocumentBuilder();//读取文件Document document1 = builder1.parse("./src/exercise03/收藏信息.XML");//文件写入TransformerFactory factory2 = TransformerFactory.newInstance();Transformer transformer = factory2.newTransformer();//获取根节点信息Element rootElement1 = document1.getDocumentElement();System.out.println(rootElement1);NodeList brands = document1.getElementsByTagName("Brand");for (int i = 0;i < brands.getLength();i++){Element brand = (Element) brands.item(i);System.out.println(brand.getAttribute("name"));NodeList types = brand.getElementsByTagName("Type");for (int j = 0;j < types.getLength(); j++){Element type = (Element) types.item(j);System.out.println(type.getAttribute("name"));}}//文件写入Document document2 = builder1.newDocument();//创建根节点Element rootElement2 = document2.createElement("PhoneInfo");document2.appendChild(rootElement2);//创建手机品牌节点for (int i = 0;i < brands.getLength(); i++ ){Element childElement = document2.createElement("brand");Element brand = (Element) brands.item(i);childElement.setAttribute("name",brand.getAttribute("name"));rootElement2.appendChild(childElement);NodeList types = brand.getElementsByTagName("Type");for (int j = 0; j < types.getLength();j++){Element childElement1 = document2.createElement("Type");Element type = (Element) types.item(j);childElement1.setAttribute("name",type.getAttribute("name"));childElement.appendChild(childElement1);}}DOMSource dom = new DOMSource(document2);transformer.setOutputProperty(OutputKeys.INDENT,"yes");transformer.setOutputProperty(OutputKeys.METHOD,"xml");transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");StreamResult result = new StreamResult(new File("./src/exercise03/output.xml"));transformer.transform(dom,result);} catch (Exception e) {e.printStackTrace();}}
}
练习四
需求说明 添加新的Brand:三星给Brand节点添加新的子标签Type:Note4将Brand添加到DOM树中
package exercise04;import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.IOException;/*** @Author: Insight* @Description: TODO* @Date: 2024/9/11 19:51* @Version: 1.0*/public class Test {public static void main(String[] args) {try {DocumentBuilderFactory factory1 = DocumentBuilderFactory.newInstance();DocumentBuilder builder1 = factory1.newDocumentBuilder();//读取文件Document document1 = builder1.parse("./src/exercise03/收藏信息.XML");//文件写入TransformerFactory factory2 = TransformerFactory.newInstance();Transformer t = factory2.newTransformer();//创建XML结构//创建根节点Element rootElement = document1.createElement("Brand");rootElement.setAttribute("name","三星");//加入树中document1.getDocumentElement().appendChild(rootElement);//创建子节点Element childElement = document1.createElement("Type");//设置属性名和属性值childElement.setAttribute("name","Note4");//加入根节点树中rootElement.appendChild(childElement);//将文件添加入DOMsource中DOMSource dom = new DOMSource(document1);//设置输出属性//设置是否再XML中添加缩进t.setOutputProperty(OutputKeys.INDENT,"yes");//指定输出方法t.setOutputProperty(OutputKeys.METHOD, "xml");//编码格式t.setOutputProperty(OutputKeys.ENCODING,"UTF-8");//创建StreamResult对象StreamResult result = new StreamResult(new File("./src/exercise04/收藏信息.xml"));// 7. 包含保存文件的信息// (StreamResult对象已经包含了文件信息)// 8. 将XML保存到指定文件中t.transform(dom,result);System.out.println("已保存文件");} catch (Exception e) {e.printStackTrace();}}
}
练习五 使用DOM4J
显示手机收藏信息保存手机收藏信息为手机收藏信息添加新的节点修改/删除手机收藏信息节点
Test
package exercise05;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.SAXWriter;
import org.dom4j.io.XMLWriter;import java.io.FileWriter;
import java.io.IOException;
import java.util.List;/*** @Author: Insight* @Description: TODO* @Date: 2024/9/12 12:02* @Version: 1.0*/public class Test {public static void main(String[] args) {//document 假爱执行XML文档 获取Document对象try {//创建管理对象Manager manager = new Manager();//读取信息manager.Info();//添加新节点//添加手机品牌节点manager.addPhoneBrand("三星");//添加手机型号节点manager.addPhoneType("三星","utla");//修改信息//修改品牌信息manager.updateBrandName("三星","小米");//修改型号信息manager.updateTypeName("小米","utla","15promax");//保存到新的文件中manager.deletebrand("小米");//删除品牌下的某一型号manager.deleteType("华为","U8650");manager.saveXML("./src/exercise05/output.xml");} catch (Exception e) {e.printStackTrace();}}
}
Manager
package exercise05;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;import java.io.FileWriter;
import java.io.IOException;
import java.util.List;/*** @Author: Insight* @Description: TODO* @Date: 2024/9/12 14:03* @Version: 1.0*/public class Manager {public Document document;public Manager() throws DocumentException {SAXReader reader = new SAXReader();this.document = reader.read("./src/exercise05/收藏信息.xml");}//显示手机收藏信息public void Info(){//获取XML根节点Element rootElement = document.getRootElement();//获取当前节点下的所有子节点List<Element> eList = rootElement.elements();//遍历获取子节点下的子节点 (显示手机收藏信息)for (Element el1 : eList){List<Element> eeList = el1.elements();System.out.println("品牌" + el1.attributeValue("name"));for (Element el2 : eeList){//显示标签属性值System.out.println(" 型号:" + el2.attributeValue("name"));}}}//保存信息到新的文件中public void saveXML(String filepath) throws IOException {OutputFormat output = OutputFormat.createPrettyPrint();XMLWriter xmlWriter = new XMLWriter(new FileWriter(filepath),output);xmlWriter.write(document);System.out.println("保存成功!!!");xmlWriter.close();}//添加新节点//添加品牌系欸但public void addPhoneBrand(String brandname){//获取根节点Element root = document.getRootElement();//添加品牌节点Element brand = root.addElement("Brand");brand.addAttribute("name",brandname);System.out.println("成功添加 品牌:" + brandname);}//添加型号节点public void addPhoneType(String brandname,String typename){Element root = document.getRootElement();List<Element> list = root.elements();for (int i = 0;i< list.size();i++){Element brand = list.get(i);if (brand.attributeValue("name").equals(brandname)){//根据品牌名进行添加Element type = brand.addElement("Type");type.addAttribute("name",typename);System.out.println("成功添加 品牌:" + brandname + " 型号:" + typename);}}}//修改信息//修改品牌信息public void updateBrandName(String oldbrnd,String newbrand){//获取根节点Element root = document.getRootElement();//获取所有品牌信息List<Element> list = root.elements();//遍历找到要修改的品牌for (Element el : list){if (el.attributeValue("name").equals(oldbrnd)){el.addAttribute("name",newbrand);System.out.println("成功修改 品牌:" + oldbrnd + "为 品牌:" + newbrand);}}}//修改型号信息public void updateTypeName(String selectbrand,String oldtype,String newtype){Element root = document.getRootElement();List<Element> list = root.elements();for (int i = 0;i< list.size();i++){Element brand = list.get(i);if (brand.attributeValue("name").equals(selectbrand)){//根据型号名进行查找List<Element> type = brand.elements();for (Element el : type){if (el.attributeValue("name").equals(oldtype)){el.addAttribute("name",newtype);System.out.println("成功修改 型号:" + oldtype + "为 型号:" + newtype);}}}}}//删除品牌public void deletebrand(String brand){//获取根节点Element root = document.getRootElement();//获取所有品牌信息List<Element> list = root.elements();//遍历找到要修改的品牌for (Element el : list){if (el.attributeValue("name").equals(brand)){root.remove(el);System.out.println("成功删除 品牌:" + brand);}}System.out.println("型号修改结束");}//删除品牌下的某个型号public void deleteType(String brandname,String typename){Element root = document.getRootElement();List<Element> list = root.elements();for (int i = 0;i< list.size();i++){Element brand = list.get(i);if (brand.attributeValue("name").equals(brandname)){//根据型号名进行查找List<Element> type = brand.elements();for (Element el : type){if (el.attributeValue("name").equals(typename)){brand.remove(el);System.out.println("成功删除 品牌:" + brandname + " 型号:" + typename);}}}}}
}