XML*

作者: 望町 | 来源:发表于2018-01-06 16:52 被阅读0次

    目录

    • XML简介
    • XML基本语法
    • XML解析
       * DOM解析
         * DOM解析原理及工具
         * DOM4J解析工具用法及示例
         * xPath技术
       * SAX解析
         * SAX解析工具
         * SAX解析原理
         * SAX解析工具用法及示例
       * SAX解析与DOM解析的区别
    • XML约束
       * 引入
       * XML约束技术
       * DTD约束
       * Schema约束

    XML简介

    XML(Extend Markup Language)是一种标记语言,被用来格式化的传输数据
    示例

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <?xml-stylesheet type = "text/css">
    <!--this is content-->
    <CATALOG>
      <CD id = "132">
        <TITLE>Empire Burlesque</TITLE>
        <ARTIST>Bob Dylan</ARTIST>
        <COUNTRY>USA</COUNTRY>
        <COMPANY>Columbia</COMPANY>
        <PRICE>10.90</PRICE>
        <YEAR>1985</YEAR>
      </CD>
    </CATALOG>
    

    其中:

    • <?xml version="1.0" encoding="ISO-8859-1"?>声明了XML的版本(version)以及编码方式(encoding)
    • <?xml-stylesheet type = "text/css"> 处理指令,告诉XML解析如何解析XML文件,type的值表示对应的css文件
    • < !--this is content-->是注释
    • <CATALOG></CATALOG>是一对标签它们的名字可以自己定义,其中<CATALOG>是开始标签,</CATALOG>是关闭标签
    • <CD id = "132"> id是CD的属性
    • <PRICE>10.90</PRICE> 10.90是标签的内容
    • xml描述了一种树形结构 CATALOG是根,CD是CATALOG的子节点;TITLE,ARTIST,COUNTRY等是CD的子节点

    XML基本语法

    一、XML对大小写敏感
    二、所有XML标签都必须有关闭标签
    三、头尾标签名应该一样
    四、属性值必须加引号
    五、在 XML 中,空格会被保留(XML中多个空格只会保留一个)
    六、实体引用(转义字符)

    • 在 XML 中,一些字符拥有特殊的意义。如果你把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。这样会产生 XML 错误:
      解决办法:


      实体引用.PNG
    • CDATA块,让一些需要进行原样输出的内容中的特殊字符原样输出。
    <![CDATA[<html><head></head><body></body></html>]]>
    

    DOM解析

    1)DOM解析原理
    DOM解析XML文档时,XML解析器一次性吧整个XML文档加载进内存,然后在内存中构建一棵Document对象树,通过Document对象,可以得到下面的节点对象,通过节点对象访问数据
    2)DOM解析工具

    • JAXP (oracle-Sun公司官方)
    • JDOM工具(非官方)
    • Dom4J工具(非官方)(三大框架默认读取xml的工具就是Dom4j)
    DOM4J解析工具

    需要导包使用

    1)dom4j结构


    domj4.png

    2)dom4j读取xml文件
    节点:

    • Iterator Element.nodeIterator(); //获取当前标签节点下的所有子节点

    标签:

    • Element Document.getRootElement(); //获取xml文档的根标签
    • Element ELement.element("标签名") //指定名称的第一个子标签
    • Iterator<Element> Element.elementIterator("标签名");// 指定名称的所有子标签
    • List<Element> Element.elements(); //获取所有子标签

    属性:

    • String Element.attributeValue("属性名") //获取指定名称的属性值
    • Attribute Element.attribute("属性名");//获取指定名称的属性对象
    • Attribute.getName() //获取属性名称
    • Attibute.getValue() //获取属性值
    • List<Attribute> Element.attributes(); //获取所有属性对象
    • Iterator<Attribute> Element.attibuteIterator(); //获取所有属性对象

    文本:

    • Element.getText(); //获取当前标签的文本
    • Element.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容

    示例1:利用dom4j输出一个xml文件

    public class Demo1 {
        @Test
        public void test()throws Exception {
            SAXReader  reader = new SAXReader();
            Document document = reader.read(new File("./src/contact.xml"));
            //获得根标签
            Element element = document.getRootElement();
            StringBuffer sb = new StringBuffer();
            //用此方法遍历整个xml文件(先根遍历形式)
            getchild(element,sb);
            System.out.println(sb.toString());
            }
    
        private void getchild(Element element, StringBuffer sb) {
            // TODO Auto-generated method stub
            sb.append("<"+element.getName());
            //获得标签的所有属性
            List<Attribute> attrs = element.attributes();
            //输出标签属性
            if(attrs!=null) {
                for (Attribute attribute : attrs) {
                    sb.append(" "+attribute.getName()+"=\""+attribute.getValue()+"\"");
                }
            }
            sb.append(">");
            //获得当前标签下的所有子标签
            Iterator<Node> iterator= element.nodeIterator();
            while(iterator.hasNext()) {
                Node node = iterator.next();
                //输出标签
                if(node instanceof Element) {
                    Element e = (Element)node;
                    getchild(e,sb);
                }
                //输出文本
                if(node instanceof Text) {
                    Text text = (Text)node;
                    sb.append(node.getText());
                }
            }
            sb.append("</"+element.getName()+">");  
        }
    }
    

    示例2:把xml获取的信息封装到对象内

    /**
     * 把xml封装到对象中
     *
     */
    public class Demo2 {
        @Test
        public void test2() throws Exception{
            SAXReader reader = new SAXReader();
            Document doc = reader.read(new File("./src/contact.xml"));
            Element elem = doc.getRootElement();
            Iterator<Element> it = elem.elementIterator();
            ArrayList<Contact> contacts = new ArrayList();
            while(it.hasNext()) {
                Contact contact = new Contact();
                Element element = it.next();
                contact.setId(element.attributeValue("id"));
                contact.setAge(element.elementText("age"));
                contact.setPhone(element.elementText("phone"));
                contact.setEmail(element.elementText("email"));
                contact.setQq(element.elementText("qq"));
                contacts.add(contact);
            }
            
            for(Contact contact:contacts) {
                System.out.println(contact);
            }
        }
    }
    

    3) 修改xml文件
    增加:

    • DocumentHelper.createDocument() 增加文档
    • addElement("名称") 增加标签
    • addAttribute("名称",“值”) 增加属性

    修改:

    • Attribute.setValue("值") 修改属性值
    • Element.addAtribute("同名的属性名","值") 修改同名的属性值
    • Element.setText("内容") 修改文本内容

    删除

    • Element.detach(); 删除标签
    • Attribute.detach(); 删除属性

    写入

    • OutputFormat.createPrettyPrint() 创建易读的xml文件
    • OutputFormat.createCompactFormat() 创建紧凑的xml文件
    • format.setEncoding("编码方式");设置编码方式
    • XMLWriter(OutputStream out,OutPutformat format) 设置写入方式
    • XMLWriter.write 写入内容

    写入基本流程:首先创构建一个空的Document对象,然后向其中按照节点关系添加标签(根标签只能有一个),然后创建文件输出流,指定输出格式,利用XMLWriter对象设置格式和写入内容,最后关闭writer对象。

    示例3:创建文件并写入一个简单的XML文档:

    
    ************
    /**
     * 生成xml文档
     *
    <Students>
    <Student id="1">
        <name>张三</name>
        <gender>男</gender>
        <grade>计算机1班</grade>
        <address>广州天河</address>
    </Student>
    <Student id="2">
        <name>李四</name>
        <gender>女</gender>
        <grade>计算机2班</grade>
        <address>广州越秀</address>
    </Student>
    </Students>
     *
     */
    public class Demo3 {
        @Test
        public void test() throws Exception {
            //在内存创建Document文档
            Document doc = DocumentHelper.createDocument();
            //写入内容
            Element rootElement = doc.addElement("Students");
            //增加第二层标签
            Element studentElem = rootElement.addElement("Student");
            //增加属性
            studentElem.addAttribute("id", "1");
            //添加第三层标签
            studentElem.addElement("name").setText("张三");
            studentElem.addElement("gender").setText("男");
            studentElem.addElement("grade").setText("计算机一班");
            studentElem.addElement("address").setText("广州天河");
            //增加第二个二层标签
            Element studentElemnt2 = rootElement.addElement("Student");
            studentElemnt2.addAttribute("id", "2");
            //为第二个二层标签添加子标签
            studentElemnt2.addElement("name").setText("李四");
            studentElemnt2.addElement("gender").setText("女");
            studentElemnt2.addElement("grade").setText("计算机二班");
            studentElemnt2.addElement("address").setText("广州越秀");
            
            //将内容写出到文件
            //创建输出流
            FileOutputStream out = new FileOutputStream(new File("f:/student.xml"));
            //指定输出方式
            OutputFormat format = OutputFormat.createPrettyPrint();
            //指定编码方式
            format.setEncoding("utf-8");
            XMLWriter writer = new XMLWriter(out,format);
            //写出内容
            writer.write(doc);
            //关闭资源
            writer.close();
        }
    }
    

    示例4:修改、删除xml文件

    /**
     * 修改id为2的学生的姓名+删除id为2的学生标签
     *
     */
    public class Demo3 {
        @Test
        public void test() throws Exception {
            //将XML文件载入为document对象
            Document document = new SAXReader().read(new File("f:/student.xml"));
            //获取所有Student标签
            Iterator<Element> it = document.getRootElement().elementIterator("Student");
            //查询id为2的学生
            while(it.hasNext()) {
                Element elem = it.next();
                System.out.println(elem.attribute("id").getValue());
                if(elem.attributeValue("id").equals("2")) {
                    //修改姓名
                    //elem.element("name").setText("王丽");
                    //删除该学生标签
                    elem.detach();
                    break;
                }
            }
            
            FileOutputStream out = new FileOutputStream("f:/student.xml");
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("utf-8");
            XMLWriter writer = new XMLWriter(out,format);
            writer.write(document);
            writer.close();
        }
    }
    

    4)xPath技术

    当使用dom4j查询比较深的层次节点时比较麻烦,xPath技术可以使我们快速获得深层次节点
    使用xPath的方法需要导入dom4j文件夹下的jaxen-1.1-beta-6.jar包。

    xPath语法:
    Xpath语法类似于在一个文件系统中定位文件
    W3C的Xpath语法教程:http://www.w3school.com.cn/xpath/xpath_syntax.asp

    • / 绝对路径 表示从xml的根位置开始或子元素(一个层次结构)
    • // 相对路径 表示不分任何层次结构的选择元素。
    • * 通配符 表示匹配所有元素
    • [] 条件 表示选择什么条件下的元素
    • @ 属性 表示选择属性节点
    • and 关系 表示条件的与关系(等价于&&)
    • text() 文本 表示选择文本内容

    在DOM4J中的使用方法:

    • List<Node> selectNodes("xpath表达式"); 查询多个节点对象
    • Node selectSingleNode("xpath表达式"); 查询一个节点对象

    SAX解析

    1)SAX解析工具
    SAX解析工具- Sun公司提供的。内置在jdk中。org.xml.sax.*
    2)SAX解析原理
    加载一点,读取一点,处理一点。对内存要求比较低。

    核心的API:
    SAXParser类: 用于读取和解析xml文件对象

    • parse(File file,DefautHandler);
      参数一: File:表示 读取的xml文件。
      参数二: DefaultHandler: SAX事件处理程序。需要自己实现它的子类,覆盖相应方法进行解析

    DefaultHandler类的API:

    • void startDocument() : 在读到文档开始时调用
    • void endDocument() :在读到文档结束时调用
    • void startElement(String uri, String localName, String qName, Attributes attributes) :读到开始标签时调用
    • void endElement(String uri, String localName, String qName) :读到结束标签时调用
    • void characters(char[] ch, int start, int length) : 读到文本内容时调用

    3)示例,利用SAX解析输出完整xml文档内容
    1.主函数:

    /**
     * 读取contact.xml文件,完整输出文档内容
     *
     */
    public class Demo2 {
    
        public static void main(String[] args)throws Exception {
            //1.创建SAXParser
            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
            //2.读取xml文件
            MyDefaultHandler2 handler = new MyDefaultHandler2();
            parser.parse(new File("./src/contact.xml"), handler);
            String content = handler.getContent();
            System.out.println(content);
        }
    }
    

    2.MyDefaultHandler2类

    /**
     * SAX处理器程序
     */
    public class MyDefaultHandler2 extends DefaultHandler {
        //存储xml文档信息
        private StringBuffer sb = new StringBuffer();
        
        //获取xml信息
        public String getContent(){
            return sb.toString();
        }
        
    
        /**
         * 开始标签
         */
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            sb.append("<"+qName);
            //判断是否有属性
            if(attributes!=null){
                for(int i=0;i<attributes.getLength();i++){
                    //得到属性名称
                    String attrName = attributes.getQName(i);
                    //得到属性值
                    String attrValue = attributes.getValue(i);
                    sb.append(" "+attrName+"=\""+attrValue+"\"");
                }
            }
            sb.append(">");
        }
        
        /**
         * 文本内容
         */
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            //得到当前读取的文本
            String content = new String(ch,start,length);
            sb.append(content);
        }
        
        /**
         * 结束标签
         */
        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            sb.append("</"+qName+">");
        }
    }
    

    SAX解析与DOM解析的区别

    DOM解析 SAX解析
    原理: 一次性加载xml文档,不适合大容量的文件读取 原理: 加载一点,读取一点,处理一点。适合大容量文件的读取
    DOM解析可以任意进行增删改查 SAX解析只能读取
    DOM解析任意读取任何位置的数据,甚至往回读 SAX解析只能从上往下,按顺序读取,不能往回读
    DOM解析面向对象的编程方法(Node,Element,Attribute),Java开发者编码比较简单。 SAX解析基于事件的编程方法。java开发编码相对复杂。

    XML约束

    1)引入
    XML语法是由w3c组织制定的规范xml文件的基本编写规则,而XML约束是开发者自定义规则以使XML符合自己的规范的约束。

    2)XML约束技术
    DTD约束:语法相对简单,功能也相对简单。学习成本也低。
    Schema约束:语法相对复杂,功能也相对强大。学习成本相对高!!!(名称空间)

    3)DTD约束
    1.导入DTD方式

    • 内部导入
    <?xml version="1.0"?>
    <!DOCTYPE note [//定义此文档是 note 类型的文档。
      <!ELEMENT note (to,from,heading,body)>     //定义 note 元素有四个元素:"to、from、heading,、body"
      <!ELEMENT to      (#PCDATA)>               //元素为 "#PCDATA" 类型
      <!ELEMENT from    (#PCDATA)>               //元素为 "#PCDATA" 类型
      <!ELEMENT heading (#PCDATA)>               //元素为 "#PCDATA" 类型
      <!ELEMENT body    (#PCDATA)>              //元素为 "#PCDATA" 类型
    ]>
    <note>
      <to>George</to>
      <from>John</from>
      <heading>Reminder</heading>
      <body>Don't forget the meeting!</body>
    </note>
    
    • 外部导入
      本地文件系统:<!DOCTYPE note SYSTEM "note.dtd">
      公共的外部导入:<!DOCTYPE 根元素 PUBLIC "http://gz.itcast.cn/itcast.dtd">

    2.DTD语法

    • 约束标签 <!ELEMENT 元素名称 类别> 或 <!ELEMENT 元素名称 (元素内容)>
      类别:
        空标签: EMPTY。 表示元素一定是空元素。
        普通字符串: (#PCDATA)。表示元素的内容一定是普通字符串(不能含有子标签)。
        任何内容: ANY。表示元素的内容可以是任意内容(包括子标签)

    顺序问题:
    <!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)>: 表示子标签必须按顺序出现
    次数问题:
    标签名 : 表示标签必须出现且只出现1次。
    标签名+ : 至少出现1次
    标签名* : 0或n次。
    标签名? : 0 或1次。

    • 约束属性 <!ATTLIST 元素名称 属性名称 属性类型 默认值>
      默认值:
          #REQUIRED  表示属性是必需的
          #IMPLIED  表示属性不是必需的
          #FIXED value  表示属性不是必须的,但属性值是固定的
      属性类型:控制属性值的
          CDATA : 表示普通字符串
          (en1|en2|..):  表示一定是任选其中的一个值
          ID: 表示在一个xml文档中该属性值必须唯一。值不能以数字开头

    4)Schema约束
    名称空间:告诉xml文档的哪个元素被哪个schema文档约束。 在一个xml文档中,不同的标签可以受到不同的schema文档的约束。
    1.一个名称空间受到schema文档约束的情况
    2.多个名称空间受到多个schema文档约束的情况
    3.默认名称空间的情况
    4.没有名称空间的情况

    相关文章

      网友评论

        本文标题:XML*

        本文链接:https://www.haomeiwen.com/subject/noxynxtx.html