XML

XML语法

XML的基本语法

XML必须有关闭标签
区分大小写
属性需要有引号
标签必须正确嵌套

Xml文件的组成部分

文档声明
元素
元素的属性
注释
CDATA区
特殊字符
处理指令(PI:Processing Instruction)

XML的文档声明

文档声明:出现在XML的第一行第一列的位置。

写法
  <?xml 属性名=”属性值” 属性名=”属性值” ...?>
  version   :必须的. 使用”1.0”
  encoding  :字符集. 是使用浏览器打开的时候采用的默认的字符集的编码
  standalone    :描述XML文档是否需要依赖其他的文件

xml的元素

什么是元素

xml中的元素其实就是一个个的标签
标签分为两种
  a: 包含标签体
  理解: 简括号全部成对儿出现, 所有的数据都用一对儿简括号存储
            <student>
                <name>zhangsan</name>
                <age>18</age>
            </student>

  b: 不包含标签体
  理解: 只有最外层的一个简括号,括号用/标识结束, 内部的数据都用属性来编写
            <student
                name="zhangsan"
                age="18"
            />

标签(元素的书写规范)

严格区分大小写;<p><P>
只能以字母或下划线开头;abc _abc
不能以xml(或XML、Xml等)开头----W3C保留日后使用;
名称字符之间不能有空格或制表符;
名称字符之间不能使用冒号 : (有特殊用途)

XML的属性

属性的名称规范与元素一致,属性需要使用引号!

元素中属性的注意事项
一个元素可以有多个属性,每个属性都有它自己的名称和取值。
属性值一定要用引号(单引号或双引号)引起来。
属性名称的命名规范与元素的命名规范相同。
元素中的属性是不允许重复的。
在XML技术中,标签属性所代表的信息也可以被改成用子元素的形式来描述。
例如:
<?xml version="1.0" encoding="UTF-8"?>
<students>
    <student name="zhangsan" age="18" />
    <student>
        <name>zhangsan</name>
        <age>18</age>
    </student>
</students>

XML的注释

<!-- 被注释的内容 -->
注释不能嵌套定义

XML的CDATA区

使用 CDATA 来避免输出标签文本时,过多的转义。
XML的CDATA区:(CDATA:Character Data)
<![CDATA[  内容  ]]>

<students>
    <student>
        <name>zhangsan</name>
        <url>
            <![CDATA[
                <cnblogs>www.cnblogs.com</cnblogs>
                <baidu>www.baidu.com</baidu>
            ]]>
        </url>
    </student>
    
    <student>
        <name>zhangsan</name>
        <url>
            &lt;cnblogs&gt;www.cnblogs.com&lt;/cnblogs&gt;
        </url>
    </student>
</students>
CDATA和转义符

XML的约束

用来规范XML的写法。

XML的约束的种类及区别?
    DTD(Document Type Definition 文档类型定义) 和 Schema
    区别:
        1.DTD语法是自成一体的.Schema语法就是XML的语法.
        2.Schema的语法就是XML的语法所以更容易被解析器所解析.
        3.Schema支持名称空间.
        4.Schema有比DTD更加强大的语义和语法的约束.

DTD的语法

DTD的引入方式

    内部的DTD:
        <!DOCTYPE persons [  ]>

    外部的DTD:
        一种本地DTD:
        <!DOCTYPE persons SYSTEM "unknown.dtd">
        一种网络DTD:
        <!DOCTYPE persons PUBLIC "//UNKNOWN/" "unknown.dtd">

DTD的语法

