XML快速入门
XML简介
- 可扩展标记型语言
- 标记型语言:HTML是标记型语言
- 也是使用标签来操作
- 可扩展:
- HTML里的标签是固定的,每个标签都有特定的含义
- 标签可以自己定义,可以写中文标签
- 标记型语言:HTML是标记型语言
- 用途
- HTML用于显示数据,xml也可以显示数据(不是主要功能)
- xml主要功能,为了存储数据
- xml是W3C组织发布的技术
- xml有两个版本1.0 1.1
- 使用都是1.0版本(1.1版本不能向下兼容)
XML的应用
-
不同的系统之间传输数据
- eg.qq消息之间的传输格式:
- 最早的时候,使用字符串,“发送者接受者发送消息发送时间”,可读性差,不利于程序的维护
- 现在,使用字符串,“各种标签,及其内容”,利于程序的维护
- eg.qq消息之间的传输格式:
-
用来表示生活中有关系的数据
(利用父节点和子节点)
-
经常用在配置文件中
XML的文档声明
- 创建一个文件,后缀名是.xml
- 写xml,第一步必须要有一个文档声明(写了文档声明之后,表示写xml文件的内容)
<?xml version="1.0" encoding="gbk"?>
- 文档声明必须写在第一行第一列
- 属性
- version:xml的版本:1.0(使用),1.1
- encoding:xml编码:gbk(中文简体),utf-8(包含中文),iso8859-1 (不包含中文)
- standalone:是否需要其他文件:yes,no
XML中文乱码问题解决
保存到本地硬盘时,使用gbk编码保存,打开xml时,打开使用设置的编码为utf-8,对应不一致,出现乱码
解决方案:设置保存时的编码与打开时的编码一致
XML元素(标签)的定义
- 标签定义<……>
- 标签定义必须有开始和结束
- 标签没有内容时,可以在标签内结束:
<aa/>
- 标签可以嵌套,必须合理嵌套
- 合理嵌套:
<aa><bb></bb></aa>
- 不合理嵌套:
<aa><bb></aa></bb>
- 合理嵌套:
- 一个xml中,只能有一个根标签,其他标签必须是这个标签下面的标签
- 在xml中把空格和换行都当做内容来解析
- xml标签可以是中文
- xml中标签的命名规则:
- xml代码区分大小写
- xml标签不能以数字和下划线开头
- xml标签不能以xml,XML,Xml等开头
- xml标签不能包含空格和冒号
XML属性的定义
- HTML是标记型文档,可以有属性;xml也是标记型文档,可以有属性
- 属性定义的要求:
- 一个标签上可以有多个属性
- 属性名称不能相同
- 属性名称和属性值之间用=,属性值一定要用引号包起来(单引号或双引号)
- xml属性的名称规范和元素的名称规范一致
XML注释
- 写法:
<!--……-->
- 注意:注释不能嵌套
- 注释也不能放在第一行,第一行第一列必须放文档声明
XML特殊字符
- 对特殊字符进行转译
- 小于<:< ;
- 大于>:> ;
- 双引号“:" ;
- 单引号‘:&apos ;
- &:& ;
XML的CDATA区
- 可以解决多个字符都需要转译的操作,把这些内容都放到CDATA区里面,就不需要进行转译了
- 写法:
<![CDATA [……] ]>
- 把特殊字符当成文本内容,而不是标签了
XML的PI指令(处理指令)
- 可以在xml中设置样式
- 写法:
<?xml-stylesheet type="text/css" href="css的路径"?>
- 设置样式,只对英文标签名称起作用,对于中文标签名称不起作用
XML约束简介
- 为什么需要约束:希望信息的保存不混乱,需要技术来规定xml中只能出现的元素,这个时候需要约束
- xml的约束技术:DTD约束和schema约束
DTD(文档类型定义)
DTD快速入门
-
创建一个文件,后缀名.dtd
-
步骤:
-
看xml中有多少个元素,有几个元素,就在dtd中写几个
<!ELEMENT>
-
判断元素是简单元素还是复杂元素
- 简单元素:没有子元素
<!ELEMENT 元素名称 (#PCDATA)>
- 复杂元素:有 子元素的元素
<!ELEMENT 元素名称 (子元素1,子元素2)>
- 简单元素:没有子元素
-
在xml文件中引入的dtd文件
<!DOCTYPE 根元素名称 SYSTEM "dtd文件的路径">
-
-
打开xml文件是使用浏览器打开的,浏览器只负责校验xml的语法,不负责校验约束;如果想要校验xml的约束,需要使用工具(myeclipse工具)
- 打开myeclipse开发工具,创建一个项目
- 在项目的src目录下面创建一个xml文件和一个dtd文件
- 当xml中引入dtd文件之后,自动校验
DTD的引入方式(3种)
-
引入外部的dtd文件:
<!DOCTYPE 根元素名称 SYSTEM "dtd路径">
-
使用内部的dtd文件:
<!DOCTYPE 根元素名称 [dtd代码]>
-
使用外部的dtd文件(网络上的dtd文件):
<!DOCTYPE 根元素名称 PUBLIC “dtd名称 "dtd文档的url">
(后面框架struts2 使用配置文件 使用外部的dtd文件)
使用DTD定义元素
- 语法格式:
<!ELEMENT 元素名 约束>
- 简单元素:没有子元素的元素
<!ELEMENT name (#PCDATA)>
- (#PCDATA):约束name是字符串类型
- EMPTY:元素为空(没有内容)
- ANY:任意
- 复杂元素:
<!ELEMENT 元素名称 (子元素1,子元素2,……)>
子元素只能出现一次- 表示子元素出现的次数
- +:表示一次或者多次
- ?:表示零次或者一次
- *:表示零次或者多次
- 子元素之间使用逗号隔开,表示元素的出现顺序
- 子元素用竖线(|)隔开,表示只能出现其中的任意一个
使用DTD定义属性
-
语法:
<!ATTLIST 元素名称
属性名称 属性类型 属性的约束
>
-
属性类型
- CDATE:字符串
- 枚举:表示只能在一定的范围内出现值,每次只能出现其中的一个(aa|bb|cc)
- ID:值只能是字母或下划线开头
-
属性约束
-
#REQUIRED:属性必须存在
-
#IMPLIED:属性可有可无
-
#FIXED:表示一个固定值
#FIXED “*”
属性的值必须是设置的这个固定值 -
直接值:
- 不写属性:使用直接值
- 写了属性:使用设置的那个值
-
定义实体
- 语法:
<!ENTITY 实体名称 "实体的值">
- 使用实体:
&实体名称;
- 注意:定义实体需要写在内部的dtd中;如果写在外部的dtd里面,在某些浏览器下,内容得不到
XML解析值JAXP(SUN公司官方提供的API)
XML解析简介(写到Java代码)
- xml是标记型文档
- js使用dom解析标记型文档,根据html的层级结构,在内存中分配一个树形结构,把html的标签、属性和文本都封装成对象
- document对象、element对象、属性对象、文本对象、Node节点对象
- xml的解析方式(技术):dom和sax
- dom方式解析:根据xml的层级结构,在内存中分配一个树形结构,把xml中标签、属性和文本都封装成对象
- 缺点:如果文件过大,造成内存溢出
- 优点:很方便实现增删改操作
- sax解析:采用事件驱动,边读边解析。从上到下,一行一行的解析,解析到某一个对象,返回对象名称
- 优点:不会造成内存溢出,可实现查询
- 缺点:不能实现增删改操作
- 想要解析xml,需要解析器。
- 不同的公司和组织提供了针对dom和sax方式的解析器,通过api方式提供
- sun公司提供了针对dom和sax解析器:jaxp
- dom4j组织针对dom和sax解析器:dom4j(实际开发中最多的)
- jdom组织针对dom和sax解析器:jdom
- 不同的公司和组织提供了针对dom和sax方式的解析器,通过api方式提供
JAXP API的查看
-
jaxp是javase的一部分
-
jaxp解析器在jdk的java.xml.parsers包里面
-
有四个类,分别是针对dom和sax解析的类
-
dom:
-
DocumentBuilder:解析器类
-
这个类是一个抽象类,不能new
此类的实例可以从DocumentBuilderFactory.newDocumentBuilder()方法获取
-
一个方法,可以解析xml:parse(“xml路径”),返回是Document整个文档
-
返回的document是一个接口,父节点是Node,如果在document里面找不到想要的方法,到Node里面去找
-
在doucument里面有方法
-
getElementByTagName(String tagname)
- 这个方法可以得到标签
- 返回集合NodeList
-
createElement(String tagname)
- 创建标签
-
createTextNode(String data)
- 创建文本
-
appendChild(Node newChild)
- 把文本添加到标签下面
-
removeChild(Node oldChild)
- 删除节点
-
getParentNode()
- 获取父节点
-
NodeList
- getLength() 得到集合的长度
- item(int index) 下标取到具体的值
遍历:
for(int i=0;i<list.getLength();i++){ list.item(i); }
-
getTextContent()
- 得到标签里面的内容
-
-
-
DocumentBuilderFactory:解析器工厂
-
这个类也是一个抽象类,不能new
采用newInstance()获取DocumentBuilderFactory的实例
-
-
-
sax:
- SAXParser:解析器类
- SAXParserFactory:解析器工厂
-
-
使用JAXP查询节点
- 查询xml中某一元素的所有值
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 得到所有元素
- 返回集合,遍历集合,得到每一个元素的值
public static void selectAll()
throws ParserConfigurationException, SAXException, IOException
{
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder bulider = builderFactory.newDocumentBuilder();
Document document = bulider.parse("xml路径");
NodeList list = document.getElementByTagName("标签名称");
for(int i=0;i<list.getLength();i++)
{
Node name = list.item(i);
String str = name.getTextContent();
System.out.println(str);
}
}
使用JAXP查询某一个节点
- 查询xml中某一元素的某一个值
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 得到所有元素
- 返回集合,利用方法item,下标获取具体的元素
- 得到具体的值,使用getTextContent方法
public static void selectSin()
throws ParserConfigurationException, IOException, SAXException
{
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder doucumentBuilder = builderFactory.newDocumentBuilder();
final Document document = documentBuilder.parse("xml路径");
NodeList list = document.getElementsByTagName("标签名称");
Node name = list.item(标签位置-1);
System.out.println(name.getTextContent());
}
使用JAXP添加节点
- 在第n个A标签后(末尾)添加B标签
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 得到第n个A标签
- 得到所有的A标签,使用item方法下标得到
- 创建B标签 createElement
- 创建文本 createTextNode
- 把文本添加到B标签下面 appendChild
- 把B标签添加到第n个A标签下面 appendChild
- 回写xml
public static void addTag()
throws ParserConfigurationException, IOException, SAXException, TransformerException
{
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse("xml路径");
NodeList list = document.getElementsByTagName("A");
Node p = list.item(n-1);
Element tag = document.createElement("B");
Text text = document.createTextNode("B的内容");
tag.appendChild(text);
p.appendChild(tag);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document),
new StreamResult("xml路径"));
}
- 此方法添加节点,格式有些混乱
使用JAXP修改节点
- 修改第n个A标签下面的B的内容
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 得到B标签 item方法
- 修改B标签内的值 setTextContent方法
- 回写xml
public static void modifyTag()
throws ParserConfigurationException, IOException, SAXException, TransformerException {
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse("xml路径");
Node tag = document.getElementsByTagName("B").item(n-1);
tag.setTextContent("修改内容");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document),
new StreamResult("xml路径"));
}
使用JAXP删除节点
- 删除第n个B标签
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 获取B标签
- 获取B的父节点 getParentNode()方法
- 利用父节点删除B removeChild方法
- 回写xml
public static void delTag()
throws ParserConfigurationException, IOException, SAXException, TransformerException {
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse("xml路径");
Node tag = document.getElementsByTagName("B").item(n-1);
Node p = tag.getParentNode();
p.removeChild(tag);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document),
new StreamResult("xml路径"));
}
使用JAXP遍历节点
- 把xml中的所有元素名称打印出来
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 得到根节点
- 得到根节点的子节点
- ……递归
public static void listElement()
throws ParserConfigurationException, IOException, SAXException
{
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse("xml路径");
list(document);
}
private static void list(Node node) {
if(node.getNodeType() == Node.ELEMENT_NODE)
{
System.out.println(node.getNodeName());
}
NodeList list = node.getChildNodes();
for(int i=0;i<list.getLength();i++)
{
Node node1 = list.item(i);
list(node1);
}
}
Schema:基于XML的DTD代替者
Schema的介绍
- schema符合xml的语法,xml语句
- 一个xml中可以有多个schema,多个schema使用名称空间区分(类似于Java中的包名)
- dtd里面有PCDATE类型,但在schema里面可以支持更多的数据类型
- schema的约束更加严格,语法更加复杂,目前不能替代dtd
Schema的开发过程
-
在< schema >文件里面是有W3C提供的属性和标签,约束xml文件
-
创建一个schema文件 后缀名是.xsd
-
要有xml文档声明
-
根节点< schema > 属性:
-
xmlns=“http://www.w3.org/2001/XMLSchema”
表示当前xml文件是一个约束文件
-
targetNamespace=“http://www.itcast.cn/20151111”
使用schema约束文件,直接通过这个地址引入约束文件
-
elementFormDefault=“qualified”
-
步骤:
-
看xml中有多少个元素,写几个< element name=“ ” >
-
看简单元素和复杂元素
-
复杂元素
<element name=""> <complexType> <sequence> 子元素 </sequence> </complexType> </element>
- < sequence >:表示元素出现的顺序
- < all >:表示元素只能出现一次
- < choice >:元素只能出现其中的一个
-
简单元素:写在复杂元素里
<element name="" type=""></element>
- < maxOccurs=“unbounded” >:表示元素出现的次数
-
<any></any>
:表示任意元素
-
-
在被约束文件里面引入约束文件
<根元素 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.itcast.cn/20151111" xsi:schemaLocation="http://www.itcast.cn/20151111 schema路径">
-
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
表示xml是一个被约束文件
-
xmlns=“http://www.itcast.cn/20151111”
是约束文档里面的targetNamespace
-
xsi:schemaLocation=“http://www.itcast.cn/20151111 schema路径”>
targetNamespace 空格 约束文档的路径
-
-
Schema约束API查看
- 用schema约束属性
- 写在复杂元素里面
- 写在< /complexType >上一行
<attribute name="属性名称" type="属性类型" use="属性是否必须出现"></attribute>
- 复杂的schema约束
- 引用多个schema文件,可以给每个起一个别名
- 在使用时通过 < 别名:标签名 >< /别名:标签名>
sax解析的过程
- 事件驱动,边读边解析
- 在java.xml.parsers包里面,有两个类
- SAXParser:解析器
- 抽象类,通过SAXParserFactory.newSAXParser()方法获得
- 方法:
- parse(File f,DefaultHandler dh)
- 第一个参数是xml的路径
- 第二个参数是事件处理器,当把时间处理器传递进来,相当于在方法里面绑定了一个事件
- startElement(Stirng url,String localName,String qName,Attributes attributes)
- 开始标签自动执行
- qName:把标签名称返回
- characters(char[] ch,int start,int length) //String的构造方法
- 文本自动执行
- 返回文本内容
- endElement(String url,String localName,String qName)
- 结束标签自动执行
- qName:把标签名称返回
- startElement(Stirng url,String localName,String qName,Attributes attributes)
- parse(File f,DefaultHandler dh)
- SAXParserFactory:解析器工厂
- 抽象类,实例通过newInstance()方法得到
- SAXParser:解析器
- sax的解析过程
- 当解析到开始标签时,自动执行startElement方法
- 当解析到文本时,自动执行characters方法
- 当解析到结束标签时,自动执行endElement方法
使用jaxp的sax方式操作xml
-
sax方式不能实现增删改操作,只能实现查询操作
-
查询步骤
- 创建解析器工厂
- 创建解析器
- 执行parse方法
- 自己创建一个类,继承DefaultHandler
- 重写类里面的三个方法
public static void CheckAll() throws ParserConfigurationException, SAXException, IOException { SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParser saxParser = saxParserFactory.newSAXParser(); saxParser.parse("xml路径",new MyDefault()); } class MyDefault extends DefaultHandler{ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { TODO } @Override public void characters(char[] ch, int start, int length) throws SAXException { TODO } @Override public void endElement(String uri, String localName, String qName) throws SAXException { TODO } }
-
打印出整个文档
class MyDefault1 extends DefaultHandler{
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
{
System.out.print("<"+qName+">");
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException
{
System.out.print(new String(ch,start,length));
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException
{
System.out.print("</"+qName+">");
}
}
- 获取所有A标签的值
- 定义一个成员变量flag=false
- 判断开始方法是否是A元素,如果是flag=true
- 如果flag是true,在characters方法里面打印内容
- 当执行到结束方法时,把flag设置成false
- 定义一个成员变量flag=false
class MyDefault2 extends DefaultHandler{
boolean flag = false;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
{
if("A".equals(qName))
{
flag = true;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException
{
if(flag == true)
{
System.out.println(new String(ch,start,length));
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException
{
if("A".equals(qName))
{
flag =false;
}
}
}
- 获取第n个A标签的值
- 定义一个成员变量idex=0
- 在开始方法时,判断自增
- 在characters方法中判断flag和idex,再打印
- 定义一个成员变量idex=0
class MyDefault2 extends DefaultHandler{
boolean flag = false;
int idex=0;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
{
if("A".equals(qName))
{
flag = true;
idex ++;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException
{
if(flag == true && idex==n)
{
System.out.println(new String(ch,start,length));
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException
{
if("A".equals(qName))
{
flag =false;
}
}
}
XML解析之dom4j
dom4j的简介
-
dom4j是一个组织,针对xml解析,提供解析器dom4j
-
dom4j不是javase的一部分,
-
在使用时要先导入dom4j提供的jar包
- src下创建文件夹lib
- 复制jar包到lib下
- project structure>>module>>dependencies>>+jar包路径
-
得到doucument
SAXReader reader = new SAXReader(); Document document = reader.read(url);
-
document的父接口是Node
如果在document里面找不到想要的方法,到Node里面去找
-
doucument里面的方法:getRootElement():获取根节点,返回的是Element
-
Element也是一个接口,父接口是Node
- Element和Node里面的方法:
- getParent():获取父节点
- addElement():添加一个标签
- Element和Node里面的方法:
-
-
使用dom4j实现查询xml操作
-
解析是从上到下进行解析的
-
方法:
- element(qname)
- 表示获取标签下面的第一个子标签
- qname:标签的名称
- elements(qname)
- 获取标签下面是这个名称的所有子标签(一层)
- qname:标签名称
- elements()
- 获取标签下面的所有一层子标签
- element(qname)
-
查询所有A元素里面的值
- 创建解析器
- 得到document
- 得到根节点 getRootElement(),返回Element
- 得到的根节点的子节点
- elements(qname)
- 返回list集合
- 遍历
- elements(qname)
- ……得到A标签
- 在其父标签下执行element(qname)方法,返回Element
- 得到A标签的值
- getText方法得到值
public static void selectTag() throws DocumentException { SAXReader saxReader = new SAXReader(); Document document = saxReader.read("xml路径"); Element root = document.getRootElement(); List<Element> list = root.elements("A标签的父标签"); for(Element element : list) { Element name1 = element.element("A"); String str = name1.getText(); System.out.println(str); } }
-
查询第n个A元素的值
- 创建解析器
- 得到document
- 得到根节点 getRootElement(),返回Element
- 得到的根节点的第n个子节点
- 使用list下标得到
- ……得到A标签
- 在其父标签下执行element(qname)方法,返回Element
- 得到A标签的值
- getText方法得到值
public static void selectSin() throws DocumentException { SAXReader saxReader = new SAXReader(); Document document = saxReader.read("xml路径"); Element root = document.getRootElement(); List<Element> list = root.elements("A的父元素 "); Element name = list.get(n-1).element("A"); String str = name.getText(); System.out.println(str); }
使用dom4j实现在末尾添加节点的操作
-
在第n个A标签末尾添加B元素
- 创建解析器
- 得到document
- 得到根节点
- 获取到A标签 elements方法
- 在A标签下添加元素 addElement方法,返回一个Element
- 在添加完成之后的元素下面添加文本 addTest方法
- 回写
- 格式化 OutputFormat,使用createPrettyPrinter方法,表示一个漂亮的格式
- 使用类XMLWriter 直接new这个类,传递两个参数
- 第一个参数是xml文件路径 new FileOutputStream(“路径”)
- 第二个参数是格式化类的值
public static void addTag() throws DocumentException, IOException { SAXReader saxReader = new SAXReader(); Document document = saxReader.read("xml路径"); Element root = document.getRootElement(); List<Element> list = root.elements("A"); Element TagName = list.get(n-1).addElement("B"); TagName.addText("B的内容"); OutputFormat fomcat =OutputFormat.createPrettyPrint(); XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("xml路径"),fomcat); xmlWriter.write(document); xmlWriter.close(); }
使用dom4j实现在待定位置添加节点的操作
-
在第n个A标签下的B标签前添加C标签
- 创建解析器
- 得到document
- 得到根节点
- 获取到A标签 elements方法
- 获取A标签下的所有元素
- elements()方法,返回list集合
- 使用list里面的方法,在特定位置添加元素
- 创建元素,在元素下创建文本
- add(int index,E element)
- 第一个元素是位置下标,从0开始
- 第二个参数是要添加的元素
- 回写xml
public static void addTagBefore() throws DocumentException, IOException { SAXReader saxReader = new SAXReader(); Document document = saxReader.read("xml路径"); Element root = document.getRootElement(); List<Element> list = root.elements("A"); List<Element> list1 = list.get(n-1).elements(); Element TagName = DocumentHelper.createElement("C"); TagName.setText("C的内容"); list1.add(B标签的位置,TagName); OutputFormat format = OutputFormat.createPrettyPrint(); XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("xml路径"),format); xmlWriter.write(document); xmlWriter.close(); }
dom4j里面封装方法的操作
- 可以对得到document的操作和回写xml的操作,都封装成方法
- 也可以把传递的文件路径,封装成一个常量
- 封装的好处:
- 可以提高开发速度
- 可以提高代码的可维护性
使用dom4j实现修改的操作
-
修改第n个A标签下B元素的值
- 得到document
- 得到根节点
- 得到第n个A元素 elements方法
- 得到A元素下的B元素
- 修改值 setText方法
- 回写xml
public static void modifyTag() throws DocumentException, SAXException, IOException { Document document = Dom4jUtils.getDocument(PATH); Element root = document.getRootElement(); List<Element> list = root.elements("A"); Element TagName = list.get(n-1).element("B"); TagName.setText("修改值"); Dom4jUtils.xmlWriters(PATH,document); }
使用dom4j实现删除节点的操作
-
删除第n个A标签下的B元素
- 得到document
- 得到根节点
- 得到第n个A元素 elements方法
- 得到A元素下的B元素
- 删除(使用A标签删除B标签)
- 得到B的父节点
- 直接用A
- 使用方法getParent得到
- 删除操作
- 在A标签上执行remove方法
- 得到B的父节点
- 回写xml
public static void delTag() throws DocumentException, SAXException, IOException { Document document = Dom4jUtils.getDocument(PATH); Element root = document.getRootElement(); List<Element> list = root.elements("A"); Element TagName = list.get(n-1).element("B"); list.get(n-1).remove(TagName); Dom4jUtils.xmlWriters(PATH,document); }
使用dom4j实现获取属性值的操作
-
获取第n个A标签里面的属性B的值
- 得到document
- 得到根节点
- 得到第n个A元素
- 得到A元素里面的属性值
- 使用attributeValue("")方法
- 在A元素上执行这个方法,里面的参数是属性名称
public static void getValues() throws DocumentException, SAXException { Document document = Dom4jUtils.getDocument(PATH); Element root = document.getRootElement(); List<Element> list = root.elements("A"); String value = list.get(n-1).attributeValue("B"); System.out.println(value); }
XPATH
XPATH简介
- 可以直接获取到某个元素‘
- 是一种书写形式(表达式)
- 第一种书写形式:
/AAA/DDD/BBB/
- 表示一层一层的,AAA下面DDD下面BBB
- 第二种书写形式:
//BBB
- 表示和这个名称相同,表示只要名称是BBB,都得到
- 第三种书写形式:
/*
- 表示所有元素
- 第四种形式
- BBB[1]:表示第一个BBB元素
- BBB[last]:表示最后一个BBB元素
- 第五种形式
//BBB[@id]
- 表示只要BBB上有id属性,都得到
- 第六种形式
//BBB[@id='a']
- 表示元素名称是BBB,在BBB上面有id属性,且id属性的值是a
使用dom4j支持XPATH的操作
-
默认情况下,dom4j不支持xpath
-
如果想要在dom4j中使用xath
- 第一步需要引入支持xpath的jar包,使用jaxen-1.1-beta-6.jar
- 需要把jar包导入到项目中
- 第一步需要引入支持xpath的jar包,使用jaxen-1.1-beta-6.jar
-
在dom4j里面提供了两个方法,用来支持xpath
- selectNodes(“xpath表达式”)
- 获取多个节点
- selectSingleNode(“xpath表达式”)
- 获取一个节点
- selectNodes(“xpath表达式”)
-
使用xpath实现,查询xml中所有A元素的值
- 得到所有的document
- 所有A元素的xpath表示://A
- 使用selectNodes("//A")
public static void selectAll() throws DocumentException, SAXException { Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH); List<Node> list = document.selectNodes("//A"); for (Node node : list) { String str = node.getText(); System.out.println(str); } }
-
使用xpath实现:获取第1个A标签下B标签的值
- 得到document
- 第1个A标签下B标签的xpath表示://A[1]/B
- 使用selectSingleNode("//A[1]/B")
public static void selectSin() throws DocumentException, SAXException { Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH); Node node = document.selectSingleNode("//A[1]/B"); String str = node.getText(); System.out.println(str); }
案例
- 使用xml当做数据库,存储学生信息
- 创建一个xml文件,写一些学生信息
学生管理系统实现-添加操作
- 创建解析器
- 得到document
- 获取到根节点
- 在根节点上面创建stu标签
- 在stu标签上面依次添加 id name age
- 在id name age上面依次添加值
- 回写xml
学生管理系统实现-删除操作
-
根据学生的id删除
-
创建解析器
-
得到document
-
获取所有id
使用xpath //id 返回list集合
-
遍历list集合
-
判断集合里面的id和传递的id是否相同
-
如果相同,把id所在的stu删除
-
学生管理系统实现-查询操作
-
根据id进行查询
-
创建解析器
-
得到document
-
获取所有id
使用xpath //id 返回list集合
-
遍历list集合
-
得到每一个id的节点
-
id节点的值
-
判断集合里面的id和传递的id是否相同
-
如果相同,先获取到id的父节点stu
-
通过stu获取到name age的值
-