XML快速入门

XML快速入门

XML简介

  • 可扩展标记型语言
    • 标记型语言:HTML是标记型语言
      • 也是使用标签来操作
    • 可扩展:
      • HTML里的标签是固定的,每个标签都有特定的含义
      • 标签可以自己定义,可以写中文标签
  • 用途
    • HTML用于显示数据,xml也可以显示数据(不是主要功能)
    • xml主要功能,为了存储数据
  • xml是W3C组织发布的技术
  • xml有两个版本1.0 1.1
    • 使用都是1.0版本(1.1版本不能向下兼容)

XML的应用

  • 不同的系统之间传输数据

    • eg.qq消息之间的传输格式:
      • 最早的时候,使用字符串,“发送者接受者发送消息发送时间”,可读性差,不利于程序的维护
      • 现在,使用字符串,“各种标签,及其内容”,利于程序的维护
  • 用来表示生活中有关系的数据

    (利用父节点和子节点)

  • 经常用在配置文件中

XML的文档声明

  • 创建一个文件,后缀名是.xml
  • 写xml,第一步必须要有一个文档声明(写了文档声明之后,表示写xml文件的内容)
    • <?xml version="1.0" encoding="gbk"?>
      • 文档声明必须写在第一行第一列
  • 属性
    • version:xml的版本:1.0(使用),1.1
    • encoding:xml编码:gbk(中文简体),utf-8(包含中文),iso8859-1 (不包含中文)
    • standalone:是否需要其他文件:yes,no

XML中文乱码问题解决

保存到本地硬盘时,使用gbk编码保存,打开xml时,打开使用设置的编码为utf-8,对应不一致,出现乱码

解决方案:设置保存时的编码与打开时的编码一致

XML元素(标签)的定义

  • 标签定义<……>
  • 标签定义必须有开始和结束
  • 标签没有内容时,可以在标签内结束:<aa/>
  • 标签可以嵌套,必须合理嵌套
    • 合理嵌套:<aa><bb></bb></aa>
    • 不合理嵌套:<aa><bb></aa></bb>
  • 一个xml中,只能有一个根标签,其他标签必须是这个标签下面的标签
  • 在xml中把空格和换行都当做内容来解析
  • xml标签可以是中文
  • xml中标签的命名规则
    1. xml代码区分大小写
    2. xml标签不能以数字和下划线开头
    3. xml标签不能以xml,XML,Xml等开头
    4. xml标签不能包含空格和冒号

XML属性的定义

  • HTML是标记型文档,可以有属性;xml也是标记型文档,可以有属性
  • 属性定义的要求:
    1. 一个标签上可以有多个属性
    2. 属性名称不能相同
    3. 属性名称和属性值之间用=,属性值一定要用引号包起来(单引号或双引号)
    4. xml属性的名称规范和元素的名称规范一致

XML注释

  • 写法:<!--……-->
  • 注意:注释不能嵌套
  • 注释也不能放在第一行,第一行第一列必须放文档声明

XML特殊字符

  • 对特殊字符进行转译
    • 小于<:&lt ;
    • 大于>:&gt ;
    • 双引号“:&quot ;
    • 单引号‘:&apos ;
    • &:&amp ;

XML的CDATA区

  • 可以解决多个字符都需要转译的操作,把这些内容都放到CDATA区里面,就不需要进行转译了
  • 写法:<![CDATA [……] ]>
  • 把特殊字符当成文本内容,而不是标签了

XML的PI指令(处理指令)

  • 可以在xml中设置样式
  • 写法:<?xml-stylesheet type="text/css" href="css的路径"?>
  • 设置样式,只对英文标签名称起作用,对于中文标签名称不起作用

XML约束简介

  • 为什么需要约束:希望信息的保存不混乱,需要技术来规定xml中只能出现的元素,这个时候需要约束
  • xml的约束技术:DTD约束和schema约束

DTD(文档类型定义)

DTD快速入门

  • 创建一个文件,后缀名.dtd

  • 步骤:

    1. 看xml中有多少个元素,有几个元素,就在dtd中写几个<!ELEMENT>

    2. 判断元素是简单元素还是复杂元素

      • 简单元素:没有子元素 <!ELEMENT 元素名称 (#PCDATA)>
      • 复杂元素:有 子元素的元素 <!ELEMENT 元素名称 (子元素1,子元素2)>
    3. 在xml文件中引入的dtd文件

      <!DOCTYPE 根元素名称 SYSTEM "dtd文件的路径">

  • 打开xml文件是使用浏览器打开的,浏览器只负责校验xml的语法,不负责校验约束;如果想要校验xml的约束,需要使用工具(myeclipse工具)

    • 打开myeclipse开发工具,创建一个项目
    • 在项目的src目录下面创建一个xml文件和一个dtd文件
    • 当xml中引入dtd文件之后,自动校验

DTD的引入方式(3种)

  1. 引入外部的dtd文件:<!DOCTYPE 根元素名称 SYSTEM "dtd路径">

  2. 使用内部的dtd文件:<!DOCTYPE 根元素名称 [dtd代码]>

  3. 使用外部的dtd文件(网络上的dtd文件):

    <!DOCTYPE 根元素名称 PUBLIC “dtd名称 "dtd文档的url">

    (后面框架struts2 使用配置文件 使用外部的dtd文件)

使用DTD定义元素

  • 语法格式:<!ELEMENT 元素名 约束>
  • 简单元素:没有子元素的元素 <!ELEMENT name (#PCDATA)>
    • (#PCDATA):约束name是字符串类型
    • EMPTY:元素为空(没有内容)
    • ANY:任意
  • 复杂元素:
    • <!ELEMENT 元素名称 (子元素1,子元素2,……)> 子元素只能出现一次
    • 表示子元素出现的次数
      • +:表示一次或者多次
      • ?:表示零次或者一次
      • *:表示零次或者多次
    • 子元素之间使用逗号隔开,表示元素的出现顺序
    • 子元素用竖线(|)隔开,表示只能出现其中的任意一个

使用DTD定义属性

  • 语法:<!ATTLIST 元素名称

    属性名称 属性类型 属性的约束

    >

  • 属性类型

    1. CDATE:字符串
    2. 枚举:表示只能在一定的范围内出现值,每次只能出现其中的一个(aa|bb|cc)
    3. ID:值只能是字母或下划线开头
  • 属性约束

    1. #REQUIRED:属性必须存在

    2. #IMPLIED:属性可有可无

    3. #FIXED:表示一个固定值

      #FIXED “*” 属性的值必须是设置的这个固定值

    4. 直接值:

      • 不写属性:使用直接值
      • 写了属性:使用设置的那个值

定义实体

  • 语法:<!ENTITY 实体名称 "实体的值">
  • 使用实体:&实体名称;
  • 注意:定义实体需要写在内部的dtd中;如果写在外部的dtd里面,在某些浏览器下,内容得不到

XML解析值JAXP(SUN公司官方提供的API)

XML解析简介(写到Java代码)

  • xml是标记型文档
    • js使用dom解析标记型文档,根据html的层级结构,在内存中分配一个树形结构,把html的标签、属性和文本都封装成对象
    • document对象、element对象、属性对象、文本对象、Node节点对象
  • xml的解析方式(技术):dom和sax
  • dom方式解析:根据xml的层级结构,在内存中分配一个树形结构,把xml中标签、属性和文本都封装成对象
    • 缺点:如果文件过大,造成内存溢出
    • 优点:很方便实现增删改操作
  • sax解析:采用事件驱动,边读边解析。从上到下,一行一行的解析,解析到某一个对象,返回对象名称
    • 优点:不会造成内存溢出,可实现查询
    • 缺点:不能实现增删改操作
  • 想要解析xml,需要解析器。
    • 不同的公司和组织提供了针对dom和sax方式的解析器,通过api方式提供
      • sun公司提供了针对dom和sax解析器:jaxp
      • dom4j组织针对dom和sax解析器:dom4j(实际开发中最多的)
      • jdom组织针对dom和sax解析器:jdom

JAXP API的查看

  • jaxp是javase的一部分

  • jaxp解析器在jdk的java.xml.parsers包里面

    • 有四个类,分别是针对dom和sax解析的类

      • dom:

        • DocumentBuilder:解析器类

          • 这个类是一个抽象类,不能new

            此类的实例可以从DocumentBuilderFactory.newDocumentBuilder()方法获取

          • 一个方法,可以解析xml:parse(“xml路径”),返回是Document整个文档

          • 返回的document是一个接口,父节点是Node,如果在document里面找不到想要的方法,到Node里面去找

          • 在doucument里面有方法

            • getElementByTagName(String tagname)

              • 这个方法可以得到标签
              • 返回集合NodeList
            • createElement(String tagname)

              • 创建标签
            • createTextNode(String data)

              • 创建文本
            • appendChild(Node newChild)

              • 把文本添加到标签下面
            • removeChild(Node oldChild)

              • 删除节点
            • getParentNode()

              • 获取父节点
            • NodeList

              • getLength() 得到集合的长度
              • item(int index) 下标取到具体的值

              遍历:for(int i=0;i<list.getLength();i++){ list.item(i); }

            • getTextContent()

              • 得到标签里面的内容
        • DocumentBuilderFactory:解析器工厂

          • 这个类也是一个抽象类,不能new

            采用newInstance()获取DocumentBuilderFactory的实例

      • sax:

        • SAXParser:解析器类
        • SAXParserFactory:解析器工厂

使用JAXP查询节点

  • 查询xml中某一元素的所有值
    1. 创建解析器工厂
    2. 根据解析器工厂创建解析器
    3. 解析xml返回document
    4. 得到所有元素
    5. 返回集合,遍历集合,得到每一个元素的值
public static void selectAll() 
throws ParserConfigurationException, SAXException, IOException
{
    DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder bulider = builderFactory.newDocumentBuilder();
    Document document = bulider.parse("xml路径");
    NodeList list = document.getElementByTagName("标签名称");
    for(int i=0;i<list.getLength();i++)
    {
        Node name = list.item(i);
        String str = name.getTextContent();
        System.out.println(str);
    }
}

使用JAXP查询某一个节点

  • 查询xml中某一元素的某一个值
    1. 创建解析器工厂
    2. 根据解析器工厂创建解析器
    3. 解析xml返回document
    4. 得到所有元素
    5. 返回集合,利用方法item,下标获取具体的元素
    6. 得到具体的值,使用getTextContent方法
public static void selectSin() 
throws ParserConfigurationException, IOException, SAXException 
{
        DocumentBuilderFactory builderFactory =
                               DocumentBuilderFactory.newInstance();
        DocumentBuilder doucumentBuilder = builderFactory.newDocumentBuilder();
        final Document document = documentBuilder.parse("xml路径");
        NodeList list = document.getElementsByTagName("标签名称");
        Node name = list.item(标签位置-1);
        System.out.println(name.getTextContent());
}

使用JAXP添加节点

  • 在第n个A标签后(末尾)添加B标签
    1. 创建解析器工厂
    2. 根据解析器工厂创建解析器
    3. 解析xml返回document
    4. 得到第n个A标签
      • 得到所有的A标签,使用item方法下标得到
    5. 创建B标签 createElement
    6. 创建文本 createTextNode
    7. 把文本添加到B标签下面 appendChild
    8. 把B标签添加到第n个A标签下面 appendChild
    9. 回写xml
public static void addTag() 
throws ParserConfigurationException, IOException, SAXException, TransformerException 
{
        DocumentBuilderFactory documentBuilderFactory =
                               DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder =
                               documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.parse("xml路径");
        NodeList list = document.getElementsByTagName("A");
        Node p = list.item(n-1);
        Element tag = document.createElement("B");
        Text text = document.createTextNode("B的内容");
        tag.appendChild(text);
        p.appendChild(tag);
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(new DOMSource(document),
                              new StreamResult("xml路径"));
}
  • 此方法添加节点,格式有些混乱

使用JAXP修改节点

  • 修改第n个A标签下面的B的内容
    1. 创建解析器工厂
    2. 根据解析器工厂创建解析器
    3. 解析xml返回document
    4. 得到B标签 item方法
    5. 修改B标签内的值 setTextContent方法
    6. 回写xml
public static void modifyTag() 
throws ParserConfigurationException, IOException, SAXException, TransformerException {
        DocumentBuilderFactory documentBuilderFactory = 
                               DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = 
                        documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.parse("xml路径");
        Node tag = document.getElementsByTagName("B").item(n-1);
        tag.setTextContent("修改内容");
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(new DOMSource(document),
                              new StreamResult("xml路径"));
}

使用JAXP删除节点

  • 删除第n个B标签
    1. 创建解析器工厂
    2. 根据解析器工厂创建解析器
    3. 解析xml返回document
    4. 获取B标签
    5. 获取B的父节点 getParentNode()方法
    6. 利用父节点删除B removeChild方法
    7. 回写xml
public static void delTag() 
throws ParserConfigurationException, IOException, SAXException, TransformerException {
        DocumentBuilderFactory documentBuilderFactory =
                               DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = 
                        documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.parse("xml路径");
        Node tag = document.getElementsByTagName("B").item(n-1);
        Node p = tag.getParentNode();
        p.removeChild(tag);
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(new DOMSource(document),
                              new StreamResult("xml路径"));
}

使用JAXP遍历节点

  • 把xml中的所有元素名称打印出来
    1. 创建解析器工厂
    2. 根据解析器工厂创建解析器
    3. 解析xml返回document
    4. 得到根节点
    5. 得到根节点的子节点
    6. ……递归
public static void listElement() 
throws ParserConfigurationException, IOException, SAXException 
{
        DocumentBuilderFactory documentBuilderFactory = 
                               DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = 
                        documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.parse("xml路径");
        list(document);
}

private static void list(Node node) {
    if(node.getNodeType() == Node.ELEMENT_NODE)
    {
        System.out.println(node.getNodeName());
    }
    NodeList list = node.getChildNodes();
    for(int i=0;i<list.getLength();i++)
    {
        Node node1 = list.item(i);
        list(node1);
    }
}

Schema:基于XML的DTD代替者

Schema的介绍

  • schema符合xml的语法,xml语句
  • 一个xml中可以有多个schema,多个schema使用名称空间区分(类似于Java中的包名)
  • dtd里面有PCDATE类型,但在schema里面可以支持更多的数据类型
  • schema的约束更加严格,语法更加复杂,目前不能替代dtd

Schema的开发过程

  • 在< schema >文件里面是有W3C提供的属性和标签,约束xml文件

  • 创建一个schema文件 后缀名是.xsd

    • 要有xml文档声明

    • 根节点< schema > 属性:

      • xmlns=“http://www.w3.org/2001/XMLSchema”

        表示当前xml文件是一个约束文件

      • targetNamespace=“http://www.itcast.cn/20151111”

        使用schema约束文件,直接通过这个地址引入约束文件

      • elementFormDefault=“qualified”

    步骤:

    1. 看xml中有多少个元素,写几个< element name=“ ” >

    2. 看简单元素和复杂元素

      • 复杂元素

        <element name="">
            <complexType>
            	<sequence>
              	   子元素
            	</sequence>
        	</complexType>
        </element>
        
        • < sequence >:表示元素出现的顺序
        • < all >:表示元素只能出现一次
        • < choice >:元素只能出现其中的一个
      • 简单元素:写在复杂元素里

        <element name="" type=""></element>

        • < maxOccurs=“unbounded” >:表示元素出现的次数
      • <any></any>:表示任意元素

    3. 在被约束文件里面引入约束文件

      <根元素 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          
             xmlns="http://www.itcast.cn/20151111"
             xsi:schemaLocation="http://www.itcast.cn/20151111 schema路径">
      
      • xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”

        表示xml是一个被约束文件

      • xmlns=“http://www.itcast.cn/20151111”

        是约束文档里面的targetNamespace

      • xsi:schemaLocation=“http://www.itcast.cn/20151111 schema路径”>

        targetNamespace 空格 约束文档的路径

Schema约束API查看

  • 用schema约束属性
    • 写在复杂元素里面
    • 写在< /complexType >上一行
    • <attribute name="属性名称" type="属性类型" use="属性是否必须出现"></attribute>
  • 复杂的schema约束
    • 引用多个schema文件,可以给每个起一个别名
    • 在使用时通过 < 别名:标签名 >< /别名:标签名>

sax解析的过程

  • 事件驱动,边读边解析
  • 在java.xml.parsers包里面,有两个类
    • SAXParser:解析器
      • 抽象类,通过SAXParserFactory.newSAXParser()方法获得
      • 方法:
        • parse(File f,DefaultHandler dh)
          • 第一个参数是xml的路径
          • 第二个参数是事件处理器,当把时间处理器传递进来,相当于在方法里面绑定了一个事件
            1. startElement(Stirng url,String localName,String qName,Attributes attributes)
              • 开始标签自动执行
              • qName:把标签名称返回
            2. characters(char[] ch,int start,int length) //String的构造方法
              • 文本自动执行
              • 返回文本内容
            3. endElement(String url,String localName,String qName)
              • 结束标签自动执行
              • qName:把标签名称返回
    • SAXParserFactory:解析器工厂
      • 抽象类,实例通过newInstance()方法得到
  • sax的解析过程
    • 当解析到开始标签时,自动执行startElement方法
    • 当解析到文本时,自动执行characters方法
    • 当解析到结束标签时,自动执行endElement方法

使用jaxp的sax方式操作xml

  • sax方式不能实现增删改操作,只能实现查询操作

  • 查询步骤

    1. 创建解析器工厂
    2. 创建解析器
    3. 执行parse方法
    4. 自己创建一个类,继承DefaultHandler
    5. 重写类里面的三个方法
    public static void CheckAll() 
    throws ParserConfigurationException, SAXException, IOException 
    {
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            SAXParser saxParser = saxParserFactory.newSAXParser();
            saxParser.parse("xml路径",new MyDefault());
    }
    class MyDefault extends DefaultHandler{
        @Override
        public void startElement(String uri, String localName, String qName, 
                                 Attributes attributes) throws SAXException 
        {
        	TODO
        }
    
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException     {
        	TODO
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) 
        throws SAXException
        {
        	TODO
        }
    }
    
    
  • 打印出整个文档

class MyDefault1 extends DefaultHandler{
    @Override
    public void startElement(String uri, String localName, String qName, 
                             Attributes attributes) throws SAXException 
    {
        System.out.print("<"+qName+">");
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException 
    {
        System.out.print(new String(ch,start,length));
    }

    @Override
    public void endElement(String uri, String localName, String qName) 
    throws SAXException 
    {
        System.out.print("</"+qName+">");
    }
}

  • 获取所有A标签的值
    • 定义一个成员变量flag=false
      1. 判断开始方法是否是A元素,如果是flag=true
      2. 如果flag是true,在characters方法里面打印内容
      3. 当执行到结束方法时,把flag设置成false
class MyDefault2 extends DefaultHandler{
    boolean flag = false;
    
    @Override
    public void startElement(String uri, String localName, String qName, 
                             Attributes attributes) throws SAXException 
    {
        if("A".equals(qName))
        {
            flag = true;
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException 
    {
        if(flag == true)
        {
            System.out.println(new String(ch,start,length));
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) 
    throws SAXException 
    {
        if("A".equals(qName))
        {
            flag =false;
        }
    }
}

  • 获取第n个A标签的值
    • 定义一个成员变量idex=0
      1. 在开始方法时,判断自增
      2. 在characters方法中判断flag和idex,再打印
class MyDefault2 extends DefaultHandler{
    boolean flag = false;
    int idex=0;
    
    @Override
    public void startElement(String uri, String localName, String qName, 
                             Attributes attributes) throws SAXException 
    {
        if("A".equals(qName))
        {
            flag = true;
            idex ++;
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException 
    {
        if(flag == true && idex==n)
        {
            System.out.println(new String(ch,start,length));
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) 
    throws SAXException 
    {
        if("A".equals(qName))
        {
            flag =false;
        }
    }
}

XML解析之dom4j

dom4j的简介

  • dom4j是一个组织,针对xml解析,提供解析器dom4j

  • dom4j不是javase的一部分,

    • 在使用时要先导入dom4j提供的jar包

      • src下创建文件夹lib
      • 复制jar包到lib下
      • project structure>>module>>dependencies>>+jar包路径
    • 得到doucument

      SAXReader reader = new SAXReader();
      Document document = reader.read(url);
      
      • document的父接口是Node

        如果在document里面找不到想要的方法,到Node里面去找

      • doucument里面的方法:getRootElement():获取根节点,返回的是Element

      • Element也是一个接口,父接口是Node

        • Element和Node里面的方法:
          1. getParent():获取父节点
          2. addElement():添加一个标签

使用dom4j实现查询xml操作

  • 解析是从上到下进行解析的

  • 方法:

    • element(qname)
      • 表示获取标签下面的第一个子标签
      • qname:标签的名称
    • elements(qname)
      • 获取标签下面是这个名称的所有子标签(一层)
      • qname:标签名称
    • elements()
      • 获取标签下面的所有一层子标签
  • 查询所有A元素里面的值

    1. 创建解析器
    2. 得到document
    3. 得到根节点 getRootElement(),返回Element
    4. 得到的根节点的子节点
      • elements(qname)
        • 返回list集合
        • 遍历
    5. ……得到A标签
      • 在其父标签下执行element(qname)方法,返回Element
    6. 得到A标签的值
      • getText方法得到值
    public static void selectTag() throws DocumentException 
    {
            SAXReader saxReader = new SAXReader();
            Document document =  saxReader.read("xml路径");
            Element root = document.getRootElement();
            List<Element> list = root.elements("A标签的父标签");
            for(Element element : list)
            {
                Element name1 = element.element("A");
                String str = name1.getText();
                System.out.println(str);
            }
    }
    
  • 查询第n个A元素的值

    1. 创建解析器
    2. 得到document
    3. 得到根节点 getRootElement(),返回Element
    4. 得到的根节点的第n个子节点
      • 使用list下标得到
    5. ……得到A标签
      • 在其父标签下执行element(qname)方法,返回Element
    6. 得到A标签的值
      • getText方法得到值
    public static void selectSin() throws DocumentException
    {
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read("xml路径");
            Element root = document.getRootElement();
            List<Element> list = root.elements("A的父元素 ");
            Element name = list.get(n-1).element("A");
            String str = name.getText();
            System.out.println(str);
    }
    

使用dom4j实现在末尾添加节点的操作

  • 在第n个A标签末尾添加B元素

    1. 创建解析器
    2. 得到document
    3. 得到根节点
    4. 获取到A标签 elements方法
    5. 在A标签下添加元素 addElement方法,返回一个Element
    6. 在添加完成之后的元素下面添加文本 addTest方法
    7. 回写
      • 格式化 OutputFormat,使用createPrettyPrinter方法,表示一个漂亮的格式
      • 使用类XMLWriter 直接new这个类,传递两个参数
        • 第一个参数是xml文件路径 new FileOutputStream(“路径”)
        • 第二个参数是格式化类的值
    public static void addTag() throws DocumentException, IOException 
    {
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read("xml路径");
            Element root = document.getRootElement();
            List<Element> list = root.elements("A");
            Element TagName = list.get(n-1).addElement("B");
            TagName.addText("B的内容");  
            OutputFormat fomcat =OutputFormat.createPrettyPrint();
            XMLWriter xmlWriter =
                new XMLWriter(new FileOutputStream("xml路径"),fomcat);
            xmlWriter.write(document);
            xmlWriter.close();
    }
    

使用dom4j实现在待定位置添加节点的操作

  • 在第n个A标签下的B标签前添加C标签

    1. 创建解析器
    2. 得到document
    3. 得到根节点
    4. 获取到A标签 elements方法
    5. 获取A标签下的所有元素
      • elements()方法,返回list集合
      • 使用list里面的方法,在特定位置添加元素
      • 创建元素,在元素下创建文本
        • add(int index,E element)
        • 第一个元素是位置下标,从0开始
        • 第二个参数是要添加的元素
    6. 回写xml
    public static void addTagBefore() throws DocumentException, IOException 
    {
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read("xml路径");
            Element root = document.getRootElement();
            List<Element> list = root.elements("A");
            List<Element> list1 = list.get(n-1).elements();
            Element TagName = DocumentHelper.createElement("C");
            TagName.setText("C的内容");
            list1.add(B标签的位置,TagName);
            OutputFormat format = OutputFormat.createPrettyPrint();
            XMLWriter xmlWriter = 
                new XMLWriter(new FileOutputStream("xml路径"),format);
            xmlWriter.write(document);
            xmlWriter.close();
    }
    

dom4j里面封装方法的操作

  • 可以对得到document的操作和回写xml的操作,都封装成方法
  • 也可以把传递的文件路径,封装成一个常量
  • 封装的好处
    1. 可以提高开发速度
    2. 可以提高代码的可维护性

使用dom4j实现修改的操作

  • 修改第n个A标签下B元素的值

    1. 得到document
    2. 得到根节点
    3. 得到第n个A元素 elements方法
    4. 得到A元素下的B元素
    5. 修改值 setText方法
    6. 回写xml
    public static void modifyTag() 
    throws DocumentException, SAXException, IOException 
    {
            Document document = Dom4jUtils.getDocument(PATH);
            Element root = document.getRootElement();
            List<Element> list = root.elements("A");
            Element TagName = list.get(n-1).element("B");
            TagName.setText("修改值");
            Dom4jUtils.xmlWriters(PATH,document);
    }
    

使用dom4j实现删除节点的操作

  • 删除第n个A标签下的B元素

    1. 得到document
    2. 得到根节点
    3. 得到第n个A元素 elements方法
    4. 得到A元素下的B元素
    5. 删除(使用A标签删除B标签)
      • 得到B的父节点
        • 直接用A
        • 使用方法getParent得到
      • 删除操作
        • 在A标签上执行remove方法
    6. 回写xml
    public static void delTag() 
    throws DocumentException, SAXException, IOException 
    {
            Document document = Dom4jUtils.getDocument(PATH);
            Element root = document.getRootElement();
            List<Element> list = root.elements("A");
            Element TagName = list.get(n-1).element("B");
            list.get(n-1).remove(TagName);
            Dom4jUtils.xmlWriters(PATH,document);
    }
    

使用dom4j实现获取属性值的操作

  • 获取第n个A标签里面的属性B的值

    1. 得到document
    2. 得到根节点
    3. 得到第n个A元素
    4. 得到A元素里面的属性值
      • 使用attributeValue("")方法
      • 在A元素上执行这个方法,里面的参数是属性名称
    public static void getValues() throws DocumentException, SAXException 
    {
            Document document = Dom4jUtils.getDocument(PATH);
            Element root = document.getRootElement();
            List<Element> list = root.elements("A");
            String value = list.get(n-1).attributeValue("B");
            System.out.println(value);
    }
    

XPATH

XPATH简介

  • 可以直接获取到某个元素‘
  • 是一种书写形式(表达式)
  • 第一种书写形式:
    • /AAA/DDD/BBB/
    • 表示一层一层的,AAA下面DDD下面BBB
  • 第二种书写形式:
    • //BBB
    • 表示和这个名称相同,表示只要名称是BBB,都得到
  • 第三种书写形式:
    • /*
    • 表示所有元素
  • 第四种形式
    • BBB[1]:表示第一个BBB元素
    • BBB[last]:表示最后一个BBB元素
  • 第五种形式
    • //BBB[@id]
    • 表示只要BBB上有id属性,都得到
  • 第六种形式
    • //BBB[@id='a']
    • 表示元素名称是BBB,在BBB上面有id属性,且id属性的值是a

使用dom4j支持XPATH的操作

  • 默认情况下,dom4j不支持xpath

  • 如果想要在dom4j中使用xath

    • 第一步需要引入支持xpath的jar包,使用jaxen-1.1-beta-6.jar
      • 需要把jar包导入到项目中
  • 在dom4j里面提供了两个方法,用来支持xpath

    • selectNodes(“xpath表达式”)
      • 获取多个节点
    • selectSingleNode(“xpath表达式”)
      • 获取一个节点
  • 使用xpath实现,查询xml中所有A元素的值

    1. 得到所有的document
    2. 所有A元素的xpath表示://A
    3. 使用selectNodes("//A")
    public static void selectAll() throws DocumentException, SAXException 
    {
            Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
            List<Node> list = document.selectNodes("//A");
            for (Node node : list)
            {
                String str = node.getText();
                System.out.println(str);
            }
    }
    
  • 使用xpath实现:获取第1个A标签下B标签的值

    1. 得到document
    2. 第1个A标签下B标签的xpath表示://A[1]/B
    3. 使用selectSingleNode("//A[1]/B")
    public static void selectSin() throws DocumentException, SAXException 
    {
            Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
            Node node = document.selectSingleNode("//A[1]/B");
            String str = node.getText();
            System.out.println(str);
    }
    

案例

  • 使用xml当做数据库,存储学生信息
  • 创建一个xml文件,写一些学生信息

学生管理系统实现-添加操作

  1. 创建解析器
  2. 得到document
  3. 获取到根节点
  4. 在根节点上面创建stu标签
  5. 在stu标签上面依次添加 id name age
  6. 在id name age上面依次添加值
  7. 回写xml

学生管理系统实现-删除操作

  • 根据学生的id删除

    1. 创建解析器

    2. 得到document

    3. 获取所有id

      使用xpath //id 返回list集合

    4. 遍历list集合

    5. 判断集合里面的id和传递的id是否相同

    6. 如果相同,把id所在的stu删除

学生管理系统实现-查询操作

  • 根据id进行查询

    1. 创建解析器

    2. 得到document

    3. 获取所有id

      使用xpath //id 返回list集合

    4. 遍历list集合

    5. 得到每一个id的节点

    6. id节点的值

    7. 判断集合里面的id和传递的id是否相同

    8. 如果相同,先获取到id的父节点stu

    9. 通过stu获取到name age的值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值