什么是xml
xml(extensible markup language),可扩展标记语言,是一种简单的基于文本的语言,旨在以村文本格式存储和传输数据,他代表可扩展标记语言。
- 1、作为系统的配置文件
- 2、作为一种特殊的数据结构,在网络中进行传输
特点
xml与操作系统、编程语言的开发平台无关
实现不同系统之间的数据交换
xml作用
- 数据交互
- 配置应用程序和网站
- ajax基石
xml的编写语法
基本语法
- 所有xml元素都必须有结束标签
- xml标签对大小写敏感
- 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>注意一:<?xml version="1.0" encoding="utf-8" ?>这行是必须要写的,且必须放在首行(前面有注释都不行)。表示版本为1.0,以utf-8字符集来编码
- 注意二:根标签只能有一个,子标签可以有多个
- 注意三:标签是成对存在的,记得嵌套正确
xml文件可以在浏览器中查看,我们打开浏览器看到,我们写的特殊字符的格式是我们所预期的


特殊字符编写
1、 指定字符替代特殊字符
xml中书写”<’
“&”等,可能会出现冲突,导致报错,此时可以用如下特殊字符替代。
| 指定字符 | 特殊字符 | 含义 |
|---|---|---|
| < | < | 小于 |
| > | > | 大于 |
| & | & | 小于 |
| ' | ’ | 单引号 |
| " | " | 双引号 |
2、cdata的数据区
xml中可以写一个叫cdata的数据区:<![cdata[..内容... ]]>,里面的内容可以随便写
<users>
<user id="1">
<name>张三</name>
<age>18</age>
<address>广州</address>
</user>
<userattribute>都是爱学习的人</userattribute>
<user id="2">
<name>李四</name>
<age>25</age>
<address>哈尔滨</address>
</user>
<!--以下是带有大于号小于号等特殊字符的写法-->
<special>
<![cdata[
5 > 2 && 3 < 5
]]>
</special>
<!--特殊字符用法二-->
<special> 5 > 2 && 3 < 5 </special>
</users>

约束xml的书写格式
dtd文档
特点
- 可以约束xml文件的编写
- 不能约束具体的数据类型
dtd文档的使用
①:编写dtd约束文档,后缀必须是.dtd
data.dtd
根目录只能叫做书并且可以有多个书的子元素
书只能由书名作者售价构成
<!element 书架 (书+)> <!element 书 (书名,作者,售价)> <!element 书名 (#pcdata)> <!element 作者 (#pcdata)> <!element 售价 (#pcdata)>
②:在需要编写的xml文件中导入该dtd约束文档
<!doctype 书架 system "data.dtd">
③:然后xml文件,就必须按照dtd约束文档指定的格式进行编写,否则报错
<?xml version="1.0" encoding="utf-8"?>
<!-- 导入约束格式 -->
<!doctype 书架 system "data.dtd">
<书架>
<!-- 只能这么写否则报错 -->
<书>
<书名>哈利波特</书名>
<作者>j.k.罗琳</作者>
<!-- 售价的类型可以是浮点型,字符串,也可以是任何数据类型 -->
<售价>49.9</售价>
</书>
<书>
<书名>西游记</书名>
<作者>吴承恩</作者>
<售价>49.9</售价>
</书>
</书架>schema文档
特点
- 可以约束xml文件的编写
- 可以约束具体的数据类型
schema文档的使用
1、编写schema约束文档,后缀必须是.xsd,具体的形式到代码中观看。
2、在需要编写的xml文件中导入该schema约束文档
3、按照约束内容编写xml文件的标签
<?xml version="1.0" encoding="utf-8"?>
<!-- xmlns: 核心命名空间声明 -->
<!-- xmlns="http://www.w3.org/2001/xmlschema:
声明使用w3c xml schema规范作为默认命名空间,所有未加前缀的标签均属于该规范。 -->
<!-- targetnamespace(目标命名空间): 申明约束文档的地址(命名空间) 这里的data.xsd也是被约束的 -->
<!-- elementformdefault(元素命名空间规则): 先不用管,这是关于局部元素的命名空间归属的属性-->
<schema xmlns="http://www.w3.org/2001/xmlschema"
targetnamespace="http://www.itcast.cn"
elementformdefault="qualified" >
<!--全局元素定义,作为根元素,该元素直接属于targetnamespace命名空间-->
<element name="书架">
<complextype>
<!-- maxoccurs="unbounded" 书架下的子元素可以有无穷多个 -->
<sequence maxoccurs="unbounded">
<element name="书">
<!-- 写子元素 -->
<complextype>
<sequence>
<element name="书名" type="string"/>
<element name="作者" type="string"/>
<element name="价格" type="double"/>
</sequence>
</complextype>
</element>
</sequence>
</complextype>
</element>
</schema>
属性命名空间
<?xml version="1.0" encoding="utf-8"?>
<batchcompany xmlns="http://www.aptech_edu.ac"
xmlns:tea="http://www.tea.org">
<batch-list>
<!-- 下面这个命名空间属于xmlns:tea="http://www.aptech_edu.ac" -->
<batch type="thirdbatch">第三批次</batch>
<!-- 下面这个命名空间属于xmlns:tea="http://www.tea.org" -->
<batch tea:type="thirdbatch">第三批茶</batch>
<!-- 下面这个命名空间属于xmlns:tea="http://www.aptech_edu.ac" -->
<batch>午班批次</batch>
</batch-list>
</batchcompany>除非带有前缀,否则属性属于所属的元素的命名空间
xml命名空间的作用
解决在复杂、大型xml文件中,出现名称相同,但是含义不同的元素
<?xml version="1.0" encoding="utf-8"?>
<!-- 两个厂家(佳能相机和尼康相机)的地址 -->
<cameras xmlns:canon="http://www.canon"
xmlns:nikon="http://www.nikon.com">
<!-- 虽然都是相机camera
但是第一个是canon(佳能牌)的相机
第二个是nikon(尼康牌)的相机
-->
<canon:camera prodid="p663" name="camera傻瓜相机"/>
<nikon:camera prodid=“k29b3” name=“camera超级35毫米相机"/>
</cameras>解析xml的方法
本节分三块
dom(内置解析xml)
- 基于xml文档树结构的解析
- 适用于多次访问的xml文档
- 特点:比较消耗资源
sax(内置解析xml)
- 基于事件的解析
- 适用于大数据量的xml文档
- 特点:占用资源少,内存消耗小
dom4j
- 非常优秀的java xml api
- 性能优异、功能强大
- 开放源代码
dom解析xml
基于xml文档树结构的解析
适用于多次访问的xml文档
特点:比较消耗资源
dom介绍
文档对象模型(document object model)
dom把xml文档映射成一个倒挂的树

dom解析包:org.w3c.dom
org.w3c.dom 是 java 中用于处理 文档对象模型(dom) 的核心包,由 万维网联盟(w3c) 制定并维护。它是 w3c dom 标准的 java 语言绑定实现,主要用于解析、访问和操作 xml/html 文档的结构化内容。(jdk自带的用于解析xml文件的api)
常用接口
| 常用接口 | 常用方法 | 说明 |
|---|---|---|
| document:表示整个 xml 文档 | nodelist getelementsbytagname(string tag) | 按文档顺序返回文档中指定标记名称的所有元素集合 |
| element createelement(string tagname) | 创建指定标记名称的元素 | |
| node:该文档树中的单个节点 | nodelist getchildnodes() | 获取该元素的所有子节点,返回节点集合 |
| element:xml 文档中的一个元素 | string gettagname() | 获取元素名称 |
dom解析包的使用
dom解析xml文件步骤
- 创建解析器工厂对象
- 解析器工厂对象创建解析器对象
- 解析器对象指定xml文件创建document对象
- 以document对象为起点操作dom树
<?xml version="1.0" encoding="utf-8"?>
<phoneinfo>
<brand name="华为">
<type name="u8650"/>
<type name="hw123"/>
<type name="hw321"/>
</brand>
<brand name="苹果">
<type name="iphone4"/>
</brand>
</phoneinfo>显示phoneinfo.xml文件中收藏的手机品牌和型号
package com.hsh.exercise2;
import org.w3c.dom.document;
import org.w3c.dom.element;
import org.w3c.dom.nodelist;
import javax.xml.parsers.documentbuilder;
import javax.xml.parsers.documentbuilderfactory;
public class main {
public static void main(string[] args) throws exception {
// 创建解析器工厂对象
documentbuilderfactory factory = documentbuilderfactory.newinstance();
// 解析器工厂对象创建解析器对象
documentbuilder db = factory.newdocumentbuilder();
// 解析 xml 文件
document document = db.parse("./src/com/hsh/exercise2/phoneinfo.xml");
// 获取根元素
element root = document.getdocumentelement();
// 获取所有 brand 元素
nodelist brandlist = root.getelementsbytagname("brand");
// 遍历每个 brand 节点并打印 name 属性
for (int i = 0; i < brandlist.getlength(); i++) {
// 获取 brand 元素
element brand = (element) brandlist.item(i);
// 获取节点名称
system.out.print(brand.getnodename()+": ");
// 获取 name 属性
system.out.print(brand.getattribute("name")+",");
// 获取节点文本内容 由于是单标签所以为空。
// system.out.println(brand.gettextcontent());
// 获取brand 元素下面的 type 元素
nodelist typelists = brand.getelementsbytagname("type");
for (int j = 0; j < typelists.getlength(); j++) {
// 获取 type 元素
element type = (element) typelists.item(j);
// 获取节点名称
system.out.print(type.getnodename()+": ");
// 获取 name 属性
system.out.print(type.getattribute("name")+" ");
}
system.out.println();
}
// 输出结果
// brand: 华为,type: u8650 type: hw123 type: hw321
// brand: 苹果,type: iphone4
}
}保存xml文件
步骤
- 获得transformerfactory对象
- 创建transformer对象
- 创建domsource对象:包含xml信息
- 设置输出属性:编码格式
- 创建streamresult对象:包含保存文件的信息
- 将xml保存到指定文件中
package com.hsh.exercise3;
import org.w3c.dom.document;
import org.w3c.dom.element;
import org.w3c.dom.bootstrap.domimplementationregistry;
import org.w3c.dom.ls.domimplementationls;
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 main {
public static void main(string[] args) throws exception {
//1. 创建工厂transformerfactory对象
transformerfactory factory = transformerfactory.newinstance();
//2. 创建transformer对象
transformer transformer = factory.newtransformer();
// 3. 创建document对象来创建新的xml文件,给xml文件设置内容,并将dom结构添加到domsource对象
// 3.1 创建document对象
documentbuilderfactory documentfactory = documentbuilderfactory.newinstance();
documentbuilder builder = documentfactory.newdocumentbuilder();
document document = builder.newdocument();
// 3.2 创建xml结构(即给xml文件设置内容)
// 创建根元素
element root = document.createelement("root");
// 加入到document中
document.appendchild(root);
// 创建子元素
element child = document.createelement("child");
// 设置属性名和属性值
child.setattribute("name", "hsh");
// 设置元素内容
child.appendchild(document.createtextnode("text content"));
//加入根节点树中
root.appendchild(child);
// 3.3 将文件添加到domsource对象中
domsource source = new domsource(document);
// 4. 给第二步 的transformer对象设置输出属性
// 4.1设置是否再xml中添加缩进
transformer.setoutputproperty(outputkeys.indent,"yes");
// 4.2指定输出方法
transformer.setoutputproperty(outputkeys.method, "xml");
// 4.3指定输出文件编码
transformer.setoutputproperty(outputkeys.encoding, "utf-8");
// 5. 创建streamresult对象,指定输出文件 streamresult对象包含了文件信息
streamresult result = new streamresult("./src/com/hsh/exercise3/collection.xml");
// 6. 将domsource对象和streamresult对象作为参数传递给transformer对象的transform方法进行保存
transformer.transform(source, result);
system.out.println("保存成功!");
}
}保存后的文件如下
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<root>
<child name="hsh">text content</child>
</root>添加dom节点
添加手机收藏
- 添加新的brand:三星
- 给brand节点添加新的子标签type:note4
- 将brand添加到dom树中
练习:给手机收藏信息xml中添加新的手机信息,并将手机收藏信息保存到新文件中
添加新的brand:三星
给brand节点添加新的子标签type:note4
将brand添加到dom树中
package com.hsh.exercise3;
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 main {
public static void main(string[] args) throws exception {
// 创建解析器工厂对象
documentbuilderfactory factory = documentbuilderfactory.newinstance();
documentbuilder db = factory.newdocumentbuilder();
document document = db.parse("./src/com/hsh/exercise3/收藏信息.xml");
// 获取根元素
element root = document.getdocumentelement();
system.out.println(root.getnodename());
// 给根元素添加子元素brand
element brand = document.createelement("brand");
brand.setattribute("name","三星");
// 给brand 元素添加子元素type
element type = document.createelement("type");
// 设置type的属性
type.setattribute("name","note4");
// 将type添加到brand中
brand.appendchild(type);
root.appendchild(brand);
// 创建工厂进行保存
transformerfactory transformerfactory = transformerfactory.newinstance();
transformer transformer = transformerfactory.newtransformer();
// 设置格式化
// 缩进
transformer.setoutputproperty(outputkeys.indent, "yes");
// 指定输出
transformer.setoutputproperty(outputkeys.method, "xml");
// 指定编码
transformer.setoutputproperty(outputkeys.encoding, "gb2312");
domsource domsource = new domsource(document);
streamresult streamresult = new streamresult("./src/com/hsh/exercise3/收藏信息.xml");
transformer.transform(domsource, streamresult);
system.out.println("保存成功");
}
}修改/删除dom节点
给所有的brand标签添加id属性
- 获取brand标签
- 调用setattribute()方法添加属性
删除brand值为“华为”的标签
- getelementsbytagname()方法获取brand标签列表
- 获得brand值为“华为”的标签对象
- 通过getparentnode()方法获得父节点对象
- 调用父节点的removechild()方法删除节点
<?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>
<brand name="三星">
<type name="note4"/>
</brand>
</phoneinfo>package com.hsh.exercise4;
import org.w3c.dom.document;
import org.w3c.dom.element;
import org.w3c.dom.nodelist;
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 main {
public static void main(string[] args) throws exception {
// 创建解析器工厂对象
documentbuilderfactory factory = documentbuilderfactory.newinstance();
documentbuilder db = factory.newdocumentbuilder();
document document = db.parse("./src/com/hsh/exercise4/收藏信息.xml");
// 获取根元素
element root = document.getdocumentelement();
system.out.println(root.getnodename());
// 获取root所有brand子级标签
nodelist nodelist = root.getelementsbytagname("brand");
for (int i = 0; i < nodelist.getlength(); i++) {
// 给每一个brand标签加属性
element brand = (element) nodelist.item(i);
brand.setattribute("id", (i+1)+"");
}
// 遍历子级标签删除 brand的属性为华为的标签
for (int i = 0; i < nodelist.getlength(); i++) {
element brand = (element) nodelist.item(i);
if (brand.getattribute("name").equals("华为")) {
// 得到父元素
element parent = (element) brand.getparentnode();
// 删除
parent.removechild(brand);
}
}
// 创建工厂进行保存
transformerfactory transformerfactory = transformerfactory.newinstance();
transformer transformer = transformerfactory.newtransformer();
// 设置格式化
// 缩进
transformer.setoutputproperty(outputkeys.indent, "yes");
// 指定输出
transformer.setoutputproperty(outputkeys.method, "xml");
// 指定编码
transformer.setoutputproperty(outputkeys.encoding, "gb2312");
domsource domsource = new domsource(document);
streamresult streamresult = new streamresult("./src/com/hsh/exercise4/收藏信息.xml");
transformer.transform(domsource, streamresult);
system.out.println("保存成功");
}
}结果如下。
<?xml version="1.0" encoding="gb2312" standalone="no"?>
<phoneinfo>
<brand id="2" name="苹果">
<type name="iphone4"/>
</brand>
<brand id="3" name="三星">
<type name="note4"/>
</brand>
</phoneinfo>sax
基于事件的解析
适用于大数据量的xml文档
特点:占用资源少,内存消耗小
dom4j
优点
- 非常优秀的java xml api
- 性能优异、功能强大
开放源代码
- document:定义xml文档
- element:定义xml元素
- text:定义xml文本节点
- attribute:定义了xml 的属性
dom4j下载和导入项目
1、下载相关jar包
方法一:去dom4j官网

2、将下载的jar包导入到idea项目中去


3、将jar包添加到库中

点击确定,打开lib出现如下界面就说明添加成功。

dom4j代码编写
获取所有值
解析器的构造方法
| 构造方法 | 说明 |
|---|---|
| public saxreader() | xml解析器对象 |
解析器对象中的方法
| 方法 | 说明 |
|---|---|
| public document read(string systemid) | 读取xml文件 |
document类中的方法
| 方法 | 说明 |
|---|---|
| element getrootelement(); | 获取根元素对象 |
| public string getname() | 获取元素标签名 |
| public string attributevalue(qname qname) | 获取元素的属性名 |
| public string gettext() | 获取元素的内容 |
| public list<element> elements() | 获取所有一级子标签 |
| public list elements(string name) | 获取所有一级子标签中的指定标签 |
| public element element(string name) | 获取一级子标签中的指定标签,若该标签有多个则获取第一个 |
<?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 com.hsh.exercise5;
import org.dom4j.document;
import org.dom4j.element;
import org.dom4j.io.saxreader;
import java.util.list;
public class main {
public static void main(string[] args) throws exception {
//创建一个dom4j提供的解析器对象
saxreader saxreader = new saxreader();
//将xml文件读取到我们的内存当中,获取到这个document 对象之后就可以读取里面的数据了
document document = saxreader.read("./src/com/hsh/exercise5/收藏信息.xml");
system.out.println("---获取根元素---");
//1、获取根元素对象里面的所有信息,下面根据这个根元素对象去获取想要的数据
element rootelement = document.getrootelement();
system.out.println(rootelement.getname());// phoneinfo
system.out.println("---获取所有一级子标签---");
//2、获取根元素里面的一级子元素
list<element> elements = rootelement.elements();
for (element element : elements){
// 获取标签名
system.out.println(element.getname());
// 获取属性值
system.out.println(element.attributevalue("name"));
// 获取标签内容 这是空,因为没有设置内容。
system.out.println(element.gettext());
}
// brand
// 华为
// brand
// 苹果
system.out.println("---获取所有一级子标签中的指定标签---");
//获取节点名称为books下所有子节点
list<element> elist = rootelement.elements("brand");
for (element element : elist){
system.out.println(element.getname());
}
// brand
// brand
system.out.println("---获取一级子标签中的指定标签---");
// 如果重复,则获取第一个
element element = rootelement.element("brand");
system.out.println(element.getname());// brand
}
}修改值和删除值
方法 | 说明 |
|---|---|
public node detach() | 删除dom元素(标签) |
public void setattributevalue(string name, string value) | 修改属性值 |
原文件
<?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 com.hsh.exercise5;
import org.dom4j.document;
import org.dom4j.element;
import org.dom4j.io.outputformat;
import org.dom4j.io.saxreader;
import org.dom4j.io.xmlwriter;
import java.io.filewriter;
import java.util.list;
public class delupdxml {
public static void main(string[] args) throws exception {
//创建一个dom4j提供的解析器对象
saxreader saxreader = new saxreader();
//将xml文件读取到我们的内存当中,获取到这个document 对象之后就可以读取里面的数据了
document document = saxreader.read("./src/com/hsh/exercise5/收藏信息.xml");
// 获取根元素对象
element rootelement = document.getrootelement();
system.out.println(rootelement.getname());
// 获取所有一级子标签
list<element> elements = rootelement.elements();
for (int i = 0; i < elements.size(); i++){
if(elements.get(i).attributevalue("name").equals("苹果")){
// 删除
elements.get(i).detach();
}else {
// 修改
elements.get(i).setattributevalue("name", "华为手机");
}
}
// 设置xml文件的格式
outputformat outputformat = outputformat.createprettyprint();
outputformat.setencoding("gb2312"); // 设置编码格式
// 写入xml文件的位置 以及指定的格式
xmlwriter xmlwriter=new xmlwriter(new filewriter("./src/com/hsh/exercise5/exercise.xml"),outputformat);
// 开始写入xml文件 写入document对象
xmlwriter.write(document);
xmlwriter.close();
}
}结果
<?xml version="1.0" encoding="gb2312"?>
<phoneinfo>
<brand name="华为手机">
<type name="u8650"/>
<type name="hw123"/>
<type name="hw321"/>
</brand>
</phoneinfo>添加值并保存文件
添加相关方法
| 方法 | 说明 |
|---|---|
| public static element createelement(string name) | 创建元素(标签) |
| element addattribute(string var1, string var2); | 设置元素的属性 |
| public void add(element element) | 添加元素()中是传入的子元素 |
保存文件相关方法
| 方法 | 说明 |
|---|---|
| public static outputformat createprettyprint() | 创建xml格式 |
| public xmlwriter(writer writer, outputformat format) | 参数分别是java的输出流和创建xml格式 |
| public void write(document doc) | 写入document对象 |
| public void close() | 关闭流 |
package com.hsh.exercise5;
import org.dom4j.document;
import org.dom4j.documenthelper;
import org.dom4j.element;
import org.dom4j.io.outputformat;
import org.dom4j.io.xmlwriter;
import java.io.filewriter;
public class writexml {
public static void main(string[] args) throws exception {
// 创建根元素对象
element rootelement = documenthelper.createelement("phoneinfo");
// 创建子元素
element brand = documenthelper.createelement("brand");
brand.addattribute("name","华为");
element type = documenthelper.createelement("type");
// 设置子元素的属性
type.addattribute("name","p10");
brand.add(type);
rootelement.add(brand);
// 创建document对象
document document = documenthelper.createdocument(rootelement);
// 设置xml文件的格式
outputformat outputformat = outputformat.createprettyprint();
outputformat.setencoding("gb2312"); // 设置编码格式
// 写入xml文件的位置 以及指定的格式
xmlwriter xmlwriter=new xmlwriter(new filewriter("./src/com/hsh/exercise5/exercise.xml"),outputformat);
// 开始写入xml文件 写入document对象
xmlwriter.write(document);
xmlwriter.close();
}
}// 输出结果
<?xml version="1.0" encoding="gb2312"?>
<phoneinfo>
<brand name="华为">
<type name="p10"/>
</brand>
</phoneinfo>案例:使用dom4j解析xml文件
- 显示手机收藏信息
- 保存手机收藏信息
- 为手机收藏信息添加新的节点
- 修改/删除手机收藏信息节点
package com.hsh.exercise5;
public class test {
public static void main(string[] args) throws exception {
xmlservise xmlservise = new xmlservise("./src/com/hsh/exercise5/收藏信息.xml");
xmlservise.addelemnet("小米","小米15");
xmlservise.addelemnet("小米","小米14");
xmlservise.addelemnet("三星","酸14");
xmlservise.addelemnet("三星","三星14");
xmlservise.addelemnet("三星","小米14");
xmlservise.deltype("三星","小米14");
xmlservise.delbrand("三星");
xmlservise.updatetype("小米","小米14","小米13");
xmlservise.updatebrand("小米","三星");
xmlservise.updatebrand("三星","小米");
xmlservise.save();
xmlservise.print();
}
}
package com.hsh.exercise5;
import org.dom4j.document;
import org.dom4j.documenthelper;
import org.dom4j.element;
import org.dom4j.io.outputformat;
import org.dom4j.io.saxreader;
import org.dom4j.io.xmlwriter;
import java.io.filewriter;
import java.util.list;
public class xmlservise {
public document document;
public string url;
saxreader saxreader = new saxreader();
public xmlservise(string url) throws exception {
this.url = url;
this.document =saxreader.read(url);
}
public void print(){
// 获取根节点
element rootelement = document.getrootelement();
// 获取根节点的所有子标签
list<element> elements = rootelement.elements();
for (int i = 0; i < elements.size(); i++){
system.out.print("手机品牌:");
// 获取属性值
system.out.print(elements.get(i).attributevalue("name")+",");
system.out.print("手机型号:");
for (int j = 0; j < elements.get(i).elements().size(); j++){
// 获取属性
system.out.print(elements.get(i).elements().get(j).attributevalue("name")+" ");
}
system.out.println();
}
}
public void save() throws exception {
// 设置xml文件的格式
outputformat outputformat = outputformat.createprettyprint();
outputformat.setencoding("utf-8");
xmlwriter xmlwriter=new xmlwriter(new filewriter(url),outputformat);
xmlwriter.write(document);
xmlwriter.close();
}
public void addelemnet(string brand, string type) throws exception{
// 获取根节点
element rootelement = document.getrootelement();
boolean isbrandexist = false;
boolean istypeexist = false;
// 遍历查找是否有brand的name属性的名字相同的
list<element> elements = rootelement.elements();
for (int i = 0; i < elements.size(); i++){
if(elements.get(i).attributevalue("name").equals(brand)){
isbrandexist = true;
list<element> elements1 = elements.get(i).elements();
for (int j = 0; j < elements1.size(); j++){
if(elements1.get(j).attributevalue("name").equals(type)){
istypeexist = true;
}
}
}
}
if(isbrandexist){
if(istypeexist){
// 不添加
}else {
// 遍历找到该品牌并添加
for (int i = 0; i < elements.size(); i++){
if(elements.get(i).attributevalue("name").equals(brand)){
element element = documenthelper.createelement("type");
element.addattribute("name",type);
elements.get(i).add(element);
}
}
}
}else {
element element = documenthelper.createelement("brand");
element.addattribute("name",brand);
element element1 = documenthelper.createelement("type");
element1.addattribute("name",type);
element.add(element1);
rootelement.add(element);
}
}
public void deltype(string brand, string type) {
// 获取根节点
element rootelement = document.getrootelement();
for (int i = 0; i < rootelement.elements().size(); i++){
if(rootelement.elements().get(i).attributevalue("name").equals(brand)){
for (int j = 0; j < rootelement.elements().get(i).elements().size(); j++){
if(rootelement.elements().get(i).elements().get(j).attributevalue("name").equals(type)){
rootelement.elements().get(i).elements().remove(j);
}
}
}
}
}
public void delbrand(string brand) {
// 获取根节点
element rootelement = document.getrootelement();
for (int i = 0; i < rootelement.elements().size(); i++){
if(rootelement.elements().get(i).attributevalue("name").equals(brand)){
rootelement.elements().remove(i);
}
}
}
public void updatetype(string brand, string name, string newname) {
// 获取根节点
element rootelement = document.getrootelement();
for (int i = 0; i < rootelement.elements().size(); i++){
if(rootelement.elements().get(i).attributevalue("name").equals(brand)){
for (int j = 0; j < rootelement.elements().get(i).elements().size(); j++){
if(rootelement.elements().get(i).elements().get(j).attributevalue("name").equals(name)){
rootelement.elements().get(i).elements().get(j).addattribute("name",newname);
}
}
}
}
}
public void updatebrand(string brand, string newbrand) {
// 获取根节点
element rootelement = document.getrootelement();
for (int i = 0; i < rootelement.elements().size(); i++){
if(rootelement.elements().get(i).attributevalue("name").equals(brand)){
rootelement.elements().get(i).addattribute("name",newbrand);
}
}
}
}结果
<?xml version="1.0" encoding="utf-8"?>
<phoneinfo>
<brand name="华为">
<type name="u8650"/>
<type name="hw123"/>
<type name="hw321"/>
</brand>
<brand name="苹果">
<type name="iphone4"/>
</brand>
<brand name="小米">
<type name="小米15"/>
<type name="小米13"/>
</brand>
</phoneinfo>综合案例
<?xml version="1.0" encoding="gbk"?> <citys> <city id='010'> <cityname>北京</cityname> <cityarea>华北</cityarea> <population>2114.8万人</population> </city> <city id='021'> <cityname>上海</cityname> <cityarea>华东</cityarea> <population>2,500万人</population> </city> <city id='020'> <cityname>广州</cityname> <cityarea>华南</cityarea> <population>1292.68万人</population> </city> <city id='028'> <cityname>成都</cityname> <cityarea>华西</cityarea> <population>1417万人</population> </city> </citys>
(1)使用dom4j将信息存入xml中
(2)读取信息,并打印控制台
(3)添加一个city节点与子节点
(4)使用socket tcp协议编写服务端与客户端,客户端输入城市id,服务器响应相应城市信息
(5)使用socket tcp协议编写服务端与客户端,客户端要求用户输入city对象,服务端接收并使用dom4j保存至xml文件
解析
这道题我的思路是
将客户端和服务端抽象成类,都有接收和发送功能。
然后把xml文件的添加,保存,查询都给保存起来。
citys.xml
<?xml version="1.0" encoding="utf-8"?>
<citys>
<city id="010">
<cityname>北京</cityname>
<cityarea>华北</cityarea>
<population>2114.8万人</population>
</city>
<city id="021">
<cityname>上海</cityname>
<cityarea>华东</cityarea>
<population>2,500万人</population>
</city>
<city id="020">
<cityname>广州</cityname>
<cityarea>华南</cityarea>
<population>1292.68万人</population>
</city>
<city id="028">
<cityname>成都</cityname>
<cityarea>华西</cityarea>
<population>1417万人</population>
</city>
</citys>server.java
package com.hsh.homework1;
import java.io.inputstream;
import java.io.outputstream;
import java.net.serversocket;
import java.net.socket;
public class server {
public int port;
serversocket s;
socket socket;
outputstream os;
inputstream is;
public server(int port) {
this.port = port;
}
public void start() throws exception {
system.out.println("服务器启动成功");
s = new serversocket(port);
// 每使用一次 accept 说明一个客户端连接
// 再次使用就和上一次的客户端连接断开
socket = s.accept(); // 只 accept 一次
is = socket.getinputstream();
os = socket.getoutputstream();
system.out.println("客户端已连接");
}
public void stop() throws exception {
s.close();
}
/**
* 发送消息 比如返回该城市的信息
* @param msg
* @throws exception
*/
public void responsemsg(string msg) throws exception {
system.out.println("服务器开始发送");
os.write((msg+"end").getbytes());
system.out.println("服务器发送成功");
}
/**
* 接收指令
* @return
* @throws exception
*/
public string receivemsg() throws exception {
system.out.println("服务器开始接收");
byte[] b = new byte[1024];
int len;
string str = "";
boolean receivedend = false;
while (!receivedend && (len = is.read(b)) != -1) {
str += new string(b, 0, len);
if (str.contains("end")) {
str = str.replace("end", ""); // 去掉结束符
receivedend = true;
}
}
return str;
}
}servertest.java
package com.hsh.homework1;
public class servertest {
public static void main(string[] args) throws exception {
server server = new server(9999);
server.start();
xmlservise xmlservise = new xmlservise("src/com/hsh/homework1/citys.xml");
while (true) {
string msg = server.receivemsg();
system.out.println("收到客户端指令: " + msg);
switch (msg){
case "1":
// 接收要查询的省份id
string provinceid = server.receivemsg();
system.out.println("查询省份id: " + provinceid);
string cityinfo = xmlservise.getcityinfo(provinceid);
server.responsemsg(cityinfo);
system.out.println();
break;
case "2":
string addcityinfo =server.receivemsg();
system.out.println("添加城市信息: " + addcityinfo);
string[] arr = utils.split(addcityinfo);
xmlservise.addcity(arr[0], arr[1], arr[2], arr[3]);
xmlservise.save();
break;
default:
server.responsemsg("无效指令");
break;
}
}
}
}client.java
package com.hsh.homework1;
import java.io.outputstream;
import java.lang.reflect.array;
import java.net.socket;
import java.util.arraylist;
import java.util.list;
public class client {
string url;
int port;
socket socket;
outputstream os;
public client(string url, int port) {
this.url = url;
this.port = port;
}
public void start() throws exception {
socket = new socket(url, port);
system.out.println("客户端启动成功");
}
/**
* 接收消息
* @return
* @throws exception
*/
public string receivemsg() throws exception {
system.out.println("客户端开始接收");
socket.getinputstream();
byte[] b = new byte[1024];
int len;
string str = "";
// 循环读取,直到读取到结束符,不然可能会卡在这不往下走。
boolean receivedend = false;
while (!receivedend && (len = socket.getinputstream().read(b)) != -1) {
str += new string(b, 0, len);
if (str.contains("end")) {
str = str.replace("end", ""); // 去掉结束符
receivedend = true;
}
}
system.out.println("客户端接收成功");
return str;
}
/**
* 关闭
*
* @throws exception
*/
public void stop() throws exception {
os.close();
socket.close();
}
/**
* 发送消息
*
* @param instructions
* @throws exception
*/
public void sendinstructions(string instructions) throws exception {
system.out.println("客户端开始发送");
os = socket.getoutputstream();
os.write((instructions + "end").getbytes());
system.out.println("客户端发送成功");
}
}clienttest.java
package com.hsh.homework1;
import java.util.arraylist;
import java.util.list;
import java.util.scanner;
public class clienttest {
public static void main(string[] args) throws exception {
client client = new client("127.0.0.1", 9999);
client.start();
scanner sc = new scanner(system.in);
while (true){
system.out.println("请选择操作");
system.out.println("1.输入城市id查看城市信息");
system.out.println("2.输入城市id,省份,省份归属地,人口数");
system.out.println("3.退出");
switch (sc.next()){
case "1":
client.sendinstructions("1");
system.out.println("请输入城市id");
// client.sendid(sc.next());
client.sendinstructions(sc.next());
system.out.println(client.receivemsg());
break;
case "2":
client.sendinstructions("2");
system.out.println("请输入城市id");
string id =sc.next();
system.out.println("请输入省份");
string province =sc.next();
system.out.println("请输入省份归属地");
string area =sc.next();
system.out.println("请输入人口数");
string population =sc.next();
list<string> list = new arraylist<>();
list.add(id);
list.add(province);
list.add(area);
list.add(population);
client.sendinstructions(list.tostring());
// client.sendcityinfo(id,province,area,population);
break;
case "3":
system.out.println("退出");
client.stop();
return;
default:
system.out.println("请输入正确的选项");
break;
}
}
}
}
xmlservise.java
package com.hsh.homework1;
import org.dom4j.document;
import org.dom4j.documenthelper;
import org.dom4j.element;
import org.dom4j.io.outputformat;
import org.dom4j.io.saxreader;
import org.dom4j.io.xmlwriter;
import java.io.filewriter;
public class xmlservise {
public document document;
public string url;
saxreader saxreader = new saxreader();
public xmlservise(string url) throws exception {
this.url = url;
this.document =saxreader.read(url);
}
public string printxml() {
// 直接输出xml内容
return document.asxml();
}
public void print() {
// 直接输出xml内容
// system.out.println(document.asxml());
// system.out.println();
element rootelement = document.getrootelement();
for (int i = 0; i < rootelement.elements().size(); i++){
element element = rootelement.elements().get(i);
system.out.println(element.attributevalue("id"));
for (int j = 0; j < element.elements().size(); j++){
element element1 = element.elements().get(j);
system.out.println(" "+element1.gettext());
}
}
}
public void addcity(string number, string cityname, string cityarea, string population) {
element rootelement = document.getrootelement();
// 创建city元素
element city = documenthelper.createelement("city");
city.addattribute("id",number);
// 创建cityname元素
element citynameelement = documenthelper.createelement("cityname");
citynameelement.settext(cityname);
// 创建cityarea元素
element cityareaelement = documenthelper.createelement("cityarea");
cityareaelement.settext(cityarea);
// 创建population元素
element populationelement = documenthelper.createelement("population");
populationelement.settext(population);
city.add(citynameelement);
city.add(cityareaelement);
city.add(populationelement);
rootelement.add(city);
}
/**
* 获取城市信息
* @param provinceid
* @return
*/
public string getcityinfo(string provinceid) {
element rootelement = document.getrootelement();
for (int i = 0; i < rootelement.elements().size(); i++){
element element = rootelement.elements().get(i);
if(element.attributevalue("id").equals(provinceid)){
stringbuilder stringbuilder = new stringbuilder();
for (int j = 0; j < element.elements().size(); j++){
element element1 = element.elements().get(j);
stringbuilder.append(element1.gettext());
stringbuilder.append(" ");
}
return stringbuilder.tostring();
}
}
return "没有此城市";
}
public void save() throws exception{
outputformat outputformat = outputformat.createprettyprint();
outputformat.setencoding("utf-8");
xmlwriter xmlwriter=new xmlwriter(new filewriter(url),outputformat);
xmlwriter.write(document);
xmlwriter.close();
}
}
utils.java
package com.hsh.homework1;
public class utils {
public static string[] split(string str) {
string[] arr = str.substring(1, str.length() - 1).split(",");
for (int i = 0; i < arr.length; i++) {
arr[i] = arr[i].trim();
system.out.println(arr[i]);
}
return arr;
}
}
运行结果
客户端启动成功
请选择操作
1.输入城市id查看城市信息
2.输入城市id,省份,省份归属地,人口数
3.退出
1
客户端开始发送
客户端发送成功
请输入城市id
010
客户端开始发送
客户端发送成功
客户端开始接收
客户端接收成功
北京 华北 2114.8万人请选择操作
1.输入城市id查看城市信息
2.输入城市id,省份,省份归属地,人口数
3.退出
2
客户端开始发送
客户端发送成功
请输入城市id
035
请输入省份
河南
请输入省份归属地
华中
请输入人口数
1234万人
客户端开始发送
客户端发送成功请选择操作
1.输入城市id查看城市信息
2.输入城市id,省份,省份归属地,人口数
3.退出
1
客户端开始发送
客户端发送成功
请输入城市id
035
客户端开始发送
客户端发送成功
客户端开始接收
客户端接收成功
河南 华中 1234万人请选择操作
1.输入城市id查看城市信息
2.输入城市id,省份,省份归属地,人口数
3.退出
服务器启动成功
客户端已连接
服务器开始接收
收到客户端指令: 1
服务器开始接收
查询省份id: 010
服务器开始发送
服务器发送成功服务器开始接收
收到客户端指令: 2
服务器开始接收
添加城市信息: [035, 河南, 华中, 1234万人]
035
河南
华中
1234万人
服务器开始接收
收到客户端指令: 1
服务器开始接收
查询省份id: 035
服务器开始发送
服务器发送成功服务器开始接收
<?xml version="1.0" encoding="utf-8"?>
<citys>
<city id="010">
<cityname>北京</cityname>
<cityarea>华北</cityarea>
<population>2114.8万人</population>
</city>
<city id="021">
<cityname>上海</cityname>
<cityarea>华东</cityarea>
<population>2,500万人</population>
</city>
<city id="020">
<cityname>广州</cityname>
<cityarea>华南</cityarea>
<population>1292.68万人</population>
</city>
<city id="028">
<cityname>成都</cityname>
<cityarea>华西</cityarea>
<population>1417万人</population>
</city>
<city id="035">
<cityname>河南</cityname>
<cityarea>华中</cityarea>
<population>1234万人</population>
</city>
</citys>总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论