1 XML简介
XML(可扩展标记语言,Extensible Markup Language)是一种用于定义文档结构和数据存储的标记语言。它主要用于在不同的系统之间传输和存储数据。
作用:
- 数据交互配
- 置应用程序和网站
- Ajax基石
特点
- XML与操作系统、编程语言的开发平台无关
- 实现不同系统之间的数据交换
2 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>
2.1 XML标签
<元素名 属性名=“属性值”>元素内容</元素名>
- 属性值用双引号包裹
- 一个元素可以有多个属性
- 属性值中不能直接包含<、“、&
- 不建议使用的字符:‘、>
2.2 注意事项
- 所有XML元素都必须有结束标签
- XML标签对大小写敏感
- XML必须正确的嵌套
- 同级标签以缩进对齐
- 元素名称可以包含字母、数字或其他的字符
- 元素名称不能以数字或者标点符号开始
- 元素名称中不能含空格
3 解析XML技术
DOM:
- 基于XML文档树结构的解析
- 适用于多次访问的XML文档
- 特点:比较消耗资源
SAX:
- 基于事件的解析
- 适用于大数据量的XML文档
- 特点:占用资源少,内存消耗小
DOM4:
- J非常优秀的Java XML API
- 性能优异、功能强大
- 开放源代码
3.1 DOM的介绍
文档对象模型(Document Object Model),DOM把XML文档映射成一个倒挂的树
<book >
<title>三国演义</title>
<author>罗贯中</author>
<price>30元</price>
</book>
3.2 DOM常用接口介绍
4 使用DOM来解析XML1
4.1 通常解析的步骤
DOM解析XML文件步骤:
1.创建解析器工厂对象
2.解析器工厂对象创建解析器对象
3.解析器对象指定XML文件创建Document对象
4.以Document对象为起点操作DOM树
5.创建Transformer对象
作用->将内存中的document对象写入xml文件
1)TransformerFactory.newInstance() 获取TransformerFactory()对象
2)transformerFactory.newTransformer() 获取Transformer对象
3)transformer.transform() 将document写入xml文件
4.2显示“收藏信息.xml”
显示“收藏信息.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>
package practise.practise02;
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;
public class DomShowPhone {
public static void main(String[] args) {
try {
// 1. 创建一个 DocumentBuilderFactory 实例
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2. 使用工厂方法创建一个 DocumentBuilder 实例
DocumentBuilder builder = factory.newDocumentBuilder();
// 3. 解析 XML 文件并获取 DOM Document 对象
Document document = builder.parse("Test10/config/phone.xml");
// 4. 规范化 XML 文档
document.getDocumentElement().normalize();//除去多余的换行符和空格,使树形结构更加完整
// 5. 获取根元素
// Element root = document.getDocumentElement();//获取根元素
// System.out.println("根元素为: " + root.getNodeName());//获取根元素名字
// 6. 获取所有 <Brand> 元素
NodeList nList = document.getElementsByTagName("Brand");//按照文档顺序将所有Brand元素返回到集合中
for (int temp = 0; temp < nList.getLength(); temp++) {
Node node = nList.item(temp);//遍历获取Brand节点
Element eElement= (Element) node;
System.out.println("品牌:"+eElement.getAttribute("name"));//得到name属性的值
NodeList type = eElement.getElementsByTagName("Type");
for (int i = 0; i < type.getLength(); i++) {
Element type1 = (Element) type.item(i);
type1.setAttribute("id","type"+(i+1));
System.out.println("型号:"+type1.getAttribute("name"));//获取name属性的值 Attribute属性的意思
}
// if (node.getNodeType() == Node.ELEMENT_NODE) {//用于确保当前节点是一个元素节点(ELEMENT_NODE)。
// Element eElement = (Element) node;
//
// // 打印书籍的详细信息
// System.out.println("Title: " + eElement.getElementsByTagName("title").item(0).getTextContent());//获取元素的文本内容
// System.out.println("Author: " + eElement.getElementsByTagName("author").item(0).getTextContent());
// System.out.println("Price: " + eElement.getElementsByTagName("price").item(0).getTextContent());
// }
}
Node brand = nList.item(0);
Element brand1 = (Element) brand;
brand1.setAttribute("id","brand1");
// brand1.setAttribute("id","b1");
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.3 收藏信息保存到文件中
package practise.practise03;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
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;
public class AddBrandDOM {
public static void main(String[] args) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("Test10/config/phone.xml");
Element newBrand = document.createElement("Brand");
newBrand.setAttribute("name","三星");
Element newType = document.createElement("Type");// tag 是标签的意思
newType.setAttribute("name","Note4");
newBrand.appendChild(newType);//将newType元素添加到newBrand的子节点
Element root = document.getDocumentElement();//得到根节点
root.appendChild(newBrand);//将newBrand元素添加到根元素的子节点
// 6. 创建 Transformer 对象以保存修改后的 DOM 树
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
// 7. 设置输出属性
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
// 8. 创建 DOMSource 对象
DOMSource domSource = new DOMSource(document);
// 9. 创建 StreamResult 对象并指定输出文件
StreamResult streamResult = new StreamResult("Test10/config/phone.xml");
// 10. 保存修改后的 XML 到指定文件
transformer.transform(domSource, streamResult);
System.out.println("XML 文件已成功修改");
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.4 修改删除手机收藏
修改/删除DOM节点:
- 给所有的Brand标签添加id属性
- 获取Brand标签
- 调用setAttribute()方法添加属性
删除Brand值为“华为”的标签
- getElementsByTagName()方法获取Brand标签列表
- 获得Brand值为“华为”的标签对象
- 通过getParentNode()方法获得父节点对象
- 调用父节点的removeChild()方法删除节点
XML文件:
<PhoneInfo>
<Brand name="苹果">
<Type name="iPhone4"/>
</Brand>
<Brand name="华为">
<Type name="U8650"/>
<Type name="HW123"/>
<Type name="HW321"/>
</Brand>
<Brand id="brand2" name="三星">
<Type name="Note4"/>
</Brand>
<price id="3" name="小米">
<Type name="小米11"/>
</price>
</PhoneInfo>
package practise.practise1;
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.IOException;
public class RomeBrandDOM {
public static void main(String[] args) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("Test11/config/phone.xml");
Element root = document.getDocumentElement();//获取根节点元素
root.normalize();
NodeList nodeList = document.getElementsByTagName("Brand");
for (int i = 0; i < nodeList.getLength(); i++) {
document.getDocumentElement().normalize();
Node node=nodeList.item(i);
Element element = (Element) node;
element.setAttribute("id","brand"+(i+1));
if ("华为".equals(element.getAttribute("name"))){
element.getParentNode().removeChild(element);
i--;
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
// 7. 设置输出属性
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // 启用缩进
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); // 设置缩进量(每级缩进4个空格)
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); // 设置编码
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); // 保留 XML 声明
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
// 8. 创建 DOMSource 对象
DOMSource domSource = new DOMSource(document);
// 9. 创建 StreamResult 对象并指定输出文件
StreamResult streamResult = new StreamResult("Test11/config/phone.xml");
// 10. 保存修改后的 XML 到指定文件
transformer.transform(domSource, streamResult);
System.out.println("XML 文件已成功修改");
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
5 使用DOM4J解析XML
5.1 Dom4j主要内容简述:
- Document 文档 - 代表整个 XML 文档。 Document 对象通常称为 DOM 树。
- Element 元素 - 表示 XML 元素。元素对象具有操作其子元素、文本、属性和命名空间的方法。
- Attribute 属性 - 表示元素的属性。属性具有获取和设置属性值的方法。它具有父类型和属性类型。
- Node 节点 - 表示元素、属性或处理指令
5.2 常见的Dom4j方法描述
- SAXReader.read(xmlSource)() − 从 XML 源构建 DOM4J 文档。
- Document.getRootElement() − 获取 XML 文档的根元素。
- Element.node(index) − 获取元素中特定索引处的 XML 节点。
- Element.attributes() − 获取元素的所有属性。
- Node.valueOf(@Name) − 获取具有给定元素名称的属性值
5.3 Dom4J的XML解析器
SAXReader解析器:
SAXReader reader = new SAXReader();
String xmlString = ResourceUtil.readStr("conversion/TestMain.xml", StandardCharsets.UTF_8);
Document document = reader.read(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
5.4 使用DOM4J解析XML文件示例
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<PhoneInfo>
<Brand id="brand1" name="苹果">
<Type name="iPhone4"/>
</Brand>
<Brand id="brand2" name="三星">
<Type name="Note4"/>
</Brand>
<price id="3" name="小米">
<Type name="小米11"/>
</price>
</PhoneInfo>
- 显示手机收藏信息
- 保存手机收藏信息
- 为手机收藏信息添加新的节点
- 修改/删除手机收藏信息节点
package practise.practise2;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.FileOutputStream;
import java.util.Iterator;
import java.util.List;
@SuppressWarnings("all")
public class ShowDom4j {
public static void main(String[] args) {
String str="Test11/config/phone.xml";
SAXReader saxReader = new SAXReader();
try {
//1 显示手机收藏信息
Document document = saxReader.read(str);
Element rootElement = document.getRootElement();
List<Element> brandList = rootElement.elements("Brand");//取得子节点所有Brand元素
Iterator<Element> iterator = brandList.iterator();
while (iterator.hasNext()) {
Element brandElement = iterator.next();
System.out.print("Brand-id="+brandElement.attributeValue("id")+",Brand-name="+brandElement.attributeValue("name"));
List<Element> type = brandElement.elements("Type");
for (Element element :type) {
System.out.println("Type-name="+element.attributeValue("name"));
}
}
//2,3 为手机收藏信息并添加新节点并保存
Element priceElement = rootElement.addElement("price");
priceElement.addAttribute("id","brand3");
priceElement.addAttribute("name","小米");
Element typeElement = priceElement.addElement("Type");
typeElement.addAttribute("name","小米11");
//4 修改/删除手机收藏信息节点 删除苹果节点的子节点
Node node = document.selectSingleNode("//Brand[@name='苹果']");//xpath 语法
Element branElment=(Element) node;
rootElement.remove(branElment);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8"); // 设置编码
format.setIndent(true); // 启用缩进
format.setIndentSize(4); // 设置缩进的空格数
format.setNewLineAfterDeclaration(true); // 在 XML 声明后添加换行
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(str),format);
xmlWriter.write(document);
System.out.println("写入成功xml!!");
xmlWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}