开发者

java中XML的使用全过程

目录
  • 什么是XML
  • 特点
  • XML作用
  • XML的编写语法
    • 基本语法
    • 特殊字符编写
  • 约束XML的书写格式
    • DTD文档
    • schema文档
  • 解析XML的方法
    • ​​DOM解析XML
    • SAX
    • DOM4J
  • 综合案例
    • 解析
    • citys.xml
    • Spythonerver.Java
    • ServerTest.java
    • Client.java
    • ClientTest.java
    • XmlServise.java
    • Utils.java
    • 运行结果
  • 总结

    什么是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">
          php  <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文件可以在浏览器中查看,我们打开浏览器看到,我们写的特殊字符的格式是我们所预期的

    java中XML的使用全过程

    java中XML的使用全过程

    特殊字符编写

    1、 指定字符替代特殊字符

    XML中书写”<’

    “&”等,可能会出现冲突,导致报错,此时可以用如下特殊字符替代。

    指定字符特殊字符含义
    &lt;<小于
    &gt;>大于
    &amp;&小于
    &apos;单引号
    &quot;"双引号

    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 &gt; 2 &amp;&amp; 3 &lt; 5 </special>
    </Users>
    

    java中XML的使用全过程

    约束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>

    java中XML的使用全过程

    属性命名空间

    <?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)

    1. 基于XML文档树结构的解析
    2. 适用于多次访问的XML文档
    3. 特点:比较消耗资源

    SAX(内置解析XML)

    1. 基于事件的解析
    2. 适用于大数据量的XML文档
    3. 特点:占用资源少,内存消耗小

    DOM4J

    1. 非常优秀的Java XML API
    2. 性能优异、功能强大
    3. 开放源代码

    ​​DOM解析XML

    基于XML文档树结构的解析

    适用于多次访问的XML文档

    特点:比较消耗资源

    DOM介绍

    文档对象模型(Document Object Model)

    DOM把XML文档映射成一个倒挂的树

    java中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文件步骤

    1. 创建解析器工厂对象
    2. 解析器工厂对象创建解析器对象
    3. 解析器对象指定XML文件创建Document对象
    4. 以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文件

    步骤

    1. 获得TransformerFactory对象
    2. 创建Transformer对象
    3. 创建DOMSource对象:包含XML信息
    4. 设置输出属性:编码格式
    5. 创建StreamResult对象:包含保存文件的信息
    6. 将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节点

    添加手机收藏

    1. 添加新的Brand:三星
    2. 给Brand节点添加新的子标签Type:Note4
    3. 将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官网

    java中XML的使用全过程

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

    java中XML的使用全过程

    java中XML的使用全过程

    3、将jar包添加到库中

    java中XML的使用全过程

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

    java中XML的使用全过程

    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文件

    1. 显示手机收藏信息
    2. 保存手机收藏信息
    3. 为手机收藏信息添加新的节点
    4. 修改/删除手机收藏信息节点
    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"/&androidgt;  
        <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>

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