语法细节
在DTD文档中使用ELEMENT关键字来声明一个XML元素。
•   语法:<!ELEMENT 元素名称 使用规则>
使用规则:
•   (#PCDATA):指示元素的主体内容只能是普通的文本.(Parsed Character Data)
•   EMPTY:用于指示元素的主体为空。比如<br/>
•   ANY:用于指示元素的主体内容为任意类型。
•   (子元素):指示元素中包含的子元素
•   定义子元素及描述它们的关系:
–   如果子元素用逗号分开,说明必须按照声明顺序去编写XML文档。
•   如: <!ELEMENT FILE (TITLE,AUTHOR,EMAIL)>
–   如果子元素用"|"分开,说明任选其一。
•   如:<!ELEMENT FILE (TITLE|AUTHOR|EMAIL)>
–   用+、*、?来表示元素出现的次数
•   如果元素后面没有+*?:表示必须且只能出现一次
•   +:表示至少出现一次,一次或多次
•   *:表示可有可无,零次、一次或多次
•   ?:表示可以有也可以无,有的话只能有一次。零次或一次

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT 书架(书+)>
    <!ELEMENT 书 (书名,作者,售价)>
    <!ELEMENT 书名 (#PCDATA)>
    <!ELEMENT 作者 (#PCDATA)>
    <!ELEMENT 售价 (#PCDATA)>
DTD例子


定义属性
•   在DTD文档中使用ATTLIST关键字来为一个元素声明属性。
•   语法:
        <!ATTLIST 元素名
            属性名1 属性值类型 设置说明
            属性名2 属性值类型 设置说明
            …
        >
•   属性值类型:
–   CDATA:表示属性的取值为普通的文本字符串
–   ENUMERATED (DTD没有此关键字):表示枚举,只能从枚举列表中任选其一,如(鸡肉|牛肉|猪肉|鱼肉)
–   ID:表示属性的取值不能重复
•   设置说明
–   #REQUIRED:表示该属性必须出现
–   #IMPLIED:表示该属性可有可无
–   #FIXED:表示属性的取值为一个固定值。语法:#FIXED "固定值"
直接值:表示属性的取值为该默认值

<!ATTLIST 商品
        类别 CDATA #REQUIRED
        颜色 CDATA #IMPLIED
>
<?xml version = "1.0" encoding="GB2312" standalone="yes"?>
    <商品 类别="服装"颜色="黄色" />


实例代码2
<?xml version = "1.0" encoding="GB2312" standalone="yes"?>
<!DOCTYPE 购物篮 [
   <!ELEMENT 购物篮 (肉+)>
    <!ELEMENT 肉 EMPTY>
    <!ATTLIST 肉 品种 ( 鸡肉 | 牛肉 | 猪肉 | 鱼肉 ) "鸡肉">
]> 
<购物篮>
    <肉 品种="鱼肉"/>
    <肉 品种="牛肉"/>
    </>
</购物篮>
DTD元素属性例子

DTD约束示例

1.在xml下面创建demo1.dtd文件,代码如下
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT persons (person+)> <!-- person节点可以出现一次或多次-->
<!ELEMENT person (name|age|sex)*> <!-- name,age,sex节点可以出现 零次或多次, 且name,age,sex顺序随意-->
<!ELEMENT name (#PCDATA)> <!-- name节点里面的内容放文本内容即可 -->
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>

<!ATTLIST person id ID #REQUIRED> <!-- person属性是id,这个id必须存在,且id值是唯一的 -->


2.在demo1.xml文件引入demo1.dtd约束,代码如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE persons SYSTEM  "demo1.dtd"> <!-- 引入dtd约束 -->
<!-- XML的注释 -->
<persons>
    <person id="p1">
        <name>李旭华</name>
        <age>38</age>
        <sex>男&lt;</sex>
    </person>
    <person id="p2">
        <name>李冠希</name>
        <age>28</age>
        <sex>男</sex>
    </person>
</persons>
DTD约束xml

Schema约束

Schema约束自身就是一个XML文件,但它的扩展名通常为.xsd。
一个XML Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的xml文件称之为实例文档。
XML Schema对名称空间支持得非常好。

名称空间: 相当于package。       
约束文档: 编写好的Person类。
实例文档: 通过Person类创建对象。

约束文档:
<?xml version='1.0' encoding='UTF-8' ?> 
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' 
                     //标准的名称空间
                      targetNamespace='http://www.cnblogs.com'
                        //将该schema文档绑定到http://www.cnblogs.com名称空间
                >
    <xs:element name='书架' >
        <xs:complexType>
            <xs:sequence maxOccurs='unbounded' >
                <xs:element name='书' >
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name='书名' type='xs:string' />
                            <xs:element name='作者' type='xs:string' />
                            <xs:element name='售价' type='xs:string' />
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

实例文档:
<?xml version="1.0" encoding="UTF-8"?>
<cnblogs:书架 xmlns:cnblogs="http://www.cnblogs.com"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.cnblogs.com book.xsd">
    <cnblogs:>
        <cnblogs:书名>JavaScript网页开发</cnblogs:书名>
        <cnblogs:作者>二狗子</cnblogs:作者>
        <cnblogs:售价>28.00元</cnblogs:售价>
    </cnblogs:书>
</cnblogs:书架>


名称空间:
<cnblogs:书架 xmlns:cnblogs="http://www.cnblogs.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.cnblogs.com book.xsd">
使用默认名称空间
    基本格式:
    xmlns="URI"  
    举例:
    <书架 xmlns="http://www.it315.org/xmlbook/schema"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.it315.org/xmlbook/schema book.xsd">
        <>
        <书名>JavaScript网页开发</书名>
        <作者>马杀鸡</作者>
        <售价>28.00元</售价>
        </>
    <书架>
schema案例

Schema约束示例

1.创建demo2.xsd文件,代码如下
<?xml version="1.0" encoding="UTF-8"?>
<!-- 
    名称空间:一个XML只能引入一个DTD约束文档.使用了Schema约束XML文档,一个XML可以引入多个Schame的约束!!!
                      如果再多个Schema文档中定义了相同的属性名称 该怎么办?
      * 名称空间类似于java中的package.通过名称空间区分 标签或属性来自于哪个文档的!!!通常名称空间唯一的不重复的即可.一般情况下使用一个URL地址表示一个名称空间.

    xmlns               :xml name sapace .代表当前的文档应用的名称空间.
    targetNameSpace     :目标名称空间.
    elementFormDefault  :确定被约束文档书写的严谨程度
 -->
<schema 
    xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.boomoom.com/ee25" 
    xmlns:tns="http://www.example.org/demo2" 
    elementFormDefault="qualified">

    <!-- 复杂标签 -->
    <element name="persons">
        <!-- 复杂类型 -->
        <complexType>
            <sequence maxOccurs="unbounded" minOccurs="1">
                <element name="person">
                    <complexType>
                        <sequence>
                            <!-- 简单标签 -->
                            <element name="name" type="string"></element>
                            <element name="age" type="int"></element>
                            <element name="sex" type="string"></element>
                        </sequence>
                        <attribute name="id" type="string" use="required"></attribute>
                    </complexType>              
                </element>
            </sequence>
        </complexType>
    </element>
</schema>

2.创建demo2.xml文件,具体代码如下
<?xml version="1.0" encoding="UTF-8"?>
<!-- XML的注释 -->
<persons
    xmlns:aa="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.cnblogs.com/ee25"
    aa:schemaLocation="http://www.boomoom.com/ee25 demo2.xsd"
>
    <person id="p1">
        <name>李旭华</name>
        <age>38</age>
        <sex>男</sex>
    </person>

    <person id="p2">
        <name>李冠希</name>
        <age>28</age>
        <sex>男</sex>
    </person>
</persons>
Schema约束XML

XML的解析的方式

DOM解析:DOM:Document Object Model.
SAX解析:Simple Api for XML.

DOM和SAX的区别

DOM 是一次性将文档加载到内存,形成树形结构进行解析。
优点:对 XML 进行增删改的操作。
缺点:如果文档特别大,容易导致内存溢出。

SAX是事件驱动的方式,一行一行进行解析的。
优点:如果文档特别大,不会导致内存溢出。
缺点:不能文档进行增删改的操作。

DOM4J

 DOM4J:开源组织提供了一套XML的解析的API。

DOM4J的入门案例步骤

1、导入jar包.dom4j-1.6.1.jar
2、创建解析器
3、解析文档获得代表文档的Document对象.
4、获得跟节点.
5、从跟节点下查找其他的节点.

@Test
    /**
     * 获得元素的内容:查询的操作.
     */
    public void demo1() throws Exception{
        // 创建解析器
        SAXReader reader = new SAXReader();
        // 解析XML的文档
        Document document = reader.read("xml/demo1.xml");
        // 获得跟节点
        Element root = document.getRootElement();
        System.out.println(root.getName());
        // 查找跟节点下的子节点. element() elements();
        Element pElement = root.element("person"); // 查找的是第一个person元素
        // root.elements("person").get(1); // 查找的是第二个person元素
        Element nElement = pElement.element("name");
        Element aElement = pElement.element("age");
        Element sElement = pElement.element("sex");
        System.out.println(nElement.getText());
        System.out.println(aElement.getText());
        System.out.println(sElement.getText());
    }
dom4j解析样例

XPath

dom4j支持XPath的jar包.
  jaxen-1.1-beta-6.jar
dom4j的XPath支持的API:
  List document.selectNodes(String xPath);
  Node document.selectSingleNode(String xPath);

    @Test
    /**
     * DOM4J的XPath的写法:
     */
    public void demo2() throws Exception{
        // 创建解析器:
        SAXReader reader = new SAXReader();
        // 解析XML返回Document对象.
        Document document = reader.read("xml/demo1.xml");
        /*List<Node> list = document.selectNodes("//name");
        for (Node node : list) {
            Element element = (Element) node;
            System.out.println(element.getText());
        }*/
        
        List<Node> list = document.selectNodes("//person['@id']");
        for (Node node : list) {
            Element element = (Element) node;
            System.out.println(element.attributeValue("id"));
        }
    }
代码实现

DOM4J解析XML

1.创建一个webapps文件夹,把html等文件放入,创建一个conf文件,把server.xml文件放入,server.xml配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<Server>
    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
</Server>

2.在MyServer中的代码如下:
public class MyServer { 
    public static void main(String[] args) throws Exception {
        // 解析XML:
        // 创建解析器
        SAXReader reader = new SAXReader();
        // 解析XML文档:
        Document document = reader.read("conf/server.xml");
        Element element = (Element)document.selectSingleNode("//Connector['@port']");
        String port = element.attributeValue("port");
        // ServerSocket 对象可以监听端口
        ServerSocket serversocket = new ServerSocket(Integer.parseInt(port));
        //ServerSocket serversocket = new ServerSocket(8888);
        while(true) {
            Socket socket = serversocket.accept();  // 等待客户端的连接请求,一旦有请求过来,就结束阻塞,返回客户端对象
            //System.out.println(socket.getInetAddress());
            // 一旦有客户来访问, 就另开一个新线程去提供服务, main线程继续等待下一个客户的连接
            new Thread(new MyService(socket)).start();
        }
    }
}

3.在MyService中的代码如下:
public class MyService implements Runnable{
    private Socket socket;
    public MyService(Socket socket) throws Exception {
        this.socket = socket;
    }

    @Override
    public void run() {
        // 提供服务
        try{
            InputStream in = socket.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String firstLine = reader.readLine();
            System.out.println(firstLine);
            String path = firstLine.split(" ")[1];
            System.out.println(path);
            // 从文件读, 往浏览器写 
            File file = new File("webapps"+path);
            FileInputStream fis = new FileInputStream(file);

            OutputStream os = socket.getOutputStream();
            os.write("HTTP/1.1 200 OK
".getBytes());
            os.write("
".getBytes());
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = fis.read(buffer))!=-1) {
                os.write(buffer, 0, len);
            }
            socket.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
dom4j解析xml

DOM4J的常用方法

Dom4JDemo:

package com.boomoom;

import java.io.IOException;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

/*
 * Dom4J的常用方法:
 *      Document
 *           Element getRootElement() :获取根元素对象(根标签)
 *      Element
 *           List elements() :获取所有的子元素
 *           List elements(String name):根据指定的元素名称来获取相应的所有的子元素
 *           Element element(String name):根据指定的元素名称来获取子元素对象,如果元素名称重复,则获取第一个元素 
 *           String elementText(String name) :根据指定的子元素名称,来获取子元素中的文本
 *           String getText() :获取当前元素对象的文本
 *           void setText(String text):设置当前元素对象的文本
 *           String attributeValue(String name):根据指定的属性名称获取其对应的值
 *           public Element addAttribute(String name,String value):根据指定的属性名称和值进行添加或者修改
 *           addElement
 *      DocumentHelper
 *          static Element  createElement(String name)    
 */
public class Dom4JDemo {
    public static void main(String[] args) throws Exception  {
        //7、操作XML文件属性:打印State的Name
        //8、添加属性:State: GDP="1w亿"
        Document document = Dom4JUtils.getDocument();
        //获取根元素
        Element rootElement = document.getRootElement();
        //添加新的属性和对应的值
        rootElement.addAttribute("GDP", "1w亿");
        //写回文件
        Dom4JUtils.write2XML(document);
    }

    private static void method7() throws Exception {
        //7、操作XML文件属性:打印State的Name
        Document document = Dom4JUtils.getDocument();
        //获取根元素
        Element rootElement = document.getRootElement();
        //根据属性名称获取值
        String value = rootElement.attributeValue("Name");
        System.out.println(value);
    }

    private static void method6() throws Exception, IOException {
        //5、向指定元素节点上增加同级元素节点:在洛阳前面,添加一个<City>三门峡</City>
        //创建一个新的元素对象
        Element cityElement = DocumentHelper.createElement("City");
        //设置文本
        cityElement.setText("三门峡");
        Document document = Dom4JUtils.getDocument();
        //获取根元素
        Element rootElement = document.getRootElement();
        //获取根元素下所有的子元素
        List<Element> es = rootElement.elements();
        //将新的元素添加到子元素列表中
        es.add(1, cityElement);
        
        //写会文件
        Dom4JUtils.write2XML(document);
    }

    private static void method5() throws Exception, IOException {
        //4、向指定元素节点中增加子元素节:添加一个新城市<City>南阳</City>
        Document document = Dom4JUtils.getDocument();
        //获取根元素
        Element rootElement = document.getRootElement();
        //添加元素
        Element cityElement = rootElement.addElement("City");
        //设置文本
        cityElement.setText("南阳");
        //写回文件
        Dom4JUtils.write2XML(document);
    }

    private static void method4() throws Exception, IOException {
        //6、删除指定元素节点:删除元素开封 
        Document document = Dom4JUtils.getDocument();
        //获取根元素
        Element rootElement = document.getRootElement();
        //获取根元素下的所有子元素
        List<Element> es = rootElement.elements();
        Element cityElement = es.get(1);
        //无法自杀,找他爹
        Element parentElement = cityElement.getParent();
        parentElement.remove(cityElement);
        //写回文件
        Dom4JUtils.write2XML(document);
    }

    private static void method3() throws Exception, IOException {
        //3、修改某个元素节点的主体内容:信阳-->安阳
        Document document = Dom4JUtils.getDocument();
        //获取根元素
        Element rootElement = document.getRootElement();
        //获取根元素下的所有子元素
        List<Element> es = rootElement.elements();
        //根据索引可以获取指定的元素
        Element cityElement = es.get(3);
        //修改文本
        cityElement.setText("安阳");
        //写回文件
        Dom4JUtils.write2XML(document);
    }

    private static void method2() throws Exception {
        //2、遍历所有元素节点:打印他们的元素名称。
        //获取根元素
        Document document = Dom4JUtils.getDocument();
        Element rootElement = document.getRootElement();
        treeWalk(rootElement);
    }
    
    public static void treeWalk(Element element) {
        //输出元素的名称
        System.out.println(element.getName());
        
        //获取指定元素的所有子元素
        List<Element> es = element.elements();
        for (Element e : es) {
            treeWalk(e);
        }
    }

    private static void method() throws Exception {
        //1、得到某个具体的节点内容:打印"郑州"
        Document document = Dom4JUtils.getDocument(); 
        //获取根元素
        Element rootElement = document.getRootElement();
        //获取根元素下的所有子元素
        List<Element> elements = rootElement.elements();
        //根据索引获取第一个City元素
        Element cityElement = elements.get(0);
        //根据子元素的名称来获取子元素的文本
        String text = cityElement.elementText("Name");
        System.out.println(text);
    }
}
Dom4JDemo

Dom4JUtils:

package com.boomoom;

import java.io.FileOutputStream;
import java.io.IOException;

import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class Dom4JUtils {
    
    public static Document getDocument() throws Exception {
        SAXReader reader = new SAXReader();
        Document document = reader.read("src/com/boomoom/city.xml");
        return document;
    }
    
    public static void write2XML(Document document) throws IOException {
        OutputFormat format = OutputFormat.createPrettyPrint();
        //format.setEncoding("UTF-8");//默认的编码就是UTF-8
        XMLWriter writer = new XMLWriter( new FileOutputStream("src/com/boomoom/city.xml"), format );
        writer.write( document );
    }
}
Dom4JUtils

city.xml

<?xml version="1.0" encoding="UTF-8"?>

<State Code="37" Name="河南" 
    description="郑州" GDP="1w亿"> 
  <City> 
    <Name>郑州</Name>  
    <Region>高薪区</Region> 
  </City>  
  <City>三门峡</City>  
  <City>洛阳</City>  
  <City>安阳</City>  
  <City>南阳</City> 
</State>
city.xml
原文地址:https://www.cnblogs.com/boomoom/p/10421400.html