本文纲要
XML概述与优势XML基础语法
标签规则
文档结构
特殊字符与CDATA区XML约束
DTD约束
DTD语法(元素、属性)
引入DTD的三种方式
Schema约束
Schema与DTD的区别
Schema语法(元素、属性)
引入SchemaXML解析
DOM解析思想
dom4j解析实战
XML概述与优势
XML(eXtensible Markup Language,可扩展标记语言)是一种用于存储和传输数据的标记语言。它由W3C(万维网联盟)发布,广泛应用于Java项目的配置文件、数据交换等场景。
相比于传统的.properties配置文件,XML具有更好的可读性和可维护性,尤其当配置项较多时,结构化的标签能清晰地表达数据层次。
优势对比:
| 特性 | properties 文件 | XML 文件 |
|---|---|---|
| 结构 | 键值对,平铺 | 标签嵌套,层次化结构 |
| 可读性 | 配置项多时冗长 | 标签包围,直观,易于阅读 |
| 扩展性 | 一般 | 可自定义标签,扩展性强 |
例如下面这个 XML 配置片段,配置一个 Servlet 时十分清晰:
xml
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>com.example.LoginServlet</servlet-class>
</servlet>
当需要配置多个 Servlet 时,只需复制整个<servlet>块即可,维护与阅读都很方便。
XML基础语法
1 ) 标签规则
XML 由标签组成,标签名称可以自定义,但需要遵循以下规则:
- 标签由尖括号和标识符组成,例如
<student> - 标签必须成对出现:开始标签
<name>和结束标签</name> - 特殊标签可以不成对,但必须有结束标记,例如
<address/> - 属性值必须用引号(单引号或双引号)括起来,例如 id="1"
- 标签必须正确嵌套
- 错误示例:
<student><name>张三</student></name>(×) - 正确:
<student><name>张三</name></student>
- 错误示例:
2 ) 文档结构
一个标准的 XML 文件包含以下部分:
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--注释内容-->
<rootElement>
<child attribute="value">文本内容</child>
</rootElement>
主要组成:
- 文档声明:必须在第一行第一列,不能有前导空格
version:必须写,固定为"1.0"encoding:可选,常用UTF-8standalone:可选,表示是否依赖其他XML文件(yes/no)
- 根标签:整个文档有且仅有一个根标签
- 子标签:可任意嵌套
3 ) 特殊字符与CDATA区
若想在标签体中包含 <、> 等特殊字符,需要使用预定义实体:
| 字符 | 实体引用 |
|---|---|
| < | < |
| > | > |
| & | & |
| " | " |
| ' | ' |
例如:
xml
<info>学生< > 的信息</info>
如果文本中包含大量特殊字符,逐一转义很麻烦,可以使用 CDATA区,其内容会被当作纯文本:
xml
<message><![CDATA[内容 <<<<<< >>>>>>]]></message>
这样即使出现多个 <、> 也不会报错。
示例代码(对应项目中的 student.xml 注释部分):
xml
<!-- 使用转义字符 -->
<info>学生< >>>>>>> 的信息</info>
<!-- 使用CDATA区 -->
<message><![CDATA[内容 <<<<<< >>>>>>]]></message>
4 ) XML校验
编写完 XML 后,可以通过以下方式校验是否正确:
- IDE 校验:IDEA 等开发工具会自动标红错误
- 浏览器打开:正确显示可折叠的树形结构,错误时显示错误信息
XML约束
在实际项目中,XML 多作为配置文件,软件的解析代码是事先写好的。为了防止开发者随意定义标签而导致解析失败,需要使用约束技术 限定 XML 中可以使用的标签、属性等。
项目结构一览
最终项目包含 XML 示例、约束文件及解析代码,完整结构如下:
dir
myxml/
├── libs/
│ └── dom4j-1.6.1.jar
├── xml/
│ └── student.xml # 解析目标文件
├── dtdgrammar/
│ ├── person1.xml # 引用DTD的XML
│ └── persondtd.dtd # DTD约束文件
├── importdtd/
│ ├── person1.xml # 引入本地DTD
│ ├── person2.xml # 内部定义DTD
│ ├── person3.xml # 引入网络DTD
│ └── persondtd.dtd # 公用DTD
├── schemaprimer/
│ ├── person.xml # 引用Schema的XML
│ └── person.xsd # Schema约束文件
└── src/
└── com/wb/xmlparse/
├── Student.java # 实体类
└── XmlParse.java # dom4j解析演示
常用约束技术有两种:DTD 和 Schema
1 ) DTD约束
1.1 DTD入门
DTD(Document Type Definition)通过定义元素和属性来约束 XML。
元素即标签,分为:
- 简单元素 :不包含子元素,如
<name>、<age> - 复杂元素 :包含子元素,如
<persons>、<person>
定义元素格式:<!ELEMENT 元素名 (内容)>
简单元素内容写 (#PCDATA),表示字符串;复杂元素内容写子元素名。
示例:约束如下 XML
xml
<persons>
<person>
<name>张三</name>
<age>23</age>
</person>
</persons>
对应的 DTD 文件 persondtd.dtd:
dtd
<!ELEMENT persons (person)>
<!ELEMENT person (name, age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
说明:
persons是复杂元素,包含personperson是复杂元素,包含name和age(逗号表示顺序出现)name、age是简单元素,类型为#PCDATA
1.2 引入DTD的三种方式
1.2.1 引入本地DTD:<!DOCTYPE 根标签名 SYSTEM "dtd文件路径">
xml
<!DOCTYPE persons SYSTEM 'persondtd.dtd'>
1.2.2 在XML内部定义DTD:
xml
<!DOCTYPE persons [
<!ELEMENT persons (person)>
<!ELEMENT person (name, age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
]>
1.2.3 引入网络DTD:
xml
<!DOCTYPE persons PUBLIC "dtd名称" "dtd文档的URL">
1.3 DTD语法规则
定义元素数量限定:
+:至少出现一次*:零次或多次?:零次或一次不写:恰好一次|:或,只能选一个
例如:
dtd
<!ELEMENT persons (person+)> <!-- person可多次出现 -->
<!ELEMENT person (name|age)> <!-- name或age选其一 -->
定义属性
格式:<!ATTLIST 元素名 属性名 属性类型 约束>
- 属性类型常用 CDATA(普通字符串)
- 约束:
#REQUIRED:必填#IMPLIED:可选#FIXED "值":固定值
示例:
dtd
<!ATTLIST person id CDATA #REQUIRED>
表示 person 标签必须有 id 属性,属性值为字符串。
完整 DTD 案例(项目 dtdgrammar/persondtd.dtd):
dtd
<!ELEMENT persons (person+)>
<!ELEMENT person (name,age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ATTLIST person id CDATA #REQUIRED>
对应 XML 必须写 id 属性:
xml
<persons>
<person id="001">
<name>张三</name>
<age>23</age>
</person>
</persons>
2 ) Schema约束
2.1 Schema与DTD的区别
Schema 也是一种 XML 约束,相比 DTD 更强大:
| 对比项 | DTD | Schema |
|---|---|---|
| 自身是否为XML | 否 | 是 |
| 引用多个约束 | 不支持 | 支持,使用名称空间区分 |
| 数据类型 | 只有 #PCDATA | 支持多种类型(string,int等) |
| 后缀名 | .dtd | .xsd |
重点:Schema 本身也是 XML 文件,它约束别人,同时也被别的 Schema 约束。
2.2 编写Schema
以约束下面的 XML 为目标:
xml
<persons>
<person id="001">
<name>张三</name>
<age>23</age>
</person>
</persons>
对应的 Schema 文件 person.xsd:
xml
<?xml version="1.0" encoding="UTF-8" ?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.wb.cn/javase"
elementFormDefault="qualified"
<!--定义persons复杂元素-->
<element name="persons">
<complexType>
<sequence>
<!--定义person复杂元素-->
<element name="person">
<complexType>
<sequence>
<!--定义name和age简单元素-->
<element name="name" type="string"></element>
<element name="age" type="string"></element>
</sequence>
<attribute name="id" type="string" use="required"></attribute>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
要点解析:
xmlns="http://www.w3.org/2001/XMLSchema":表示当前文件是一个约束文件targetNamespace:指定本约束的名称空间,供他人引用elementFormDefault="qualified":固定格式,表示本文件质量良好<element>:定义元素,复杂元素用<complexType>包裹;简单元素用type="string"等指定类型<sequence>:指示子元素必须按顺序出现<attribute>:定义属性,use="required"表示必填,optional为可选
2.3 引入Schema
在 XML 的根标签中添加:
xml
<persons
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.wb.cn/javase"
xsi:schemaLocation="http://www.wb.cn/javase person.xsd"
<!-- 内容 -->
</persons>
说明:
xmlns:xsi:声明本 XML 是一个被 Schema 约束的实例xmlns="...":引入约束文件的名称空间(即targetNamespace)xsi:schemaLocation:内容为"名称空间 URI 空格 xsd 文件路径",告诉解析器从哪里找约束文件
Mermaid 流程图 - Schema约束作用机制:
#mermaid-svg-qYGd4FHsErSHwfKl{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qYGd4FHsErSHwfKl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qYGd4FHsErSHwfKl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qYGd4FHsErSHwfKl .error-icon{fill:#552222;}#mermaid-svg-qYGd4FHsErSHwfKl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qYGd4FHsErSHwfKl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qYGd4FHsErSHwfKl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qYGd4FHsErSHwfKl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qYGd4FHsErSHwfKl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qYGd4FHsErSHwfKl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qYGd4FHsErSHwfKl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qYGd4FHsErSHwfKl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qYGd4FHsErSHwfKl .marker.cross{stroke:#333333;}#mermaid-svg-qYGd4FHsErSHwfKl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qYGd4FHsErSHwfKl p{margin:0;}#mermaid-svg-qYGd4FHsErSHwfKl .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qYGd4FHsErSHwfKl .cluster-label text{fill:#333;}#mermaid-svg-qYGd4FHsErSHwfKl .cluster-label span{color:#333;}#mermaid-svg-qYGd4FHsErSHwfKl .cluster-label span p{background-color:transparent;}#mermaid-svg-qYGd4FHsErSHwfKl .label text,#mermaid-svg-qYGd4FHsErSHwfKl span{fill:#333;color:#333;}#mermaid-svg-qYGd4FHsErSHwfKl .node rect,#mermaid-svg-qYGd4FHsErSHwfKl .node circle,#mermaid-svg-qYGd4FHsErSHwfKl .node ellipse,#mermaid-svg-qYGd4FHsErSHwfKl .node polygon,#mermaid-svg-qYGd4FHsErSHwfKl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qYGd4FHsErSHwfKl .rough-node .label text,#mermaid-svg-qYGd4FHsErSHwfKl .node .label text,#mermaid-svg-qYGd4FHsErSHwfKl .image-shape .label,#mermaid-svg-qYGd4FHsErSHwfKl .icon-shape .label{text-anchor:middle;}#mermaid-svg-qYGd4FHsErSHwfKl .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qYGd4FHsErSHwfKl .rough-node .label,#mermaid-svg-qYGd4FHsErSHwfKl .node .label,#mermaid-svg-qYGd4FHsErSHwfKl .image-shape .label,#mermaid-svg-qYGd4FHsErSHwfKl .icon-shape .label{text-align:center;}#mermaid-svg-qYGd4FHsErSHwfKl .node.clickable{cursor:pointer;}#mermaid-svg-qYGd4FHsErSHwfKl .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qYGd4FHsErSHwfKl .arrowheadPath{fill:#333333;}#mermaid-svg-qYGd4FHsErSHwfKl .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qYGd4FHsErSHwfKl .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qYGd4FHsErSHwfKl .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qYGd4FHsErSHwfKl .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qYGd4FHsErSHwfKl .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qYGd4FHsErSHwfKl .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qYGd4FHsErSHwfKl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qYGd4FHsErSHwfKl .cluster text{fill:#333;}#mermaid-svg-qYGd4FHsErSHwfKl .cluster span{color:#333;}#mermaid-svg-qYGd4FHsErSHwfKl div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qYGd4FHsErSHwfKl .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qYGd4FHsErSHwfKl rect.text{fill:none;stroke-width:0;}#mermaid-svg-qYGd4FHsErSHwfKl .icon-shape,#mermaid-svg-qYGd4FHsErSHwfKl .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qYGd4FHsErSHwfKl .icon-shape p,#mermaid-svg-qYGd4FHsErSHwfKl .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qYGd4FHsErSHwfKl .icon-shape .label rect,#mermaid-svg-qYGd4FHsErSHwfKl .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qYGd4FHsErSHwfKl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qYGd4FHsErSHwfKl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qYGd4FHsErSHwfKl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
编写 XML 配置文件
是否引入 Schema?
声明 xsi 命名空间
指定名称空间 xmlns
用 schemaLocation 关联 .xsd 文件
XML 编写需遵循 .xsd 定义
无约束,可任意定义标签
软件解析 XML 时按约束校验
XML解析
1 ) DOM解析思想
常用的解析思想是 DOM(Document Object Model):将整个 XML 文档一次性加载到内存,形成树形结构,然后逐层获取数据。
核心对象:
Document:整个文档对象Element:标签对象Attribute:属性对象Text:标签体文本
解析过程类似"剥玉米":整体 → 根 → 子元素 → 属性/文本。
以如下XML为例:
xml
<students>
<student id="1">
<name>张三</name>
<age>23</age>
</student>
<student id="2">
<name>李四</name>
<age>24</age>
</student>
</students>
DOM树结构如下(mermaid):
#mermaid-svg-cHvqhSfP6xwVoepf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cHvqhSfP6xwVoepf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cHvqhSfP6xwVoepf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cHvqhSfP6xwVoepf .error-icon{fill:#552222;}#mermaid-svg-cHvqhSfP6xwVoepf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cHvqhSfP6xwVoepf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cHvqhSfP6xwVoepf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cHvqhSfP6xwVoepf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cHvqhSfP6xwVoepf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cHvqhSfP6xwVoepf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cHvqhSfP6xwVoepf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cHvqhSfP6xwVoepf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cHvqhSfP6xwVoepf .marker.cross{stroke:#333333;}#mermaid-svg-cHvqhSfP6xwVoepf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cHvqhSfP6xwVoepf p{margin:0;}#mermaid-svg-cHvqhSfP6xwVoepf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cHvqhSfP6xwVoepf .cluster-label text{fill:#333;}#mermaid-svg-cHvqhSfP6xwVoepf .cluster-label span{color:#333;}#mermaid-svg-cHvqhSfP6xwVoepf .cluster-label span p{background-color:transparent;}#mermaid-svg-cHvqhSfP6xwVoepf .label text,#mermaid-svg-cHvqhSfP6xwVoepf span{fill:#333;color:#333;}#mermaid-svg-cHvqhSfP6xwVoepf .node rect,#mermaid-svg-cHvqhSfP6xwVoepf .node circle,#mermaid-svg-cHvqhSfP6xwVoepf .node ellipse,#mermaid-svg-cHvqhSfP6xwVoepf .node polygon,#mermaid-svg-cHvqhSfP6xwVoepf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cHvqhSfP6xwVoepf .rough-node .label text,#mermaid-svg-cHvqhSfP6xwVoepf .node .label text,#mermaid-svg-cHvqhSfP6xwVoepf .image-shape .label,#mermaid-svg-cHvqhSfP6xwVoepf .icon-shape .label{text-anchor:middle;}#mermaid-svg-cHvqhSfP6xwVoepf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cHvqhSfP6xwVoepf .rough-node .label,#mermaid-svg-cHvqhSfP6xwVoepf .node .label,#mermaid-svg-cHvqhSfP6xwVoepf .image-shape .label,#mermaid-svg-cHvqhSfP6xwVoepf .icon-shape .label{text-align:center;}#mermaid-svg-cHvqhSfP6xwVoepf .node.clickable{cursor:pointer;}#mermaid-svg-cHvqhSfP6xwVoepf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cHvqhSfP6xwVoepf .arrowheadPath{fill:#333333;}#mermaid-svg-cHvqhSfP6xwVoepf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cHvqhSfP6xwVoepf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cHvqhSfP6xwVoepf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cHvqhSfP6xwVoepf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cHvqhSfP6xwVoepf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cHvqhSfP6xwVoepf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cHvqhSfP6xwVoepf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cHvqhSfP6xwVoepf .cluster text{fill:#333;}#mermaid-svg-cHvqhSfP6xwVoepf .cluster span{color:#333;}#mermaid-svg-cHvqhSfP6xwVoepf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cHvqhSfP6xwVoepf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cHvqhSfP6xwVoepf rect.text{fill:none;stroke-width:0;}#mermaid-svg-cHvqhSfP6xwVoepf .icon-shape,#mermaid-svg-cHvqhSfP6xwVoepf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cHvqhSfP6xwVoepf .icon-shape p,#mermaid-svg-cHvqhSfP6xwVoepf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cHvqhSfP6xwVoepf .icon-shape .label rect,#mermaid-svg-cHvqhSfP6xwVoepf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cHvqhSfP6xwVoepf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cHvqhSfP6xwVoepf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cHvqhSfP6xwVoepf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Document
根Element: students
Element: student
Element: student
Attribute: id=1
Element: name
Element: age
Text: 张三
Text: 23
Attribute: id=2
Element: name
Element: age
Text: 李四
Text: 24
2 ) dom4j解析实战
2.1 准备工作
dom4j 是一个第三方开源的 XML 解析框架,使用前需下载并导入 dom4j-1.6.1.jar
项目目录结构(放置 jar 包):
dir
myxml/
├── libs/
│ └── dom4j-1.6.1.jar
├── xml/
│ └── student.xml
└── src/
└── com/wb/xmlparse/
├── Student.java
└── XmlParse.java
将 jar 包添加为库:右键 jar → Add as Library。
2.2 解析代码
需求:解析 student.xml,将数据封装为 Student 对象,存入 ArrayList 并打印
实体类 Student.java:
java
package com.wb.xmlparse;
public class Student {
private String id;
private String name;
private int age;
public Student() {}
public Student(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
// getter & setter & toString 省略...
}
解析类 XmlParse.java:
java
package com.wb.xmlparse;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/*
利用dom4j解析xml文件
*/
public class XmlParse {
public static void main(String[] args) throws DocumentException {
//1. 创建解析器对象
SAXReader saxReader = new SAXReader();
//2. 将xml文件加载到内存,获取Document文档对象(整体)
Document document = saxReader.read(new File("myxml\\xml\\student.xml"));
//3. 获取根标签 students
Element rootElement = document.getRootElement();
//4. 获取所有指定的子标签 student (避免获取到其他标签如aaa)
List<Element> studentElements = rootElement.elements("student");
//准备集合存储学生对象
ArrayList<Student> list = new ArrayList<>();
//5. 遍历每个student标签
for (Element element : studentElements) {
// 获取id属性值
Attribute attribute = element.attribute("id");
String id = attribute.getValue();
// 获取name子标签,再获取其文本内容
Element nameElement = element.element("name");
String name = nameElement.getText();
// 获取age子标签,再获取其文本内容
Element ageElement = element.element("age");
String ageStr = ageElement.getText();
// 转为int
int age = Integer.parseInt(ageStr);
// 封装到Student对象
Student s = new Student(id, name, age);
list.add(s);
}
// 遍历集合输出
for (Student student : list) {
System.out.println(student);
}
}
}
关键方法总结:
SAXReader.read(file):读取 XML,返回Documentdocument.getRootElement():获取根元素rootElement.elements("子标签名"):获取所有指定名称的子元素集合element.attribute("属性名"):获取属性对象,再.getValue()得到属性值element.element("子标签名"):获取单个指定子元素element.getText():获取元素中的文本内容
解析流程图:
#mermaid-svg-60ApR1T7ZLXr6cJc{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-60ApR1T7ZLXr6cJc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-60ApR1T7ZLXr6cJc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-60ApR1T7ZLXr6cJc .error-icon{fill:#552222;}#mermaid-svg-60ApR1T7ZLXr6cJc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-60ApR1T7ZLXr6cJc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-60ApR1T7ZLXr6cJc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-60ApR1T7ZLXr6cJc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-60ApR1T7ZLXr6cJc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-60ApR1T7ZLXr6cJc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-60ApR1T7ZLXr6cJc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-60ApR1T7ZLXr6cJc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-60ApR1T7ZLXr6cJc .marker.cross{stroke:#333333;}#mermaid-svg-60ApR1T7ZLXr6cJc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-60ApR1T7ZLXr6cJc p{margin:0;}#mermaid-svg-60ApR1T7ZLXr6cJc .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-60ApR1T7ZLXr6cJc .cluster-label text{fill:#333;}#mermaid-svg-60ApR1T7ZLXr6cJc .cluster-label span{color:#333;}#mermaid-svg-60ApR1T7ZLXr6cJc .cluster-label span p{background-color:transparent;}#mermaid-svg-60ApR1T7ZLXr6cJc .label text,#mermaid-svg-60ApR1T7ZLXr6cJc span{fill:#333;color:#333;}#mermaid-svg-60ApR1T7ZLXr6cJc .node rect,#mermaid-svg-60ApR1T7ZLXr6cJc .node circle,#mermaid-svg-60ApR1T7ZLXr6cJc .node ellipse,#mermaid-svg-60ApR1T7ZLXr6cJc .node polygon,#mermaid-svg-60ApR1T7ZLXr6cJc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-60ApR1T7ZLXr6cJc .rough-node .label text,#mermaid-svg-60ApR1T7ZLXr6cJc .node .label text,#mermaid-svg-60ApR1T7ZLXr6cJc .image-shape .label,#mermaid-svg-60ApR1T7ZLXr6cJc .icon-shape .label{text-anchor:middle;}#mermaid-svg-60ApR1T7ZLXr6cJc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-60ApR1T7ZLXr6cJc .rough-node .label,#mermaid-svg-60ApR1T7ZLXr6cJc .node .label,#mermaid-svg-60ApR1T7ZLXr6cJc .image-shape .label,#mermaid-svg-60ApR1T7ZLXr6cJc .icon-shape .label{text-align:center;}#mermaid-svg-60ApR1T7ZLXr6cJc .node.clickable{cursor:pointer;}#mermaid-svg-60ApR1T7ZLXr6cJc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-60ApR1T7ZLXr6cJc .arrowheadPath{fill:#333333;}#mermaid-svg-60ApR1T7ZLXr6cJc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-60ApR1T7ZLXr6cJc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-60ApR1T7ZLXr6cJc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-60ApR1T7ZLXr6cJc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-60ApR1T7ZLXr6cJc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-60ApR1T7ZLXr6cJc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-60ApR1T7ZLXr6cJc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-60ApR1T7ZLXr6cJc .cluster text{fill:#333;}#mermaid-svg-60ApR1T7ZLXr6cJc .cluster span{color:#333;}#mermaid-svg-60ApR1T7ZLXr6cJc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-60ApR1T7ZLXr6cJc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-60ApR1T7ZLXr6cJc rect.text{fill:none;stroke-width:0;}#mermaid-svg-60ApR1T7ZLXr6cJc .icon-shape,#mermaid-svg-60ApR1T7ZLXr6cJc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-60ApR1T7ZLXr6cJc .icon-shape p,#mermaid-svg-60ApR1T7ZLXr6cJc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-60ApR1T7ZLXr6cJc .icon-shape .label rect,#mermaid-svg-60ApR1T7ZLXr6cJc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-60ApR1T7ZLXr6cJc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-60ApR1T7ZLXr6cJc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-60ApR1T7ZLXr6cJc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建SAXReader
读取XML获得Document
获取根元素 Element
获取指定子元素列表
遍历每个子元素
获取属性: attribute.getValue
获取子元素: element.element...getText
封装为对象
加入集合
遍历输出
这样我们就完成了 XML 的解析。
总结
通过本文,我们从 XML 的基础语法开始,学习了 DTD 和 Schema 两种约束技术,并通过 dom4j 实现了 XML 文件的解析,掌握了 Java 中处理 XML 的核心技能。