• W5-xml基础知识二[JavaWeb]


    1.schema约束

      1.1 schema符合xml的语句,一个xml中可以有多个schema,多个schema使用名称空间区分(类似于java包名)

      1.2 dtd里面有PCDATA类型,但是在schema里面可以支持更多的数据类型

        -例如:年龄只能是整数,在schema中可以直接定义一个整数类型

      1.3 schema语法更加复杂,目前不能替代dtd

    2.schema的快速入门

      2.1 创建schema文件,后缀名是.xsd,根节点是<schema>

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

       -属性

         xmlns="http://www.w3.org/2001/XMLSchema"表示当前xml文件是一个约束文件

         targetNamespace="http://www.example.org/1"使用schema约束文件,直接通过这个地址引入约束文件

         elementFormDefault="qualified" 表示schema文件质量良好

      (1)步骤:

        -看xml中有多少个文件 <element>

        -看简单元素还是复杂元素(person为复杂元素)

    <element name="person">
        <complexType>
            <sequence>
                <element name="name" type="string"></element>
                <element name="age" type="int"></element>
            </sequence>
        </complexType>
    </element>

        -简单元素需要在复杂元素里面

        -在被约束文件中引入约束文件

          xlmns:xsi="http://www.w3.org/2001/XMLSchema-instance"表示xml是一个被约束文件

          xmlns="http://www.example.org/1"是约束文档中targetNamespace
          xsi:schemaLocation="http://www.example.org/1 1.xsd" 
    targetNamespace 空格 约束文档路径

    <?xml version="1.0" encoding="UTF-8"?>
    <person xlmns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.example.org/1"
    xsi:schemaLocation="http://www.example.org/1 1.xsd">
        <name>zhangsan</name>
        <age>20</age>
    </person>>

      (2)复杂元素的指示器

        <sequence></sequence> :表示元素依照顺序出现

        <all></all>:表示元素只能出现一次

        <choice></choice>:表示只能出现其中一个元素

        <maxOccurs=“”></maxOccurs>:表示元素最多能出现的次数,unbound表示无限次数

        <any></any>:表示任意元素

      (3)可约束属性

        -写在复杂元素里面,写在</complexType>之前,name表示属性名称,type表示属性类型int或string,use表示属性是否必须出现

    <attribute name="id1" type="int" use="required"></attribute>

       (4)引入多个schema文件,可以给每个起一个别名

    3.sax解析的原理

      3.1 解析xml的两种技术dom和sax

      -sax的解析方式:事件驱动,边读边解析

        --当解析到开始标签的时候,自动执行startElement方法,参数qName返回标签名称

        --当解析到文本内容的时候,自动执行character方法,通过string的构造方法返回内容

        --当解析到结束标签的时候,自动执行endELement方法,参数qName,返回标签名称

      -在javax.xml.parsers包下

        --SAXParser 此类的实例可以从SAXParserFactory.newsSAXParser() 方法获得

              ---parse(File f, DefaultHandler dh)

        -- SAXParserFactory 实例 newInstance()方法获得

      3.2 使用jaxp的sax方式解析xml

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

    package cn.itcast.jaxpsax;
    
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    public class TestSax {
    
        /**
         * @param args
         */
        public static void main(String[] args)throws Exception {
            // TODO Auto-generated method stub
            /*
             * 1.创建解析器工厂
             * 2.创建解析器
             * 3.执行parse方法
             * 4.自行创建一个类,继承DefaultHandler,重写三个方法
             */
            //创建解析器工厂
            SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();
            //创建解析器
            SAXParser saxParser=saxParserFactory.newSAXParser();
            //执行parse方法
            saxParser.parse("src/p1.xml", new MyDefault());
        }
    
    }
    
    class MyDefault extends DefaultHandler{
    
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            System.out.print("<"+qName+">");
        }
    
        @Override
        public void endElement(String uri, String localName, String qName)
                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));
        }
        
    }

      (2)获取到所有的name元素的值

    //实现获取所有的name元素的值、
    class MyDefault1 extends DefaultHandler{
        boolean flag=false;
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            //判断qName是否是name元素
            if("name".equals(qName)){
                flag=true;
            }
        }
    
        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            //把flag设置成false,把name元素结束
            if("name".equals(qName)){
                flag=false;
            }
        }
    
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            //当flag值是true时,表示解析到name元素
            if(flag==true){
                System.out.println(new String(ch,start,length));            
            }
        }
        
    }

      (3)获取第一个name元素的值,添加索引即可

    4.使用dom4j解析xml

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

        -dom4j不是javase的部分,因此需要导包(创建文件夹lib,右键复制jar包到lib下面,右键点击jar包,build path--add to buildpath)

        -得到document文件

     SAXReader reader = new SAXReader();
     Document document = reader.read(url);

        -document的父接口是Node,如果在document里面找不到想要的方法,到Node里面去找

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

        -element也是一个接口,父节点是Node

          -Element和Node里面方法:

          --getParent():获取父节点

          --addElement:添加标签

      4.2 使用dom4j查询xml

    package cn.itcast.dom4j;
    
    import java.io.IOException;
    import java.util.List;
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    public class TestDom4j {
        public static void main(String[] args)throws Exception {
            // TODO Auto-generated method stub
            selectSin();
        }
        //查询xml中所有name元素的值
        /*
         * 1.创建解析器
         * 2.得到document
         * 3.得到根节点 getRootElement()
         * 4.得到所有的p1标签
         *         element(qname):表示获取标签下面的第一个子标签,qname是标签的名称
         *         elements(qname):获取标签下面是qname名称的所有子标签(一层)
         *         elements():获取标签下面的所有一层子标签
         * 5.得到name
         * 6.得到name里面的值
         */
        public static void selectName()throws Exception{
            //创建解析器
            SAXReader saxReader=new SAXReader();
            //得到document
            Document document=saxReader.read("src/p1.xml");    
            //获取根节点
            Element root=document.getRootElement();
            //得到所有的p1标签
            List<Element> list=root.elements("p1");
            //遍历list
            for(Element element:list){
                //element是每一个p1元素
                //得到p1下面的name元素
                Element name=element.element("name");
                //得到name元素里面的内容
                String s=name.getText();
                System.out.println(s);
            }    
        }
        
        //获取到第一个name元素的值
        /*
         * 1.创建解析器
         * 2.得到document
         * 3.得到根节点 getRootElement()
         * 4.得到第一个p1元素
         * 5.得到p1下面的name元素
         * 6.得到name元素里面的值
         */
        public static void selectSin()throws Exception{
            //得到解析器
            SAXReader saxReader=new SAXReader();
            //得到document
            Document document=saxReader.read("src/p1.xml");
            //得到根节点
            Element root=document.getRootElement();
            //得到第一个p1元素
            Element element=root.element("p1");
            //得到p1元素下的name元素
            Element nameele=element.element("name");
            //得到name元素的内容
            String names=nameele.getText();
            System.out.println(names);        
        }
    }

      4.3 使用dom4j实现增加

    //在第一个p1下面的age标签之前添加<school>ecit.edu.cn</school>
        /*
         * 1.创建解析器
         * 2.得到document
         * 3.得到根节点
         * 4.获取第一个p1
         * 5.获取p1下面的所有元素 elements()方法 返回list集合;使用list里面的方法,在特定位置添加的方法add(int index,Element e)
         * 6.回写xml
         * 
         */
        public static void addAgeBefore()throws Exception{
            //创建解析器
            SAXReader saxReader=new SAXReader();
            //得到document
            Document document=saxReader.read("src/p1.xml");
            //得到根节点
            Element root=document.getRootElement();
            //得到第一个p1
            Element element=root.element("p1");
            //得到p1下面所有的元素
            List<Element> list=element.elements();
            //创建元素
            Element school=DocumentHelper.createElement("school");
            //在元素下面创建文本
            school.setText("ecit.edu.cn");
            list.add(1,school);
            //回写
            OutputFormat format=OutputFormat.createPrettyPrint();
            XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("src/p1.xml"),format);
            xmlWriter.write(document);
            xmlWriter.close();
        }
        
        //在第一个p1标签末尾添加一个元素<sex>nv</sex>
        /*
         * 1.创建解析器
         * 2.得到document
         * 3.得到根节点
         * 4.获取第一个p1
         * 5.在p1下面添加元素
         * 6.在添加完成之后的元素下面添加文本
         * 7.回写xml
         */
        public static void addSex()throws Exception{
            //创建解析器
            SAXReader saxReader=new SAXReader();
            //得到document
            Document document =saxReader.read("src/p1.xml");
            //得到根节点
            Element root=document.getRootElement();
            //获取第一个p1
            Element p1=root.element("p1");
            //在p1下面直接添加元素
            Element sexnode=p1.addElement("sex");
            //在sex下面直接添加文本
            sexnode.addText("nv");
            //回写xml
            OutputFormat format=OutputFormat.createPrettyPrint();//有缩进的效果
            XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("src/p1.xml"),format);
            xmlWriter.write(document);
            xmlWriter.close();    
        }

       4.4 将dom4j中的方法进行封装

    package cn.itcast.dom4j;
    
    import java.io.FileOutputStream;
    
    import org.dom4j.Document;
    import org.dom4j.io.OutputFormat;
    import org.dom4j.io.SAXReader;
    import org.dom4j.io.XMLWriter;
    
    
    public class Dom4jUtils {
        public static final String PATH="src/p1.xml";
        //返回document
        public static Document getDocument(String path){
            //创建解析器
            SAXReader saxReader=new SAXReader();
            //得到document
            try{
                Document document=saxReader.read(path);    
                return document;
            }catch(Exception e){
                e.printStackTrace();
            }
            return null;
        }
        //回写xml的方法
        public static void xmlWriters(String path,Document document){
            try{
                OutputFormat format=OutputFormat.createPrettyPrint();//有缩进的效果
                XMLWriter xmlWriter=new XMLWriter(new FileOutputStream(path),format);
                xmlWriter.write(document);
                xmlWriter.close();                
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

       4.5 使用dom4j修改xml

    //修改第一个p1元素下面的age元素的内容 20->30
        /*
         * 1.得到document
         * 2.得到第一个p1元素
         * 3.得到第一个p1下面的age
         * 4.修改值是30
         * 5.回写xml
         */
        public static void modifyAge() throws Exception{
            //得到document
            Document document=Dom4jUtils.getDocument(Dom4jUtils.PATH);
            //得到第一个元素p1
            Element rootele=document.getRootElement();
            Element p1ele=rootele.element("p1");
            //得到p1下面的age元素
            Element ageEle=p1ele.element("age");
            //修改age的值
            ageEle.setText("30");
            Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document);
        }

      4.6 使用dom4j删除节点的操作

    //删除第一个p1元素下面的school元素
        /*
         * 1.得到document
         * 2.得到根节点
         * 3.得到第一个p1标签
         * 4.得到第一个p1标签下面的school标签
         * 5.使用p1删除school
         * 6.回写xml
         */
        public static void delSch()throws Exception{
            //得到document
            Document document=Dom4jUtils.getDocument(Dom4jUtils.PATH);
            //得到根节点
            Element root=document.getRootElement();
            //得到第一个p1元素
            Element p1Ele=root.element("p1");
            //得到第一个p1元素下面的school
            Element schEle=p1Ele.element("school");
            //删除节点
            p1Ele.remove(schEle);
            //回写xml
            Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document);
        }

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

    //获取第一个p1里面的属性id的值
        /*
         * 1.得到document
         * 2.得到根节点
         * 3.得到第一个p1元素
         * 4.得到p1里面的属性
         */
        public static void getValues()throws Exception{
            //得到document
            Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
            // 得到根节点
            Element root = document.getRootElement();
            // 得到第一个p1元素
            Element p1Ele = root.element("p1");
            //得到p1里面的属性
            String value=p1Ele.attributeValue("id");
            System.out.println(value);
            
        }

       4.8 使用dom4j支持xpath的操作

      (1)可以直接获得某元素,不需要层层解析

      (2)xpath的第一种形式:/AAA/DDD/BBB :表示一层一层的,AAA下面的 DDD下面的BBB

          xpath的第二种形式://BBB:表示和这个名称相同,只要名称是BBB,都可以得到

          xpath的第三种形式://*:所有元素

          xpath的第四种形式:/BBB[1]:表示第一个BBB元素

                  /BBB[last]:表示最后一个BBB元素

          xpath的第五种形式://BBB[@id]:表示BBB上有id属性的都可以得到

          xpath的第六种形式://BBB[@id='b1']:表示元素的名称是BBB,在BBB上面有id属性,属性名称为b1

      (3)具体操作,默认情况下,dom4j不支持xpath

        step1:引入支持xpath的jar包,使用  jaxen-1.1-beta-6.jar

        step2:在dom4j中提供两个方法支持xpath

            -selectNodes("xpath表达式")  获取多个节点

            -selectSingleNode("xpath表达式")  获取单个节点

      (4)源码

    package cn.itcast.dom4j;
    
    import java.util.List;
    
    import org.dom4j.Document;
    import org.dom4j.Node;
    
    public class TestDom4jXpath {
    
        /**
         * @param args
         */
        public static void main(String[] args)throws Exception {
            // TODO Auto-generated method stub
            test2();
        }
        //使用xpath实现获取第一个p1下面的那么的值
        public static void test2()throws Exception{
            /*
             * 1.得到document
             * 2.直接使用selectSingleNode("//p1[@id='aaaa']/name")方法得到name元素
             */
            //得到document
            Document document=Dom4jUtils.getDocument(Dom4jUtils.PATH);
            Node node=document.selectSingleNode("//p1[@id='aaaa']/name");
            System.out.println(node.getText());
        }
        
        //查询xml中所有那么元素的值
        public static void test1()throws Exception{
            /*
             * 1.得到document
             * 2.直接使用selectNodes("//name")方法得到所有的name元素
             */
            //得到document
            Document document=Dom4jUtils.getDocument(Dom4jUtils.PATH);
            List<Node> list=document.selectNodes("//name");
            //遍历list集合
            for (Node node : list) {
                System.out.println(node.getText());
            }
        }
    }
  • 相关阅读:
    protobuf(Protocol Buffers)java初体验
    排序(6)---------归并排序(C语言实现)
    JSP/Servlet-----charset 、pageEncoding差别
    [Android] Android开发优化之——对界面UI的优化(2)
    [Android] Android开发优化之——对界面UI的优化(1)
    [Android] Android开发优化之——从代码角度进行优化
    Android开发优化之——对Bitmap的内存优化
    Java 如何有效地避免OOM:善于利用软引用和弱引用
    开源中国源码学习(八)——枚举类
    Android ADB server didn't ACK * failed to start daemon * 简单有效的解决方案
  • 原文地址:https://www.cnblogs.com/ERFishing/p/11221023.html
Copyright © 2020-2023  润新知