文章目录
一、XML简介
XML是Extensible Markup Language的缩写,即可扩展标记语言,是一种简单的存储语言,使用一系列简单的标记来描述结构化数据。
XML的特点
- XML与操作系统、编程语言的开发平台都无关。
- 规范统一,实现不同系统之间的数据交互。
XML的文档结构
1.声明(Declaration)
XML文档通常以XML声明开始,它定义了文档的版本和编码方式。这通常位于文档的第一行,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
XML声明由以下几个部分组成:
- version: 文档符合XML1.0规范。
- encoding: 文档字符编码,默认值为UTF-8。
2.标签(Label)
在XML中,通过用尖括号<>括起来的各种标签(Tag)来标记数据,标签成对使用来界定字符数据。例如,<author>
张三</author>
中,<author>
是开始标签,</author>
是结束标签,张三是标签描述的内容,表示作者信息。
注意:
XML标签必须正确结束并正确地嵌套,缺少结束标签及如下的嵌套方式是错误的。
<tile>
<name>XML编程
</title>
</name>
//这是一个错误的示范
3.元素(Elements)
XML文档由一系列的元素组成。元素由开始标签、结束标签和(可选的)内容组成。开始标签和结束标签包含元素的名称,而内容则是元素所包含的文本或其他元素。
<person>
<title>你好!</title>
<author>张三</author>
</person>
<person>
、<title>
和<author>
是元素的开始标签。</person>
、</title>
和</author>
是元素的结束标签。- “你好!” 和 “张三” 是元素的内容。
元素的命名规则如下:
- 名称中可以包含字母、数字或其他的字符。
- 名称不能以数字或标点符号开始。
- 名称不能以字符“XML”(XML、Xml)开始。
- 名称中不能包含空格。
元素允许是空元素,如<title></title>
,</title/>
的元素写法是允许的。
4.根元素(Root Element)
每个XML文档必须有且仅有一个根元素,如"<persons>``</persons>
"。
根元素的特点如下:
- 根元素是一个完全包括文档中其他所有元素的元素。
- 根元素的起始标签要放在所有其他元素的起始标签之前。
- 根元素的结束标签要放在所有其他元素的结束标签之后。
5.属性(Attributes)
元素可以有属性,这些属性提供了关于元素的额外信息。属性总是包含在开始标签中,并且由名称和值组成,使用等号 (=) 分隔,并用引号包围值。
<person id="1">
<title>你好!</title>
<author>张三</author>
</person>
- id="1"是
<person>
元素的属性。语法:
<元素名 属性名="属性值">
//属性值用引号包裹
注意:
1:一个元素可以有多个属性,多个属性之间用空格隔开,基本格式如下:
<元素名 属性名=“属性值” 属性名=“属性值”/>
2:属性值中不能直接包含<、"、&。
3:属性可以加在任何一个元素的起始标签上,但不能加在结束标签上。
6.XML中的特殊字符的处理
在XML中,有时在元素的文本中会涉及一些特殊字符(如<、>、'、"、&),而XML文档结构本身就用到这几个特殊字符,这会引起文档结构解析错误。有以下两种办法可以正常地解析包含特殊字符的内容。
(1)对这5个字符进行转义,也就是使用XML中的预定义实体代替这些字符。XML中的预定义实体和特殊字符的对应关系如下表所示。
特殊字符 | 实体名称 |
---|---|
< | <; |
> | >; |
& | &; |
" | "; |
’ | &apos; |
(2)在元素的文本中使用CDATA节处理。CDATA节中的所有字符都会被当作元素字符数据的常量部分,而不是XML标签。定义CDATA节的语法如下(推荐)
语法:
<![CDATA[
要显示的字符
]]>
7.注释
注释的语法如下。
<!-- 注释内容 -->
8.格式良好的XML文档
格式良好的XML文档需要遵循如下规则。
- 有XML声明语句。
- 有且仅有一个根元素。
- 标签大小写敏感。
- 标签大小写敏感。
- 标签成对/空标签关闭。
- 元素正确嵌套。
二、DOM读取XML数据
在Java中,你可以使用javax.xml.parsers包中的DocumentBuilderFactory和DocumentBuilder类来解析XML文件。以下是一个简单的Java代码示例,展示了如何使用这些类来读取和解析XML文件:
首先,确保你的XML文件(例如学员信息.xml)是有效的,并且与上面的示例类似:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<scores>
<student id="1">
<name>李煜</name>
<course>语文</course>
<score>95</score>
</student>
<student id="2">
<name>陈晓薇</name>
<course>数学</course>
<score>90</score>
</student>
</scores>
然后,你可以使用以下Java代码来解析这个XML文件:
package ch02.jianda;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class XMLStudent {
public static void main(String[] args) {
XMLStudent student =new XMLStudent();
student.getDocument();
student.showInFo();
student.universal();
}
Document doc = null;
public void getDocument(){
//获取解析器工厂
DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();
//获取解析器
try {
DocumentBuilder builder = factory.newDocumentBuilder();
//加载DOM树
doc = builder.parse("src/main/java/学员信息.xml");
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
public void showInFo(){
NodeList studentList = doc.getElementsByTagName("student");
for (int i = 0; i < studentList.getLength(); i++) {
Element student = (Element) studentList.item(i);
//获取并打印姓名
Element nameElement = (Element) student.getElementsByTagName("name").item(0);
String name = nameElement.getFirstChild().getNodeValue();
//获取并打印学科
Element courseElement = (Element) student.getElementsByTagName("course").item(0);
String course = courseElement.getFirstChild().getNodeValue();
//获取并打印分数
Element scoreElement = (Element) student.getElementsByTagName("score").item(0);
String score = scoreElement.getFirstChild().getNodeValue();
System.out.println("学员信息 姓名:"+name+"\t学科:"+course+"\t分数:"+score);
}
}
public void universal(){
//添加一个学员的成绩信息(id为3)
Element root = doc.getDocumentElement();
Element newStudent = doc.createElement("student");
newStudent.setAttribute("id", "3");
Element newName = doc.createElement("name");
newName.setTextContent("刘宇航");
newStudent.appendChild(newName);
Element newCourse = doc.createElement("course");
newCourse.setTextContent("英语");
newStudent.appendChild(newCourse);
Element newScore = doc.createElement("score");
newScore.setTextContent("85");
newStudent.appendChild(newScore);
root.appendChild(newStudent);
//修改id为2的成绩为60
NodeList studentList = doc.getElementsByTagName("student");
for (int i = 0; i < studentList.getLength(); i++) {
Node studentNode = studentList.item(i);
if (studentNode.getNodeType() == Node.ELEMENT_NODE) {
Element studentElement = (Element) studentNode;
if ("2".equals(studentElement.getAttribute("id"))) {
NodeList scoreList = studentElement.getElementsByTagName("score");
if (scoreList.getLength() > 0) {
Element scoreElement = (Element) scoreList.item(0);
scoreElement.setTextContent("60");
}
break;
}
}
}
//删除id为1的成绩
for (int i = 0; i < studentList.getLength(); i++) {
Node studentNode = studentList.item(i);
if (studentNode.getNodeType() == Node.ELEMENT_NODE) {
Element studentElement = (Element) studentNode;
if ("1".equals(studentElement.getAttribute("id"))) {
studentElement.getParentNode().removeChild(studentElement);
break;
}
}
}
try {
//保存XML文件
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(doc);
//设置编码类型
transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
StreamResult result = new StreamResult(new FileOutputStream("src/main/java/学员信息.xml"));
//把DOM树转换为XML文件
transformer.transform(domSource,result);
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
System.out.println("XML文件已修改并保存。");
}
}
运行后的学员信息.xml的universal()方法结果为:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<scores>
<student id="2">
<name>陈晓薇</name>
<course>数学</course>
<score>60</score>
</student>
<student id="3">
<name>刘宇航</name>
<course>英语</course>
<score>85</score>
</student>
</scores>
这段代码首先使用DocumentBuilderFactory和DocumentBuilder来解析XML文件,并获取Document对象。然后,它找到根元素并遍历所有<student>
元素。对于每个<student>
元素,它使用辅助方法getTagValue来获取<name>
、<course>
和<score>
标签的值,并将这些值打印到控制台。
三、DOM4J解析XML
下面是使用DOM4J解析学员信息.xml文档,从控制台输出所有学员信息。
package ch02.jianda;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.net.MalformedURLException;
public class DOM4JStudent {
public static void main(String[] args) {
Document doc = null;
try {
SAXReader saxReader = new SAXReader();
doc = saxReader.read(new File("src/main/java/学员信息.xml"));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
//获取XML的根节点
Element root = doc.getRootElement();
for(Object obj : root.elements("student")){
Element student = (Element) obj;
//获取并输出id、name、course和score
String id = student.attributeValue("id");
String name = student.elementText("name");
String course = student.elementText("course");
String score = student.elementText("score");
System.out.println("学员id:"+id+"\t姓名:"+name+"\t学科:"+course+"\t成绩:"+score);
}
}
}
运行结果: