XML——可扩展标记语言

XML介绍

XML 是一种标记语言,类似于HTML,XML是可扩展标记语言,严格区分大小写。

HTML是用来显示数据的。XML是用来存储和传输数据的,多用在框架的配置文件中,可实现跨平台数据传输。

HTML中的标签是定义好的,用户直接使用这些标签。XML标签没有被预定义,XML本身如果没有任何规范或约定的话,所有标签都是自定义的。

XML语法格式

<元素名 属性名="属性值">文本内容</元素名>

注意事项

1.严格区分大小写

2.元素名和属性名均自定义

3.前后元素名保持一致(包括大小写)

4.结束标签必须包含 /

5.属性值必须被 " " 包围

6.每个元素可以有0到多个属性

7.元素需正确嵌套

8.XML文件的第一行必须是xml声明

<?xml version="1.0" encoding="UTF-8"?>    //文档头,声明版本和编码

9.只能有一个根节点

10.元素节点是标签,属性节点是属性(包含属性名和属性值),文本节点是标签之间的文本值。

11.XML认为换行标记也属于文本节点

特殊字符

实体符号

在XML中必须要写某些符号,但是写上会报错,这时需要使用实体符号。

特殊字符

字符实体

<

&lt;

>

&gt;

&

&amp;

'

&apos;

"

&quot;

转义标签

在当前标签,需要存储的内容中包含许多特殊字符,全都转换为字符实体过于麻烦,这时可以使用转义标签。

转义标签:可将特殊字符转换为普通字符

