zoukankan      html  css  js  c++  java
  • xml解析

    xml:可扩展标记语言,类似于HTML,用于传输或者描述数据

    XML

    应用

    • 在客户端(client)/服务器(server)之间传递数据
    • 用来保存有关系的数据
    • 用来做配置文件,在Android当中的布局文件和清单文件

    语法

    文档声明

    • 声明必须在第一行,最简单的声明
      <?xml version="1.0"?>
    • encoding属性用于指定编码格式
      <?xml version="1.0" encoding="utf-8"?>
    • standalone属性说明文档是否独立,即是否依赖于其他文档
      <?xml version="1.0" standalone="yes"?>

    元素

    • xml文档中出现的标签,成对出现
    • 如果包含主体,则用以下形式
      <tag>content</tag>
    • 如果不包含主体,则可以使用如下形式
      <tag />
    • 标签中可以嵌套,不允许交叉嵌套
    • xml中必须且只能有一个根标签
    • xml中不会忽略主题中出现的空格和换行
    • 命名规范:区分大小写,不能以数字和_开头,不能以XML(Xml,xml等)开头,不能包含空格,名称中间不能有冒号
    • 属性:一个元素可以有多个属性,每个属性都有自己的名称和取值,用单引号或者双引号。e.g.<mytag name="value" .../>,属性不允许重复,也可用子标签来表示

    注释

    • 格式<!--注释-->

    CDATA

    • 所有XML中的文本均会被解析器解析,只有CDATA区段中的文本会被解析器忽略。
    • 语法<![CDATA[ content ]]>

    特殊字符

    特殊字符 替代符号
    & &amp;
    < &lt;
    > &gt;
    " &quot;
    ' &apos;

    XML约束

    • 由于标签都是自定义的,若出现错误将无法正确读取xml文件信息。
    • 用来约束xml书写规范的文档称之为约束文档
      • 格式良好的xml文档:遵循XML语法的XML
      • 有效的XML:遵循约束文档的XML
    • 约束文档定义了XML中允许出现的元素名称,属性及元素出现的顺序等。

    常用的约束技术

    XML DTD

    • Document Type Definition(文档类型定义)
    • 约束XML的书写规范
    • dtd可以写在单独的文件中,扩展名为dtd,必须使用UTF-8编码(此时为外部),如果为内部文档则不一定要为UTF-8
      • 文件清单
      <?xml version="1.0">
      <!DOCTYPE 书架 SYSTEM "book.dtd">
      <书架>
          <>
              <书名>第一本书书名</书名>
              <作者>第一本书作者</作者>
              <售价>第一本书售价</售价>
          </>
          <>
              <书名>第二本书书名</书名>
              <作者>第二本书作者</作者>
              <售价>第二本书售价</售价>
          </>
      </书架>
      
    • 引入外部DTD文档
      • XML使用DOCTYPE语句指明它遵循的DTD文档有两种形式
        • 1.当引用的DTD文档在本地时,采用
          <!DOCTYPE 根元素 SYSTEM "DTD名称">
        • 2.当引用的DTD文档在公共网络上时,采用
          <!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文档URL">
    • 在XML内部编写DTD
    • e.g.
    <?xml version="1.0" encoding="GBK"?>
    <!DOCTYPE 书架 [
        <!ELEMENT 书架 (书+)>
        <!ELEMENT 书(书名,作者,售价)>
        <!ELEMENT 书名(#PCDATA)>
        <!ELEMENT 作者(#PCDATA)>
        <!ELEMENT 售价(#PCDATA)>
        <!ATTLIST 
            ISBN ID #REQUIRED
            COMMENT CDATA #IMPLIED
            出版社 CDATA "书名"
        <!ENTITY copyright "实体内容">
    ]>
    
    • DTD-定义元素
      • 在DTD文档中使用ELEMENT关键字来声明一个XML元素
      • 语法:<!ELEMENT 元素名称 使用规则>
        • 使用规则:
          • (#PCDATA):指示元素的主体内容只能是普通文本(parsed character Data)。
          • EMPTY:用于指示元素的主体内容。
          • ANY:用于指示元素的主题内容为任意类型。
          • (子元素):指示元素中包含的子元素。
        • 定义子元素及描述他们之间的关系
          • 如果子元素用逗号分开,说明必须按照声明的顺序去编写XML文档
          • 如果子元素用 “|” 分开,说明任远其一
          • + * ? 来表示元素出现的次数
            • 如果子元素后面没有 + * ? 说明必须出现一次
            • + 表示至少出现一次
            • * 表示可有可无
            • ? 表示0次或1次
    • DTD-定义属性
      • 在DTD文档中使用ATTLIST关键字来为一个元素声明属性
      • 语法:<!ATTLIST 元素名称 属性1 属性值类型 设置说明···>
      • 属性值类型
        • CDATA:表明属性的取值为普通文本字符串
        • (a|b|c)说明只能从其中任选其一
        • ID 表示属性的取值不能重复
      • 设置说明
        • #REQUIRED:表示该属性必须出现
        • #IMPLIED:表示该属性可有可无
        • #FIXED:表示属性的取值为一个固定值 语法:#FIXED “固定值”
    • DTD-定义引用实体
      • 概念:在DTD中定义,在XML中使用
      • 语法:<!ENTITY 实体名称 "实体内容">
      • 引用方式(主义实在XML中使用):&实体名称
      • e.g.
    DTD中定义:
    <!ENTITY copyright "cj5785">
    XML中引用
    &copyright
    
    • DTD-定义参数实体
      • 概念:在DTD中定义,在DTD中使用
      • 语法:<!ENTITY %实体名称 "实体内容">
      • 引用方式(注意是在DTD中使用):%实体名称
      • e.g.
    DTD中定义
    <!ENTITY %TAG_NAME "姓名|EMAIL|电话|地址">
    DTD中引用
    <!ENTITY 个人信息 (%TAG_NAME;|生日)>
    <!ENTITY 客户信息 (%TAG_NAME;|公司名)>
    

    XML Schema

    • 也是一种用于定义和描述XML文档结构与内容的模式语言,其出现是为了克服DTD的缺陷
    • XML Schema VS DTD
      • XML Schema符合XML语法规范
      • DOM,SAX等XML API很容易解析出XML Schema文档中的内容
      • XML Schema对名称空间支持的非常好
      • XML Schema比XML DTD支持更多的数据类型,并支持用户自定义的数据类型
      • XML Schema定义约束的能力非常强大,可以对XML实例文档做出细致的语义限制
      • XML Schema不能像DTD一样定义实体,比DTD复杂,但XML Schema现在是W3C组织的标准,正在逐步取代DTD
    • 名称空间 namespace 对应一个约束文档
    • Schema约束
      • XML Schema文件自身就是一个XML文件,但它的拓展名通常为.xsd
      • 一个XML Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的XML称之为实例文档
      • 和XML文件一样,一个XML Schema文档也必须有一个根节点,但这个根节点的名字为schema
      • 编写了一个XML Schema约束文件后,通常需要把这个文件中声明的元素绑定到一个URI地址上,在XML Schema技术中有一个专业术语来描述这个过程,即把XML Schema文档声明中的元素绑定到一个名称空间上,以后XML文件可以通过这个URI(即名称空间)来告诉解析引擎,XML文件中编写的元素来自哪里,被谁约束
      <?xml version="1.0" encoding="UTF-8"?>
      <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
      		targetNamespace="http://www.cj5785.com"
      		elementFromDefault="qualified">
      		<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>
      
    • XDR(已不再使用)
    • SOX(已不再使用)

    XML解析

    解析的xml文档内容

    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <书架>
        <>
            <书名>第一行代码(第二版)</书名>
            <作者>郭霖</作者>
            <售价>79.00元</售价>
        </>
        <>
            <书名>自己动手写网络爬虫</书名>
            <作者>罗刚</作者>
            <售价>49.00元</售价>
        </>
    </书架>
    

    Dom解析

    xml与json-dommoxing

    • DOM解析
      • 根据xml层级结构在内存中会分配一个树形结构
      • 在XML DOM每个元素都会被解析成一个节点Node,而常用的节点类型又分为:
        • 元素节点 Element
        • 属性节点 Attr
        • 文本节点 Text
        • 文档节点 Document
    • Dom解析xml的优缺点
      • 优点:因为分配了一个树形结构,很方便的实现了增加,修改和删除的操作。
      • 缺点:如果要解析的文件过大,一次性在内存中分配一个树形结构,造成内存的溢出。
    • DOM & SAX解析开发包
      • JAXP是sun公司推出的解析标准实现
      • Dom4j:开源组织推出的解析开发包
      • JAXP:(Java API for XML Processing)开发包是JavaSE的一部分,它由以下几个包及其子包组成:
        • org.w3c.dom:提供DOM方式解析XML的标准接口
        • org.xml.sax:提供SAX方式解析XML的标准接口
        • javax.xml:提供了解析XML文档的类
      • java.xml.parsers包中,定义了几个工厂类,用来获得DOM和SAX解析器对象
        • DocumentBuilderFactory
        • SAXParserFactory
          xml与json-jaxp
    • 1.把整个文档先加载到内存中->Document所以可以对文档进行修改
    • 2.如果文件比较大,则可能导致内存溢出
    • 编程思路:DocumentBuilderFactory -> DocumentBuilder -> Document -> 通过节点获得NodeList -> 具体的Node
    • 如果想修改TransformerFactory -> Transformer -> transform(xmlSource , outputTarget)
    public void domParse() throws Exception{
        //获取DocumentBuilderFactory
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        //获取DocumentBuilder
         DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
        //通过DocumentBuilder解析xml文档获取Document对象
        Document document = documentBuilder.parse("book.xml");
        //通过元素名称可以找到元素集合
        NodeList nodeList = document.getElementsByTagName("售价");
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            String connect = node.getTextContent();
            System.out.println(connect);
        }
        //找到第二个元素
        Node node = nodeList.item(1);
        //读出相应节点的文本内容
        String content = node.getTextContent();
        System.out.println(content);
    }
    
    public void domModifyxml() throws Exception {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
        Document document = builder.parse("book.xml");
        NodeList nodeList = document.getElementsByTagName("售价");
        Node node = nodeList.item(1);
        //修改节点的内容(此时只是在内存中生效)
        node.setTextContent("99.00元");
    
        //以下修改生效于xml
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        //数据源
        Source xmlSource = new DOMSource(document);
        //输出的目的地
        Result outputTarget = new StreamResult("book.xml");
        transformer.transform(xmlSource , outputTarget );
    }
    

    Sax解析

    • 解析方式:边读边解析
    • 当使用sax方式读到特定标签的时候,自动调用相应的方法进行操作。
    • sax解析的优缺点
      • 优点:不会造成内存的溢出
      • 缺点:不能修改xml文件
    • 解析的xml文档内容
    package domtest;
    
    public class SaxParseTest {
    
        public void saxParser() throws Exception {
            //获取工厂
            SAXParserFactory parserFactory = SAXParserFactory.newInstance();
            SAXParser saxParser = parserFactory.newSAXParser();
            //获取XMLReader通过这个reader可以设置ContentHandler
            XMLReader xmlReader = saxParser.getXMLReader();
            //给xmlReader设置contentHandler,ContentHandler是一个接口,里面太多的方法没有实现
            //不去直接实现ContentHandler而是继承它默认的实现DefaultHandler
            xmlReader.setContentHandler(new Myhandler());
            //解析xml文档
            xmlReader.parse("book.xml");
        }
    
        private class Myhandler extends DefaultHandler{
            @Override
            public void characters(char[] ch, int start, int length) throws SAXException {
                String text = new String(ch,start,length);
                System.out.println("文本内容"+text);
            }
            @Override
            public void endDocument() throws SAXException {
                System.out.println("文档结束");
            }
    
            @Override
            public void endElement(String uri, String localName, String qName) throws SAXException {
                System.out.println("结束标签</"+qName+">");
            }
            @Override
            public void startDocument() throws SAXException {
                System.out.println("文档开始");
            }
            @Override
            public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
                System.out.println("开始标签<"+qName+">");
            }
        }
    
        public void saxParserTest() throws Exception {
            SAXParserFactory parserFactory = SAXParserFactory.newInstance();
            SAXParser parser = parserFactory.newSAXParser();
            XMLReader reader = parser.getXMLReader();
            reader.setContentHandler(new DefaultHandler() {
                boolean isPrice = false;
                int count = 0;
                @Override
                public void characters(char[] ch, int start, int length) throws SAXException {
                    if (isPrice && count == 2) {
                        System.out.println(new String(ch,start,length));
                    }
                }
                @Override
                public void endElement(String uri, String localName, String qName) throws SAXException {
                    if ("售价".equals(qName)) {
                        isPrice = false;
                    }
                }
                @Override
                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
                    if ("售价".equals(qName)) {
                        isPrice = true;
                        count++;
                    }
                }
    		
            });
            reader.parse("book.xml");
        }
    }
    
    • book.java (java bean)
    public class Book {
        private String title;
        private String auther;
        private String price;
    
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        public String getAuther() {
            return auther;
        }
        public void setAuther(String auther) {
            this.auther = auther;
        }
        public String getPrice() {
            return price;
        }
        public void setPrice(String price) {
            this.price = price;
        }
        @Override
        public String toString() {
            return "Book [title=" + title + ", auther=" + auther + ", price=" + price + "]";
        }
    }
    
    • 用sax解析将其解析为集合
    public void saxParse2list() throws Exception {
        SAXParserFactory parserFactory = SAXParserFactory.newInstance();
        SAXParser parser = parserFactory.newSAXParser();
        XMLReader reader = parser.getXMLReader();
        reader.setContentHandler(new DefaultHandler() {
            ArrayList<Book> bookshelf = null;
            Book book = null;
            String tag = null;
            @Override
            public void characters(char[] ch, int start, int length) throws SAXException {
                if ("书名".equals(tag)){
                    book.setTitle(new String(ch, start, length));
                }else if("作者".equals(tag)){
                    book.setAuther(new String(ch, start, length));
                }else if("售价".equals(tag)){
                    book.setPrice(new String(ch, start, length));
                }
            }
    
            @Override
            public void endElement(String uri, String localName, String qName) throws SAXException {
                //每次到结束标签都要将tag设置成null
                tag = null;
                if("书架".equals(qName)) {
                    for (Book book1 : bookshelf) {
                        System.out.println(book1);
                    }
                }else if ("书".equals(qName)) {
                    //读到书的结束标签,把book对象添加到集合里
                    bookshelf.add(book);
                }
            }
    
            @Override
            public void startElement(String uri, String localName, String qName, Attributes attributes)
                throws SAXException {
                if ("书架".equals(qName)) {
                //创建集合
                    bookshelf = new ArrayList<Book>();
                }else if("书".equals(qName)){
                    //创建book对象
                    book = new Book();
                }else if("书名".equals(qName)){
                    tag = "书名";
                }else if("作者".equals(qName)){
                    tag = "作者";
                }else if("售价".equals(qName)){
                    tag = "售价";
                }
            }
    		
        });
        reader.parse("book.xml");
    }
    

    Pull解析

    • 首先导入pull的jar包(两个jar包kxml.jarxmlpull.jar),其原理其实就是sax解析。但pull解析可以在任意位置停止,而sax解析必须全部解析完成
    • 使用pull解析xml文件把xml中的内容放到集合中去
    • 步骤:
      • 1.创建解析器工厂
      • 2.根据解析器工厂创建解析器
      • 3.把要操作的文件放到解析器里面
    • 示例
    public void pullTest() throws Exception {
        ArrayList<Book> books = null;
        Book book = null;
        //获取工厂
        XmlPullParserFactory parserFactory = XmlPullParserFactory.newInstance();
        //获取到xml解析器
        XmlPullParser parser = parserFactory.newPullParser();
        //给解析器设置一个输入源
        //第一个参数输入源,第二个参数文档中用到的字符集编码
        parser.setInput(new FileInputStream(new File("book.xml")),"utf-8");
        //获取当前事件类型
        int eventType = parser.getEventType();
        while (eventType != XmlPullParser.END_DOCUMENT) {
            switch (eventType) {
                case XmlPullParser.START_TAG:
                    //开始标签
                    //parser.getName()获取当前事件对应的元素名字
                    if ("书架".equals(parser.getName())) {
                        //创建一个集合
                        books = new ArrayList<>();
                    }else if ("书".equals(parser.getName())) {
                        //创建一个book对象
                        book = new Book();
                    }else if ("书名".equals(parser.getName())) {
                        //给book对象设置书名的属性
                        book.setTitle(parser.nextText());//parser.nextText()获取当前节点的下一个文本内容
                    }else if ("作者".equals(parser.getName())) {
                        //给book对象设置作者的属性
                        book.setAuther(parser.nextText());
                    }else if ("售价".equals(parser.getName())) {
                        //给book对象设置售价的属性
                        book.setPrice(parser.nextText());
                    }
                    break;
                case XmlPullParser.END_TAG:
                    //结束标签
                    if ("书".equals(parser.getName())){
                        //把book对象添加到集合
                        books.add(book);
                    }
                    break;
                }
            //调用parse.next方法解析下一个元素 用这个结果来更新eventType,如果解析到文档结束则退出循环
            //如果不更新eventType则就成为死循环了
            eventType = parser.next();
        }
    	
        //遍历集合
        for (Book book2 : books) {
            System.out.println(book2);
        }
    }
    
  • 相关阅读:
    UVA 1513
    《ArcGIS Runtime SDK for Android开发笔记》——问题集:.geodatabase创建,创建时内容缺失问题总结
    《ArcGIS Runtime SDK for Android开发笔记》——问题集:使用TextSymbol做标注显示乱码
    《ArcGIS Runtime SDK for Android开发笔记》——(7)、示例代码arcgis-runtime-samples-android的使用
    《ArcGIS Runtime SDK for Android开发笔记》——(6)、基于Android Studio的ArcGIS Android工程结构解析
    《ArcGIS Runtime SDK for Android开发笔记》——(5)、基于Android Studio构建ArcGIS Android开发环境(离线部署)
    《ArcGIS Runtime SDK for Android开发笔记》——(4)、基于Android Studio构建ArcGIS Android开发环境
    《ArcGIS Runtime SDK for Android开发笔记》——(3)、ArcGIS Runtime SDK概述
    《ArcGIS Runtime SDK for Android开发笔记》——(2)、Android Studio基本配置与使用
    《ArcGIS Runtime SDK for Android开发笔记》——(1)、Android Studio下载与安装
  • 原文地址:https://www.cnblogs.com/cj5785/p/10664696.html
Copyright © 2011-2022 走看看