一、XML介绍

XML的使用场景:(1)XML是用来传输和存储数据的。(2)XML 多用在框架的配置文件中。(3)XML 大多平台都支持,所以可以实现跨平台数据传输。

语法格式:<元素名 属性名=”属性值”>文本内容</元素名>

(1)前后元素名相同, 元素名自定义。(2)每个元素可以有0到多个属性,属性名自定义。(3)文本内容表示文字。(4)支持嵌套结构。(5)结束时元素名前有 /。

语法要求:(1)元素正确嵌套(2)XML文件的第一行必须是xml声明(3)只能有一个根节点(4)严格区分大小写(5)结束标签必须包含/(6)属性值的设置必须被""包围起来(7)XML认为换行标记也属于文本节点(8)<!-- -->注释。有的非官方资料认为这是注释节点。

实体符号:

java xml节点中包含xml xml节点可以扩展吗_前端

 转义标签:< ! [ CDATA [ 要显示的字符 ] ] >

<?xml version="1.0" encoding="utf-8" ?><!--实例-->
<products>
    <product>
        <id>p001</id>
        <name>蜘蛛王皮鞋</name>
        <price>268</price>
        <color>黑色</color>
        <size>42</size>
        <num>500</num>
    </product>
    <product>
        <id>p002</id>
        <name>ThinkPad x240</name>
        <price>5678</price>
        <color>黑色</color>
        <size>12</size>
        <num>50</num>
    </product>
    <product>
        <id>p003</id>
        <name>WD移动硬盘</name>
        <price>568</price>
        <color>黑色</color>
        <size>5</size>
        <num>1000</num>
    </product>
</products>

二、DTD

介绍:DTD(Document Type Definition)文档类型定义。即约束XML文件中可以包含哪些元素、哪些属性、及元素个数和元素之间的关系和元素的顺序。在包含DTD的XML文件中,如果XML内容不满足DTD要求,会提示错误。

分类:DTD的三种分类:(1)内部DTD(2)外部DTD(3)公共DTD

内部DTD

