XML语言

XML定义

XML, Extensible Markup Language(可扩展标记语言),由SGML语言发展而来,允许用户自定义标签,可以将标签和内容有效分离。它逐渐演变为—种跨平台的数据交换格式(一种在不同平台、不同系统之间的数据交换格式),一种轻量级的持久化方案(保存简单数据,无需使用数据库)。XML只是纯文本而已,只是一种独立于软件、硬件的数据存储和传输工具。它可对外提供一下信息,但于C、Java这些编程语言不同,XML无法提供任何“动态行为”。和HTML提供预定义标签不同,开发者可以自定义任意标签,因此具有很强的扩张性不同于HTML侧重于数据的展示,XML更加关注数据的存储和传输;不同于HTML可以使用浏览器来解析并显示,XML需自行编写软件或程序,才能传送、接收、显示这个文档。1998年2月10日,XML正式成为W3C的推荐标准(晚于HTML)。XML和 Javaee是两种不同的技术,但是其广泛的用在 Javaee开发的各个方面,比如使用XML作为配置文件,使用XML进行数据交换。

XML文档的优缺点

优点:

  • 简单性
    逍循XML文档的基本规则的前提下,可以任意自定义标签
  • 良好的可读性
    遵循XML文档的基本规则的前提下,标签名见名知义,具有良好的嵌套关系,带有了良好的可读性。
  • 可扩展性
    可以根据XML的基本语法来进一步限定使用范围和文档格式,从而定义一种新的语言
  • 可以轻松的跨平台应用
    XML文档是基于文本的,所以很容易被人和机器阅读,也非常容易使用,便于不同设备和不同系统间的信息交换
  • 数据内容与显示的分离
    在XML文档中,数据的显示样式已从文档中分离出来,而放入相关的样式表文件中

XML的组成

XML文档有以下几部分组成。

文档声明

XML文档必须以文档声明开始,声明中包含了:version文档版本号,encoding文档编码格式。

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

元素

XML文档必须包含元素,每一对标签即为一个元素,元素通常为以开始标签、元素内容、结束标签组成,并且开始标签名需要和结束标签同名。元素必须拥有结束标签,但是可以没有开始标签和内容。元素中的每一个子标签也是一个元素,元素是XML文档的主要部分,一个XML文档只能有一个根元素,作为所有元素的根。XML的元素对大小写敏感,大小写不同的标签被视为两个不同的元素。

<Users>...内容...</Users>

属性

XML文档中的标签可以有属性也可以没有属性,属性用来描述元素。属性必须写在元素的开始标签上,元素的属性没有先后顺序,属性名自定义,属性值必须使用双引号,每一个元素可以有众多属性,同一个元素中属性名是唯一的不可重复,

<user id="001"></user>

特殊符号

由于XML文档使用了部分字符作为关键字符。我们不能以正常的方式书写这些符号,这样会导致符号被当做关键符进行解析。以下列出了两种解决方式。

字符实体

如果我们要少量使用这些字符则需要使用XML文档规定的一些其他字符来代替,以确保XML中的这些字符可以被正确解析。

原始字符代替字符
&lt;<
&gt;>
&amp;&
&apos
&quot"

注释:在 XML 中,只有字符 “<” 和 “&” 确实是非法的。大于号是合法的,但是用实体引用来代替它是一个好习惯。

CTATA

CTATA为:CharData的缩写

在使用大量的关键字符时可以使用CTATA来包裹这些字符,以保证符号被正确的解析。

CDATA 部分中的所有内容都会被解析器忽略。
CDATA 部分不能包含字符串 “]]>”。也不允许嵌套的 CDATA 部分。
标记 CDATA 部分结尾的 “]]>” 不能包含空格或换行。

<user><![CDATA[ “符号”]]>/user>

注释

在XML文档中使用 <!--注释内容 --> 进行注释说明。

XML文档规范

  • 元素正确嵌套XML

  • 文件的第一行必须是XML声明

  • XML文件只能有一个根节点

  • 英文字符的大小写是有差异的

  • 开始的控制标记与结束的控制标记缺一不可

  • 属性值的设置必须被"包围起来

有效的XML文档

  • 首先必须是格式良好的(语法约束)
  • 使用DTD和XSD( XML Schema)定义语义约束