<![CDATA[
    > < >> & ;;;  ::: ''' """
]]>

DTD

DTD是文档类型定义。

通过DTD约束XML文件中的元素、属性等,包括哪些元素、哪些属性、元素个数、元素之间的关系、元素顺序。

DTD缺点是,当对XML文件结构更新时,需要修改整个DTD文件,可扩展性较差。

DTD分类

内部DTD、外部DTD、公共DTD

内部DTD

直接在XML中编写DTD内容

<!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 test CDATA #IMPLIED>
        <!ATTLIST age class CDATA #FIXED "18">
        <!ATTLIST sex aa CDATA #REQUIRED bb CDATA #IMPLIED>
        ]>
<students>
    <student id="">
        <name></name>
        <age></age>
        <sex aa=""></sex>
    </student>
</students>

!DOCTYPE:文档类型的声明,XML中的内容必须为声明中的内容

students:根标签的名称(自定义的)

[ ]:XML中可以有哪些标签和属性

!ELEMENT:定义元素(标签)

<!ELEMENT students (student)>:定义根标签中的子标签

        1. (student):必须且仅有一个

        2. (student?):可以有一个或者零个

        3. (student+):可以有至少一个

        4. (student*):可以有零到多个

<!ELEMENT students (name, age, sex)>:只能有name, age, sex,且顺序必须为指定的顺序

<!ELEMENT name (#PCDATA)>:name标签中为文本内容

<!ATTLIST 标签名 自定义属性名 CDATA #REQUIRED>

        CDATA:属性控制

        1.#REQUIRED:必须存在的(标签student中必须有属性id)

        2.#IMPLIED:可选的(标签name中可以有属性test,也可以没有)

        3.#FIXED "值":固定值(标签age中可以有属性class,也可以没有,但是如果有的话,属性值一定为18)

外部DTD(常用)

外部DTD是单独编写一个后缀为.dtd的文件,然后通过引入方式引入DTD。

<!-- dog.dtd -->
<!ELEMENT dogs (dog+) >
<!ELEMENT dog (name,age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ATTLIST dog id CDATA #IMPLIED>
<?xml version="1.0" encoding="UTF-8" ?>
<!-- XML -->
<!DOCTYPE dogs SYSTEM "dog.dtd">
<dogs>
    <dog>
        <name></name>
        <age></age>
    </dog>
</dogs>

公共DTD

公共DTD是由一些开源组织编写的DTD,需要使用时按照要求的语法格式使用。

<!DOCTYPE 根元素 PUBLIC "DTD标识名" "公用DTD的URI">
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

XSD

XSD是XML模式定义,在DTD基础上解决了使用时不易扩展问题。

同一个XML文件只能引入DTD或XSD其中之一,不能同时引入。

XSD只能使用外部XSD,即创建后缀为.xsd的文件,通过引入方式引入XSD。

<!-- cat.xsd -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="cats">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="cat" maxOccurs="3">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="name" type="xs:string"/>
                            <xs:element name="sex" type="xs:string"/>
                            <xs:element name="age" type="xs:int"/>
                        </xs:sequence>
                        <xs:attribute name="id" fixed="zs" use="required"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">:声明XSD约束

        xs:自定义名称(前后需保持一致)

<xs:element name="cat" maxOccurs="3">

        1.name:指定标签名为cat

        2.maxOccurs:指定标签的个数上限

                maxOccurs="3":标签个数最多为3个

                maxOccurs="unbounded":标签个数无上限

<xs:complexType>:复杂类型,指定子标签、属性……

<xs:sequence>:指定有哪些子标签及其顺序

complexType和sequence搭配使用,通过复杂类型里具体的细节(顺序),控制cat标签中的子标签name,sex,age,后续指定子标签时必须按照这个顺序指定。

<xs:element name="age" type="xs:int"/>:指定age中存放的文本节点值类型为int

<xs:attribute name="id" default="zs" use="optional"/>属性(需要放在复杂类型里)

        1.name:属性名,指定cat中属性的属性名为id

        2.default="值":默认属性值

           fixed="值":固定属性值

        3.use 属性的状态

                use="optional":可选(可有可无)

                use="required":必须(一定要有)

                use="prohibited":禁止(一定不能有)

<?xml version="1.0" encoding="UTF-8" ?>
<cats xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="cat.xsd">
    <cat id="zs">
        <name></name>
        <sex>男</sex>
        <age>0</age>
    </cat>
</cats>

XML解析

JAVA中XML的两种解析方式分别为DOM和SAX。

解析的目的是拿出标签之间的值,而不是标签。

解析的是XML文件中的根节点及子节点,与DTD和XSD无关。

DOM

简介

DOM是文档对象模型,是将XML文件一次性加载到内存中并转换为树状模型,是将XML中的标签解析为元素节点对象。

这种方式效率高但是比较消耗内存,适用于小型XML文档。

解析器是基于工厂设计模式的,不需要自己创建解析器,基于工厂直接获取解析器。

获取到XML文档后,每个元素都是一个节点,只需要操作节点对象就可以。

在DOM解析时需要过滤掉换行。

DOM解析示例

(出现问题,转成文件类)

<?xml version="1.0" encoding="UTF-8" ?>
<!--
    doggg.xml
-->
<!DOCTYPE dogs SYSTEM "dog.dtd">
<dogs>
    <dog id="dog">
        <name>旺财</name>
        <age>10</age>
    </dog>
    <dog id="dog1">
        <name>小花</name>
        <age>0.5</age>
    </dog>
public class DOMParseXML {
    public static void parse(String path) throws Exception{
        //1.创建文档构建器工厂
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        //2.根据文档构建器工厂获取文档构建器
        DocumentBuilder db = dbf.newDocumentBuilder();
        //3.通过文档构建器解析XML
        //Document document = db.parse(path);
        File file = new File(path);
        Document document = db.parse(file);
        //4.获取根节点
        NodeList dogs = document.getElementsByTagName("dogs");
        Node root = dogs.item(0);   //获取第一个节点
        String nodeName = root.getNodeName();   //获取节点名
        System.out.println("根节点名:"+nodeName);
        //5.获取根节点的所有子节点
        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) {
                        String textContent = item1.getTextContent();    //获取该元素节点的文本节点值
                        System.out.println("    子节点名:" + item1.getNodeName()+"  "+textContent);
                    }
                }
            }
        }
    }
}
public class TestDOMParse {
    public static void main(String[] args) throws Exception {
        //DOMParseXML.parse("doggg.xml");
        DOMParseXML.parse("D:\\JAVA就业\\03.阶段3\\Day04\\源码\\Stage03_Day04\\doggg.xml");
    }
}

使用DOM生成XML

DOM生成XML主要是创建节点

public class DOMCreateXML {
    public static void create(String path) throws Exception{
        //1.获取文档构建器工厂
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        //2.根据文档构建器工厂获取文档构建器
        DocumentBuilder db = dbf.newDocumentBuilder();
        //3.通过文档构建器生成XML
        Document document = db.newDocument();   //没有任何节点

        //4.创建元素节点
        Element root = document.createElement("rabbits");
        Element rabbit = document.createElement("rabbit");
        rabbit.setAttribute("id","小灰兔");    //属性
        Element name= document.createElement("name");
        name.setTextContent("兔子");
        Element sex = document.createElement("sex");
        sex.setTextContent("母");
        Element age = document.createElement("age");
        age.setTextContent("10");
        Element addr = document.createElement("addr");
        addr.setTextContent("海淀");

        //5.指定元素节点之间的关系
        rabbit.appendChild(name);
        rabbit.appendChild(sex);
        rabbit.appendChild(age);
        rabbit.appendChild(addr);

        root.appendChild(rabbit);
        document.appendChild(root);

        //设置为独立的xml
        document.setXmlStandalone(true);

        //6.创建转换器工厂
        TransformerFactory tf = TransformerFactory.newInstance();
        //根据转换器工厂获取转换器
        Transformer t=tf.newTransformer();

        //调整格式
        t.setOutputProperty(OutputKeys.INDENT, "yes");
        t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");


        //7.将document对象转换为XML并输出到指定的位置
        /*
        * 参数一:new DOMSource(document) -> 将document对象转换为XML
        * 参数二:输出流
        * */
        t.transform(new DOMSource(document),new StreamResult(new FileOutputStream(path)));
    }
}
public class TestDOMCreate {
    public static void main(String[] args) throws Exception{
        DOMCreateXML.create("rabbit.xml");
    }
}

SAX解析

简介

SAX是基于事件的解析,事件驱动,边读边写。

应用程序通过监听解析过程中所触发的事件获取XML文档的内容。相当于封装好了解析的方法,使用时直接调取。

这种方式占用资源少,内存消耗小,解决了DOM解析的资源耗费,SAX适用于较大的XML文档。

在SAX解析时需要过滤掉换行。

SAX解析示例

public class SAXParseXML {
    public static void parse(String path) throws Exception{
        //1.创建SAX解析器工厂对象
        SAXParserFactory spf=SAXParserFactory.newInstance();
        //2.基于工厂获取解析器对象
        SAXParser sp=spf.newSAXParser();
        //3.使用解析器解析XML
        sp.parse(new File(path), new MyHandler());
    }
}
public class MyHandler extends DefaultHandler {
    String name=null;

    @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);
        name=qName;
    }

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

    @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("文档解析结束");
    }
}
public class TestSAXParse {
    public static void main(String[] args) throws Exception{
        SAXParseXML.parse("D:\\JAVA就业\\03.阶段3\\Day04\\源码\\Stage03_Day04\\doggg.xml");
    }
}

使用SAX生成XML

public class SAXCreateXML {
    public static void create(String path) throws Exception{
        //1.创建转换器工厂
        SAXTransformerFactory stf=(SAXTransformerFactory)SAXTransformerFactory.newInstance();
        //2.基于工厂获取转换器
        TransformerHandler th=stf.newTransformerHandler();
        Transformer tf = th.getTransformer();

        //调整格式
        tf.setOutputProperty(OutputKeys.INDENT, "yes");
        tf.setOutputProperty(OutputKeys.ENCODING, "utf-8");
        tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");

        //3.将document对象转换为XML并输出到指定的位置
        th.setResult(new StreamResult(new FileOutputStream(path)));

        //4.创建元素节点
        th.startElement(null, null, "students", null);
        AttributesImpl attributes = new AttributesImpl();
        attributes.addAttribute(null, null, "id", null, "aa");

        th.startElement(null, null, "student", attributes);
        th.startElement(null, null, "name", null);
        char[] chars = "zs".toCharArray();  //toCharArray():将字符串对象中的字符转换为一个字符数组。
        th.characters(chars, 0, chars.length);
        th.endElement(null, null, "name");
        
        th.startElement(null, null, "age", null);
        char[] chars1 = "19".toCharArray();
        th.characters(chars1, 0, chars1.length);
        th.endElement(null, null, "age");
        
        th.startElement(null, null, "sex", null);
        char[] chars2 = "男".toCharArray();
        th.characters(chars2, 0, chars2.length);
        th.endElement(null, null, "sex");
        
        th.endElement(null, null, "student");
        th.endElement(null, null, "students");
        th.endDocument();
    }
}
public class TestSAXCreate {
    public static void main(String[] args) throws Exception{
        SAXCreateXML.create("student.xml");
    }
}
  • 23
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值