<?xml version="1.0" encoding="UTF-8" ?>
<!--
    !DOCTYPE:声明文档的类型,固定值
    students:自定义根标签名
    []:自定义子标签
    !ELEMENT:声明标签
    students:标签名
    (student):子标签
        (student):有且只能有一个
        (student?):至多一个
        (student+):至少一个
        (student*):任意个
    students (student):students标签中有student子标签
    student (name,age,sex):student标签中有name,age,sex子标签
                            使用子标签时顺序必须和指定一致
    #PCDATA:字符串类型的值,没有子标签了
        name (#PCDATA):name标签中为字符串值

    !ATTLIST;声明属性
    student:为哪个标签指定属性
    id:自定义属性名
    CDATA:属性控制,固定
        #REQUIRED:必须有
        #IMPLIED:可选择
        #FIXED:固定值
            #FIXED "18":固定值为18
-->
<!DOCTYPE students[
        <!ELEMENT students (student*)>
        <!ELEMENT student (name,age,sex)>
        <!ELEMENT name (#PCDATA)>
        <!ELEMENT age (#PCDATA)>
        <!ELEMENT sex (#PCDATA)>

        <!ATTLIST student id CDATA #REQUIRED>
        <!ATTLIST name class CDATA #IMPLIED>
        <!ATTLIST age abc CDATA #FIXED "18">
        ]>
<students>
    <student id="1">
        <name>chen</name>
        <age>18</age>
        <sex>nan</sex>
    </student>
</students>

外部DTD

a.xml

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

<!--
    从自己的本地引入
    SYSTEM:固定值
    "a.dtd":引入外部DTD文件的地址
-->
<!DOCTYPE students SYSTEM "a.dtd">
<students>
    <student id="1">
        <name></name>
        <age></age>
        <sex></sex>
    </student>
</students>

a.dtd文件

<!ELEMENT students (student*)>
<!ELEMENT student (name,age,sex)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student id CDATA #REQUIRED>
<!ATTLIST name class CDATA #IMPLIED>
<!ATTLIST age abc CDATA #FIXED "18">

公共DTD 

语法:<!DOCTYPE 根元素名 PUBLIC "DTD标识名" "公用的DTD的URI">

三、XSD

XSD(XML Schema Definition )XML模式定义。

属于DTD的升级版。完美的解决了DTD使用时不易扩展问题,并且提供了更强大功能。

teacher.xsd

<!--
    xs:schema : 自定义名字:schema固定
    xmlns:xs : xmlns固定:自定义名字必须与前面的名字一致
    xs:element : 定义标签
        name="teachers" : 自定义标签名
        ref="teacher" : 引用其他标签
        maxOccurs="2" : 该标签至多2个,至少1个
        type="xs:string" : 指定标签中文本内容的类型
    xs:complexType : 定义复杂类型,其中可以指定子标签的使用顺序,属性值
    xs:sequence : 指定子标签的顺序
    xs:attribute : 指定标签中的属性
        name="id" : 指定id为属性名
        defult="abc" : 为属性设置默认值为abc
        use : 指定属性是否可必要
            required : 必要的
            optional : 可选择的
            prohibited : 禁止的
        fixed="asb" : 为属性设置固定值
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="teachers">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="teacher" maxOccurs="2"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="teacher">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
                <xs:element name="age" type="xs:integer"/>
                <xs:element name="sex" type="xs:string"/>
            </xs:sequence>
            <xs:attribute name="id" use="required" fixed="asd"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

teacher.xml

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

<teachers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="teacher.xsd">
    
    <teacher id="asd">
        <name>aa</name>
        <age>12</age>
        <sex>sac</sex>
    </teacher>
    
</teachers>

四、XML解析 

分类:在Java中提供了两种XML解析方式:DOM、SAX。

DOM解析:Document Object Model 文档对象模型。把XML文件一次性加载到内存中,并转换为树状模型。然后一个节点一个节点的解析,这种解析方式效率较高,但是比较消耗内存,适用于小型XML文档。

SAX解析:Simple API for XML是基于事件的解析,它是为了解决DOM解析的资源耗费而出现的。SAX在解析一份XML文档时,会依次出发文档开始、元素开始、元素结束、文档结束等事件,应用程序通过监听解析过程中所触发的事件即可获取XML文档的内容。该方式不需要事先调入整个文档,优势是占用资源少,内存消耗小,一般在解析数据量较大的文档是采用该方式。

五、DOM

使用DOM解析XML

package com.java.test;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class TestDom {
    public static void main(String[] args) throws Exception {
        parseXML("teacher.xml");
    }

    public static void parseXML(String path) throws Exception{
        //获取文档构建器工厂
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        //根据文档构建器工厂获取文档构建器
        DocumentBuilder db = dbf.newDocumentBuilder();

        //使用文档构造器解析xml文件,将xml解析出的内容存储到Document对象中
        Document document = db.parse(path);

        //根据标签名获取标签结点集合
        NodeList teachers = document.getElementsByTagName("teachers");

        //获取根节点
        Node root = teachers.item(0);
        //获取结点名
        System.out.println("根节点: " + root.getNodeName());
        //获取根节点的子节点集合
        NodeList childNodes = root.getChildNodes();
        //遍历集合获取每一个节点
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node item = childNodes.item(i);
            //判断节点类型为元素节点
            if (item.getNodeType() == Node.ELEMENT_NODE){
                System.out.println(" 子节点: "+item.getNodeName());

                NodeList childNodes1 = item.getChildNodes();
                for (int j = 0; j < childNodes1.getLength(); j++) {
                    Node item1 = childNodes1.item(j);
                    if(item1.getNodeType() == Node.ELEMENT_NODE){
                        //获取该节点的文本内容
                        System.out.println("  子节点: " +item1.getNodeName()+" "+item1.getTextContent());
                    }
                }
            }
        }
    }
}

运行结果

java xml节点中包含xml xml节点可以扩展吗_XML_02

使用DOM创建XML

package com.java.test;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.FileOutputStream;

public class TestDom {
    public static void main(String[] args) throws Exception {
        //parseXML("teacher.xml");
        createXML("person.xml");
    }

    //使用DOM创建XML
    public static void createXML(String path) throws Exception {
        //创建文档构建器工厂
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        //根据文档构建器工厂获取文档构建器
        DocumentBuilder db = dbf.newDocumentBuilder();
        //根据文档构建器创建Document文档对象
        Document document = db.newDocument();
        //创建标签
        Element root = document.createElement("persons");
        Element person = document.createElement("person");
        //为person标签设置属性及属性名
        person.setAttribute("id","per");
        Element name = document.createElement("name");
        //设置文本内容
        name.setTextContent("chen");
        Element age = document.createElement("age");
        age.setTextContent("18");
        //指定标签之间的关系
        person.appendChild(name);
        person.appendChild(age);
        root.appendChild(person);
        //将根节点添加到文档中
        document.appendChild(root);

        //获取document转换为xml的转换器工厂
        TransformerFactory tf = TransformerFactory.newInstance();
        //根据转化器工厂获取转换器
        Transformer transformer = tf.newTransformer();
        //格式化
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","2");

        //将document转换为xml,将xml输出到指定位置
        transformer.transform(new DOMSource(document),new StreamResult(new FileOutputStream(path)));

    }
}

六、SAX

使用SAX解析XML

package com.java.test;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.FileInputStream;

public class Main {
    public static void main(String[] args) throws Exception {
        //获取SAX解析器工厂
        SAXParserFactory spf = SAXParserFactory.newInstance();
        //根据解析器工厂获取解析器
        SAXParser sp = spf.newSAXParser();
        //将解析xml的过程进行了封装,解析对应结点是,自动调用相关的方法
        sp.parse(new FileInputStream("teacher.xml"),new MyHandler());
    }
    static class MyHandler extends DefaultHandler {
        @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);
        }

        @Override//解析文本时,自动调用
        public void characters(char[] ch, int start, int length) throws SAXException {
            System.out.println(new String(ch,start,length));
        }

        @Override//解析结束标签时,自动调用
        public void endElement(String uri, String localName, String qName) throws SAXException {
            System.out.println("解析结束标签:"+qName);
        }

        @Override//结束解析时,自动调用
        public void endDocument() throws SAXException {
            System.out.println("文档解析结束");
        }
    }
}

使用SAX创建XML

package com.java.test;

import org.xml.sax.helpers.AttributesImpl;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import java.io.FileWriter;

public class TestSAXCreateXML {
    public static void main(String[] args) throws Exception {
        //获取SAX转换器工厂
        SAXTransformerFactory stf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
        //根据转换器工厂获取转换器执行器
        TransformerHandler th = stf.newTransformerHandler();
        //获取转换器
        Transformer transformer = th.getTransformer();
        //格式化
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
        //将转换后的内容输出到该文件
        th.setResult(new StreamResult(new FileWriter("phone.xml")));

        //开始文档
        th.startDocument();
        //开始标签
        th.startElement(null, null, "phones", null);

        //设置属性
        AttributesImpl attributes = new AttributesImpl();
        attributes.addAttribute(null, null, "id", "String", "iph");
        //开始标签时将属性放入到标签中
        th.startElement(null,null,"phone",attributes);

        th.startElement(null,null,"name",null);
        //设置文本内容
        char[] chars = "chen".toCharArray();
        th.characters(chars,0,chars.length);
        th.endElement(null,null,"name");

        th.startElement(null,null,"age",null);
        char[] chars1 = "18".toCharArray();
        th.characters(chars1,0,chars1.length);
        th.endElement(null, null, "age");

        th.endElement(null, null, "phone");
        th.endElement(null, null, "phones");
        th.endDocument();
    }
}