DDT约束

TD, Document Type Definition,文档类型定义,保证ⅩML文档格式正确性。使用DTD定义了合法的语义约束后,必须让XML文档引入该语义约束,才会生效。在ⅩM文档中引入DTD主要包括3中方式:

  • 内部DTD
  • 外部DTD
  • 公用DTD

符号说明

(!!不包含全部)

  • 子元素有序使用逗号:<! ELEMENT user( name, age, sxe)>。

  • 子元素互斥使用竖线:<! ELEMENT user( name age,sxe)>。

  • 子元素无序没有特殊语法,变通解决:<! ELEMENT user(name| age|sxe)+>。

  • 元素类型:字符串类型# PCDATA空内容 EMPTY、任意内容ANY、子元素。

  • 子元素出现的频率
    表示子元素出现0次到1次令。
    +表示子元素至少出现一次。
    *表示子元素可以出现0到多次。

  • PCDATA: (parsed character data)被解析的字符串类型在DTD定义来指定元素类型 CDATA (character data)不被解析的字符串类型在DTD定义中指定属性类型。

  • ATTLIST只能定义一个属性,如果个元素包括多个属性,需通过多个 ATTLIST来定义。

内部DTD

内部DTD是指DTD和XML数据在同一个XML文件中。DTD定义在XML声明和XML主体内容之间。以 <! DOCTYPE " 根元素" [ 开始,....约束规则....]>结束

示例:

<?xml version="1.0" encoding="utf-8" ?><!-- 文档声明 -->
<!DOCTYPE Users [
    <!--声明根元素下的子元素,“+”表示至少可以有一个这样的子元素-->
    <!ELEMENT Users (user+)>
    <!--声明根元素下user子元素可拥有那些子元素-->
    <!ELEMENT user (name,age,sxe)>
    <!--声明属性的约束,为id属性 声明为普通文本,且值不能为空-->
    <!ATTLIST user id CDATA #REQUIRE>.
     <!--声明name元素的属性为没有属性-->
    <!ELEMENT name (#PCDATA)>
     <!--声明age元素的属性为没有属性-->
    <!ELEMENT age (#PCDATA)>



        ]>
<Users>
    <user id="001">
        <name>张三</name>
        <age>19</age>
    </user>
</Users>

外部DTD

在不同的XML文件使用相同的DTD验证规则时,使用内部DTD就会导致代码的重复,不利于后期修改维护。此时可以定义外部DTD,让XML文件来引入外部DTD达到可复用的效果。在DTD中定义语义约束简单易用,但是也具有一些明显的劣势:DTD可以定义XM文档的结构,却无法对ⅩML元素内容进行约束,比如,如果希望某个XML元素的内容是日期类型,希望内容必须是正整数,希望某个子元索最多出现3次,就无能为力了。这就需要使用 XML Schema来进行语义约束了。

1.创建一个.dtd文件,将DTD约束写入此文件中。

<!DOCTYPE Users [
        <!--声明根元素下的子元素,“+”表示至少可以有一个这样的子元素-->
        <!ELEMENT Users (user+)>
        <!--声明根元素下user子元素可拥有那些子元素-->
        <!ELEMENT user (name,age)>
        <!--声明属性的约束,为id属性 声明为普通文本,且值不能为空-->
        <!ATTLIST user id CDATA #REQUIRE>
        <!--声明name元素的属性为没有属性-->
        <!ELEMENT name (#PCDATA)>
        <!--声明age元素的属性为没有属性-->
        <!ELEMENT age (#PCDATA)>
]>

2.在XML文件中引入此约束。

语法格式:<!DOCTYPE 根元素 SYSTEM "外部约束路径.dtd">

<?xml version="1.0" encoding="utf-8" ?><!-- 文档声明 -->

<!--引入外部dtd约束-->
<!DOCTYPE Users SYSTEM "Users.dtd">

<Users>
    <user id="001">
        <name>张三</name>
        <age>19</age>
    </user>
</Users>

XML Schema约束

DTD和 XML Schema是两种XML定义语义约束的工具,二者各有特色:DTD简单易用,但是功能相对较弱。XML Schema采用XML文档来定义语义约束,要复杂一些,但是功能强大的多。 XML Schema指定丰富的类型,而且允许开发者自定义数据类型,因此完全可以处琿更加复杂的语义约束场景XML。

Schema简称 XSD(XML Schema Definition),是DTD的替代者,既可以定义XML文档结构,也可以定义ⅩML文档的内容约束。优势体现在:

  • 令可读性强:
    本身就是一个XML文档

  • 支持数据类型:
    比如日期类型,并且限制日期范围都没有问题

  • 可扩展:
    导入其他的 Schema,自定义数据类型、一个ⅩML文档使用多个XML Schema 。

JavaEE和JavaEE开源框架中都大量使用了XML文档,其语义约束也己经陆续从之前的DTD约束升级为 Schema约束。

使用DOM4J解析XML文档

DOM4J的操作原理类似于DOM树。请遵循DOM树的思想使用。

注意

DOM4J解析XML文档的默认路径为项目的 resources目录下,在不修改默认读取位置情况下,读取非resources目录下的XML文档很可能发生文件找不到异常,此异常来自于DOM4J,而不是流。
对于创建XML文档文件时则没有位置要求,但如果不将新创建的XML文档文件创建在resources目录下,在读取此文件时则依然很可能发生文件找不到异常,此异常来自于DOM4J,而不是流。

解析

  1. 在使用maven或下载DOM4J的jar包。
  	<dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>

	<!--或许你还需要这个包-->
	<dependency>
      <groupId>jaxen</groupId>
      <artifactId>jaxen</artifactId>
      <version>1.2.0</version>
    </dependency>

  1. 创建一个类读取xml文档

首先需要通过流来读取XML文档,这是第一步。

InputStream inputStream = Thread.currentThread()
				.getContextClassLoader()
                .getResourceAsStream("user.xml");
  1. 读取XML文档取得XML对象
		//获取指定的xml文档的DOM4J树
        SAXReader reader = new SAXReader();
        //获取XML文档对象
        Document document = reader.read(inputStream);
       
  1. 获取根元素
		//获取根元素
        Element  rootElement = document.getRootElement();
  1. 其余操作
    	//获取根元素下所有元素
       List<Element> elements =  rootElement.elements();
       
       //或者返回一个<Element>迭代器
       Iterator<Element> iterator = rootElement.elementIterator();
       
       //遍历
       for (Element element : elements){
          /* System.out.println("elements:-->" +element);*/
           System.out.println(element.getText());
       }

        //获取指定名称的所有的子元素
       List<Element> list = rootElement.selectNodes("user");
        for (Element e : list) {
            System.out.println(e);

            //获取此元素的所有属性
            List<?> elementAttributes = e.attributes();

            //获取此元素的指定属性
            Attribute attribute = e.attribute("id");
            
            //获取属性名
            String name = attribute.getName();
            
            //获取属性值
            String value = attribute.getValue();
            System.out.println(value);

            //获取元素的 文本 值
            String text = e.getStringValue();


        }

创建XML文档

请按照以下顺序创建一个新的XML文档。

1.创建一个新的文档文件

首先我们需要先创建一个文档工厂,使用文档工厂创建文档对象。

 		//1. 使用 对象创建XML文档
        DocumentFactory documentFactory = new DocumentFactory();
        Document document = documentFactory.createDocument();
        //或
        Document document1 = DocumentHelper.createDocument();

2.添加元素

对新建文档的具体添加操作与对已有文档的具体添加操作相同。

对文档对象添加元素,达到为XML文件添加元素的目的。

  //为根元素添加注释
        document.addComment("用户根");

        //为XML文档创建根元素
        Element rootElement = document.addElement("User");

        //为根元素添加一个子元素
        Element childNode = rootElement.addElement("user");

        //为子元素添加属性
        childNode.addAttribute("id", "001");

        //为子元素添加一个 name 子元素
        Element nameElement = childNode.addElement("name");
        //为元素添加内容
        nameElement.setText("张三");

        //为子元素添加一个 age 子元素
        Element ageElement = childNode.addElement("age");
        //为元素添加内容
        ageElement.setText("20");

        //为子元素添加一个 sex 子元素
        Element sexElement = childNode.addElement("sex");
        //为元素添加内容
        sexElement.setText("false");

3.向XML文档写入所有元素

最终将文档对象写入到指定目录下。


        //添加换行,生成格式(使其拥有易于阅读的格式)
        OutputFormat format = OutputFormat.createPrettyPrint();

        //在项目中创建一个xml文档
        Writer  writer = new FileWriter("D:\\源码\\untitled1\\src\\main\\resources\\User_1.xml");

        //创建一个XML写入流,指定写入的文件
        XMLWriter xmlWriter = new XMLWriter(writer,format);

        //将根节点内包含的所有元素写入
        xmlWriter.write(document);
        xmlWriter.flush();
        xmlWriter.close();

最终结果

在这里插入图片描述

添加

添加的具体操作和创建文档时具体操作相同。

有时候我们需要在已经存在内容的XML文档中添加元素,请使用以下方法。

首先我们需要先获取需要进行添加的XML文档的根元素。


        InputStream inputStream = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("user.xml");

        //获取指定的xml文档的DOM4J树
        SAXReader reader = new SAXReader();
        //获取XML文档对象
        Document document = reader.read(inputStream);
        //获取根元素
        Element  rootElement = document.getRootElement();

添加元素应是对根元素内的某个位置添加一个新的元素,默认为添加到最后一个元素的下方。

 InputStream inputStream=  Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("User_1.xml");
        //获取指定的xml文档的DOM4J树
        SAXReader reader = new SAXReader();
        
        //获取XML文档对象,此时读取到的文档对象内包含文档内原有的元素
        Document document = reader.read(inputStream);

        //获取根元素
        Element  rootElement = document.getRootElement();


        //为根元素添加一个子元素
        Element childNode = rootElement.addElement("user");

        //为子元素添加属性
        childNode.addAttribute("id", "002");

        //为子元素添加一个 name 子元素
        Element nameElement = childNode.addElement("name");
        //为元素添加内容
        nameElement.setText("王五");

        //为子元素添加一个 age 子元素
        Element ageElement = childNode.addElement("age");
        //为元素添加内容
        ageElement.setText("62");

        //为子元素添加一个 sex 子元素
        Element sexElement = childNode.addElement("sex");
        //为元素添加内容
        sexElement.setText("false");


        //添加换行,生成格式
        OutputFormat format = OutputFormat.createPrettyPrint();

        //指定文件
        Writer  writer = new FileWriter("D:\\源码\\untitled1\\src\\main\\resources\\User_1.xml");

        //创建一个XML写入流,指定写入的文件
        XMLWriter xmlWriter = new XMLWriter(writer,format);

        //将根节点内包含的所有元素写入
        xmlWriter.write(document);
        xmlWriter.flush();
        xmlWriter.close();

添加元素到指定的位置

添加元素到指定的位置其实针对的是有内容的集合。

/*-----------------------------------以下为固定部分-----------------------------------------------*/

        InputStream inputStream=  Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("User_1.xml");
        //获取指定的xml文档的DOM4J树
        SAXReader reader = new SAXReader();
        //获取XML文档对象
        Document document = reader.read(inputStream);
        //获取根元素
        Element  rootElement = document.getRootElement();

/*-----------------------------------以下为向指定位置添加-----------------------------------------------*/

        //获取根元素中的某个名称的所有元素
        List<Element> elementList = rootElement.elements("user");

		/*以下为一个创建完整的元素的过程*/	

       //新建一个元素
        Element newElement = DocumentHelper.createElement("user");

        //为元素添加属性
        newElement.addAttribute("id", "003");

        //为元素添加一个 name 子元素
        Element nameElement = newElement.addElement("name");
        //为元素添加内容
        nameElement.setText("赵柳");

        //为元素添加一个 age 子元素
        Element ageElement = newElement.addElement("age");
        //为元素添加内容
        ageElement.setText("45");

        //为元素添加一个 sex 子元素
        Element sexElement = newElement.addElement("sex");
        //为元素添加内容
        sexElement.setText("true");

        //重点  向指定位置添加元素
        elementList.add(2,newElement);


/*-----------------------------------以下为固定部分-----------------------------------------------*/
        //添加换行,生成格式
        OutputFormat format = OutputFormat.createPrettyPrint();

        //指定文件
        Writer  writer = new FileWriter("D:\\源码\\untitled1\\src\\main\\resources\\User_1.xml");

        //创建一个XML写入流,指定写入的文件
        XMLWriter xmlWriter = new XMLWriter(writer,format);

        //将根节点内包含的所有元素写入
        xmlWriter.write(document);
        xmlWriter.flush();
        xmlWriter.close();



与创建文件时添加的不同之处

  1. 操作的对象不同
    在创建文件时,需要使用new DocumentFactory();DocumentHelper.createDocument();来创建一个新的文档对象,针对新文档对象进行添加,此时添加的元素还未写入XML文档文件。

  2. 添加时不同
    在对已有内容的文档进行添加时,Element rootElement = document.getRootElement();此对象已然包含有原始文档中的内容,是一个包含元素的rootElement对象。在添加时DOM4J应该会进行根节点内容检查,否则应是添加到内容的头部而不是尾部。
    因此,在向指定位置添加时,拥有元素的rootElement对象尤为重要。添加时是添加的新的已经有了新的元素的rootElement对象,而不只是新的元素自己。

  3. 写入时不同
    在创建新文档时, new FileWriter(“.....”)是如果没有此文件则创建此文件。而在添加时则是执行的写入到此文件的操作。

与创建文件时添加的相同之处

  1. 添加的具体方式相同
    都是使用获取的文档对象取得根元素针对根元素,使用相同的方法添加元素。添加元素的具体方法相同。

删除

如果你仔细阅读了上一节:向指定位置添加元素 ,那么我相信你已经猜到了如何修改与删除元素。
通过获取根元素中的某个名称的元素们,得到这种标签名的元素,通过判断删除元素与修改元素。

/*-----------------------------------以下为固定部分-----------------------------------------------*/

        InputStream inputStream=  Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("User_1.xml");
        //获取指定的xml文档的DOM4J树
        SAXReader reader = new SAXReader();
        //获取XML文档对象
        Document document = reader.read(inputStream);
        //获取根元素
        Element  rootElement = document.getRootElement();

/*-----------------------------------以下为修改-----------------------------------------------*/

        //获取根元素中的某个名称的所有元素
        ListIterator<Element> elementList = rootElement.elements("user").listIterator();

        while (elementList.hasNext()){
            Element element = elementList.next();
            Attribute attribute = element.attribute("id");
            if (attribute.getValue().equals("001")){
                elementList.remove();
                break;
            }

        }



/*-----------------------------------以下为固定部分-----------------------------------------------*/
        //添加换行,生成格式
        OutputFormat format = OutputFormat.createPrettyPrint();

        //在项目中创建一个xml文档
        Writer  writer = new FileWriter("D:\\源码\\untitled1\\src\\main\\resources\\User_1.xml");

        //创建一个XML写入流,指定写入的文件
        XMLWriter xmlWriter = new XMLWriter(writer,format);

        //将根节点内包含的所有元素写入
        xmlWriter.write(document);
        xmlWriter.flush();
        xmlWriter.close();





修改

修改与删除原理相同,都是针对集合操作。

/*-----------------------------------以下为固定部分-----------------------------------------------*/

        InputStream inputStream=  Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("User_1.xml");
        //获取指定的xml文档的DOM4J树
        SAXReader reader = new SAXReader();
        //获取XML文档对象
        Document document = reader.read(inputStream);
        //获取根元素
        Element  rootElement = document.getRootElement();

/*-----------------------------------以下为修改-----------------------------------------------*/

        //获取根元素中的某个名称的所有元素
        ListIterator<Element> elementList = rootElement.elements("user").listIterator();

        while (elementList.hasNext()){
            Element element = elementList.next();
            Attribute attribute = element.attribute("id");
            if (attribute.getValue().equals("002")){

                attribute.setValue("999");

                break;
            }

        }



/*-----------------------------------以下为固定部分-----------------------------------------------*/
        //添加换行,生成格式
        OutputFormat format = OutputFormat.createPrettyPrint();

        //在项目中创建一个xml文档
        Writer  writer = new FileWriter("D:\\源码\\untitled1\\src\\main\\resources\\User_1.xml");

        //创建一个XML写入流,指定写入的文件
        XMLWriter xmlWriter = new XMLWriter(writer,format);

        //将根节点内包含的所有元素写入
        xmlWriter.write(document);
        xmlWriter.flush();
        xmlWriter.close();




  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值