XML(Extensible Markup Language),可扩展标记语言
<books>
<book id="bk101">
<title>.NET高级编程title>
<author>王姗author>
<description>包含C#框架和网络编程等description>
book>
<book id="bk102">
<title>XML基础编程title>
<author>李明明author>
<description>包含XML基础概念和基本用法description>
book>
books>
使用标签描述的文档元素信息,成对出现。
节点不包含子节点可自闭合
XML 文档的内容元素由一系列标签组成
<元素名 属性名="属性值">元素内容(子元素、字符等)元素名>
xml
(或者XML、Xml)开始 <、"、&
XML 中的特殊字符包括 < 、> 、' 、" 、&
使用预定义实体对特殊字符进行转义
特殊字符 | 实体名称 |
---|---|
< | < |
> | > |
" | " |
’ | ' |
& | & |
在元素的文本中使用 CDATA 节处理
<description>
以及的使用]]>
description>
格式良好的 XML 文档需要遵循如下规则
DOM 和 SAX 不针对特定语言,只是定义了一些接口,以及部分缺省实现(使用空方法实现接口)
文档对象模型(Document Object Model)DOM 把 XML 文档映射成一个倒挂的树
<book >
<title>三国演义title>
<author>罗贯中author>
<price>30元price>
book>
使用 Oracle 提供的 JAXP(Java API for XML Processing)
常用接口 | 说明 | 常用方法 |
---|---|---|
Node | 代表了文档树中的一个抽象节点,有 Document、Element、Text 等子对象 | NodeList getChildNodes() Node getFirstChild() Node getLastChild() Node getNextSibling() Node getPreviousSibling() Node appendChild(Node child) String getNodeName() String getNodeValue() short getNodeType() |
NodeList | 包含了一个或多个节点(Node)的列表 | int getLength() Node item(int index) |
Document | 表示整个 XML 文档 | NodeList getElementsByTagName(String tagname) Element getElementById(String id) Element getDocumentElement() Element createElement(String tagname) |
Element | XML 文档中的一个元素,是 Node 最主要的子对象 | String getAttribute(String name) NodeList getElementsByTagName(String tagname) String getTagName() |
显示 XML 文件中收藏的手机品牌和型号
<PhoneInfo>
<Brand name="华为">
<Type name="P90"/>
<Item>
<title>标题信息title>
<link>链接link>
<description>描述description>
<pubDate>2023-02-01pubDate>
Item>
Brand>
<Brand name="苹果">
<Type name="iPhone Z"/>
<Type name="iPhone ZL"/>
Brand>
<Brand name="三星">
<Type name="NoteX"/>
Brand>
PhoneInfo>
public class Book {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse("src/main/java/CH15_XML/PhoneInfo.xml");
NodeList bookList = doc.getElementsByTagName("Brand");
for (int i = 0; i < bookList.getLength(); i++) {
Node brand = bookList.item(i);
Element element = (Element) brand;
String attrVal = element.getAttribute("name");
NodeList types = element.getChildNodes();
for (int j = 0; j < types.getLength(); j++) {
Node typeNode = types.item(j);
if (typeNode.getNodeType() == Node.ELEMENT_NODE) {
Element typeElement = (Element) typeNode;
String type = typeElement.getAttribute("name");
System.out.println("手机:" + attrVal + type);
}
}
}
}
}
public class Xz01 {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
NodeList brandList = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse("src/main/resources/PhoneInfo.xml")
.getElementsByTagName("Brand");
for (int i = 0; i < brandList.getLength(); i++) {
Element brandElement = (Element) brandList.item(i);
System.out.println(brandElement.getTagName() + ":" + brandElement.getAttribute("name"));
NodeList typeList = brandElement.getElementsByTagName("Type");
for (int j = 0; j < typeList.getLength(); j++) {
Element typeElement = (Element) typeList.item(j);
System.out.println("\t" + typeElement.getTagName() + ":" + typeElement.getAttribute("name"));
NodeList itemList = brandElement.getElementsByTagName("Item");
for (int k = 0; k < itemList.getLength(); k++) {
Element itemElement = (Element) itemList.item(k);
NodeList pubDateList = itemElement.getElementsByTagName("pubDate");
System.out.print("\t" + itemElement.getTagName() + ":");
for (int l = 0; l < pubDateList.getLength(); l++) {
String textContent = pubDateList.item(l).getTextContent();
System.out.println(textContent);
}
}
}
}
}
}
// Brand:华为
// Type:P90
// Item:2023-02-01
// Brand:苹果
// Type:iPhone Z
// Type:iPhone ZL
// Brand:三星
// Type:NoteX
调用 Node 对象的 getChildNodes() 方法有时会包含 XML 文档中的空白符,导致调用 Node 对象方法出错,解决办法包括:
- 取得 Node 对象后判断
node.getNodeType() == Node.ELEMENT_NODE
,即判断是否是元素节- 点将 Node 对象转换为 Element 对象,使用 Element 的 getElementsByTagName(String name)
显示XML文件中手机新闻的发布日期
public class Book2 {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse("src/main/java/CH15_XML/PhoneInfo.xml");
NodeList bookList = doc.getElementsByTagName("pubDate");
Element pubDateElement = (Element) bookList.item(0);
String nodeValue = pubDateElement.getFirstChild().getNodeValue();
System.out.println(nodeValue);
}
}
// 2023-02-01
public class Book3 {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, TransformerException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse("src/main/java/CH15_XML/PhoneInfo.xml");
Element brandElement = doc.createElement("Brand");
brandElement.setAttribute("name", "三星");
Element typeElement = doc.createElement("Type");
typeElement.setAttribute("name", "NoteX");
brandElement.appendChild(typeElement);
Element phoneInfoElement = (Element) doc.getElementsByTagName("PhoneInfo").item(0);
phoneInfoElement.appendChild(brandElement);
TransformerFactory tff = TransformerFactory.newInstance();
Transformer tf = tff.newTransformer();
DOMSource domSource = new DOMSource(doc);
tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
StreamResult streamResult = new StreamResult(Files.newOutputStream(Paths.get("src/main/java/CH15_XML/PhoneInfo.xml")));
tf.transform(domSource, streamResult);
}
}
<Brand name="三星">
<Type name="NoteX"/>
Brand>
public class Book4 {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, TransformerException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse("src/main/java/CH15_XML/PhoneInfo.xml");
NodeList list = doc.getElementsByTagName("Brand");
for (int i = 0; i < list.getLength(); i++) {
Element brandItem = ((Element) list.item(i));
String brandName = brandItem.getAttribute("name");
if ("三星".equals(brandName)) {
// ElementBrand.setAttribute("name", "OPPO");
brandItem.getParentNode().removeChild(brandItem);
// 先获取父节点,再删除子节点
}
}
TransformerFactory tff = TransformerFactory.newInstance();
Transformer tf = tff.newTransformer();
DOMSource domSource = new DOMSource(doc);
tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
StreamResult streamResult = new StreamResult(Files.newOutputStream(Paths.get("src/CH15_XML/PhoneInfo.xml")));
tf.transform(domSource, streamResult);
}
}
DOM4J 的主要接口都定义在 org.dom4j 包里
接口说明 |
---|
Node:为所有的 DOM4J 中的 XML 节点定义了多态行为 |
Branch:为能够包含子节点的节点定义了公共行为 |
Element:定义 XML 元素 |
Document:定义 XML 文档 |
Entity:定义 XML 实体 |
Attribute:定义了 XML 的属性 |
DocumentType:定义 XML DOCTYPE 声明 |
ProcessingInstruction:定义 XML 处理指令 |
CharacterData:标识接口,标识基于字符的节点 |
Text:定义 XML 文本节点 |
CDATA:定义了 XML CDATA 区域 |
Comment:定义了 XML 注释的行为 |
常用接口 | 常用方法 |
---|---|
Branch | Element elementById(String id) Element addElement(String name) boolean remove(Node node) |
Document | Element getRootElement() |
Element | Element element(String name) List elements() List elements(String tagname) Iterator elementIterator() Iterator elementIterator(String name) Attribute attribute(String name) Element addAttribute(String name, String value) String getText() |
package CH15_XML;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.Iterator;
public class Book5 {
public static void main(String[] args) throws DocumentException {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/main/java/CH15_XML/PhoneInfo.xml"));
Element rootElement = document.getRootElement();
for (Iterator<Element> itBrand = rootElement.elementIterator(); itBrand.hasNext(); ) {
Element brand = itBrand.next();
System.out.println(brand.attributeValue("name"));
for (Iterator<Element> itType = brand.elementIterator(); itType.hasNext(); ) {
Element type = itType.next();
System.out.println("\t" + type.attributeValue("name"));
}
}
}
}
// 华为
// P90
// null
// 苹果
// iPhone Z
// iPhone ZL
// 三星
// NoteX