XML:可扩展标记语言

XML:可扩展标记语言

主要内容

  • XML介绍
  • DTD
  • XSD
  • DOM解析
  • SAX解析

学习目标

知识点要求
XML介绍掌握
DTD掌握
XSD掌握
DOM解析掌握
SAX解析掌握

一、XML介绍

1. 简介

XML(Extensible Markup Language)可扩展标记语言。严格区分大小写。

2. XML和HTML

XML是用来传输和存储数据的。

XML 多用在框架的配置文件中。

XML 大多平台都支持,所以可以实现跨平台数据传输。

HTML 是用来显示数据的。

3. 语法

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

前后元素名相同, 元素名自定义。

每个元素可以有0到多个属性,属性名自定义。

文本内容表示文字。

支持嵌套结构。

结束时元素名前有 /。

4. 语法要求

XML的语法和HTML语法是差不多的,但是比HTML要求更加严格。

​ 1. 元素正确嵌套

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

​ 3. 只能有一个根节点

​ 4. 严格区分大小写

​ 5. 结束标签必须包含/

​ 6. 属性值必须被""包围起来

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

​ 8. <!-- --> 注释。有的非官方资料认为这是注释节点。

5. 特殊字符

5.1 实体符号
image-20220328183821908
5.2 转义标签

<![CDATA[

要显示的字符

]]>

二、小节实战案例 - 编写XML文件

1. 需求

项目根路径下创建product.xml并存储下面信息。

根节点叫做products,里面包含3个product元素。每个元素里面又包含下面的元素及文本内容

id名称(name)单价(price)颜色(color)尺寸(size)库存(num)
P001蜘蛛王皮鞋268黑色42500
P002ThinkPad x2405678黑色1250
P003WD移动硬盘568蓝色51000

2. 实现

<?xml version="1.0" encoding="utf-8" ?> <!-- xml的文档声明 -->
<products>
  <product>
    <id>P001</id>
    <name>蜘蛛王皮鞋</name>
    <price>268</price>
    <color>黑色</color>
    <size>42</size>
    <num>500</num>
  </product>
  <!-- ... -->
</products>

三、DTD

1. 简介

DTD(Document Type Definition)文档类型定义。

即约束XML文件中可以包含哪些元素、哪些属性、及元素个数和元素之间的关系和元素的顺序。

在包含DTD的XML文件中,如果XML内容不满足DTD要求,会提示错误。

2. 分类

DTD的三种分类:

​ 1. 内部DTD

​ 2. 外部DTD

​ 3. 公共DTD

2.1 内部DTD

直接在XML中编写DTD内容。不推荐。

  1. <!ELEMENT 元素名 (包含内容)> 内容可以是其他标签,也可以是#PCDATA文本内容。

  2. <!ATTLIST 元素名 属性名 CDATA 内容控制> 定义属性

  3. 内容控制可取值:

​ 1. #REQUIRED 必须有这个属性

​ 2. #IMPLIED 可以有也可以没有

​ 3. #FIXED “内容” 必须取固定值

  1. (name,age,score) 表示顺序必须是先name,后age,然后score

  2. student+ 表示student至少出现一次。括号内容的元素名都可以跟下面符号

​ 1. ?表示子元素出现0次到1次 (最多出现一次)

​ 2. + 表示子元素至少出现一次 (至少出现一次 )

​ 3. *表示子元素可以出现0到多次 (任意)

<?xml version="1.0" encoding="UTF-8" ?> <!-- 声明xml文档头 -->
<!-- 内部DTD约束 -->
<!--
    !DOCTYPE: 固定语法 文档类型
    students: 自定义根标签名字
    []: 存放子标签
    ELEMENT: 元素(标签)
       #PCDATA:元素是字符串类型#PCDATA(不能再有子元素,也不能为空)
    DTD中标签的顺序就是日后使用的顺序, 不允许改变
-->
<!DOCTYPE students[
        <!-- 标签 -->
        <!--
            (student): 只能有一对student标签
            (student?): 0~1次
            (student+): 至少1次
            (student*): 0~多次
        -->
        <!ELEMENT students (student*)>
        <!ELEMENT student (name, age, sex)>
        <!ELEMENT name (#PCDATA)>
        <!ELEMENT age (#PCDATA)>
        <!ELEMENT sex (#PCDATA)>
        <!-- 属性 -->
        <!--
            ATTLIST: 属性
            student: 哪个标签指定属性
            id: 指定的属性名
            CDATA: 属性控制
                #REQUIRED: 必须有
                #FIXED "值": 固定值
                #IMPLIED: 可有可无
        -->
        <!ATTLIST student id CDATA #REQUIRED>
        <!ATTLIST name class CDATA #FIXED "qwe">
        <!ATTLIST age test CDATA #IMPLIED>
        ]>

<students>
  <student id="aa">
    <name class="qwe">张三</name>
    <age test="aaa">18</age>
    <sex></sex>
  </student>
</students>
2.2 外部DTD

外部DTD是我们自己编写的DTD文件。通过引入方式引入DTD。

在外部创建一个xxx.dtd文件,文件内容和内部dtd [ ] 中的内容相同。

  1. 新建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 #FIXED "qwe">
<!ATTLIST age test CDATA #IMPLIED>
  1. xml引入外部dtd文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "aa.dtd">
<students>
  <student id="aa" >
    <name class="qwe">张三</name>
    <age test="aaa">18</age>
    <sex></sex>
  </student>
</students>
2.3 公共DTD

公共DTD是一些开源组织编写的DTD,并且已经发布到互联网中。

公共DTD语法:

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

代码示例:

3. 总结

DTD是较简单的语法检查机制。整体语法较简单,功能较单一。

当需要对XML文件结构更新时,需要修改整个DTD文件,不够灵活。

四、XSD

1. 简介

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

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

2. 定义XSD

新建xxx.xsd。

所有需要的元素、属性都需要被定义。

<!--
  声明xsd约束
 		aa: 自定义名称(随意)
  	schema: 约束(固定)
-->
<aa:schema xmlns:aa="http://www.w3.org/2001/XMLSchema">
  <!--
        aa:element: 标签
        name: 标签名
    -->
  <aa:element name="students">
    <!-- 必须设置为复杂类型 -->
    <aa:complexType>
      <!-- 在此标签中规范了 标签的顺序 -->
      <aa:sequence>
        <!-- 引用其他标签 -->
        <!-- maxOccurs: 指定可以有多少个标签 -->
        <aa:element ref="student" maxOccurs="2"/>
      </aa:sequence>
    </aa:complexType>
  </aa:element>
  <aa:element name="student">
    <!-- 复杂类型可以指定 包含的标签  属性 -->
    <aa:complexType>
      <aa:sequence>
        <!-- type: 值的类型 -->
        <aa:element name="name" type="aa:string"/>
        <aa:element name="age" type="aa:int"/>
        <aa:element name="sex" type="aa:boolean"/>
      </aa:sequence>
      <!--
                use: 属性的设置
                    required : 必须存在
                    prohibited: 禁用
                    optional: 可选的
                fixed="值": 固定值
            -->
      <aa:attribute name="id" use="optional" fixed="aa"/>
    </aa:complexType>
  </aa:element>
</aa:schema>

3. 引用xsd

<?xml version="1.0" encoding="UTF-8" ?>
<students xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="s.xsd">
  <student id="aa">
    <name></name>
    <age>11</age>
    <sex>false</sex>
  </student>
</students>

五、XML 解析

1. 简介

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

2. DOM解析

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

3. SAX

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

六、DOM解析

1. 简介

DOM解析所有API都是org.w3c包中。

使用DOM操作XML按照标准树状结构一层一层解析。

解析器是基于工厂设计模式的。当获取到文档对象后每个元素都是一个节点,然后操作节点对象。

在DOM解析时,每个换行符都是一个文本节点,所以一定要过滤掉换行。

2. 代码示例

以上面的students作为xml进行解析。

已知XML文件就三层结构,所以直接使用循环进行解析。如果XML文档结构比较深,此处需要使用递归。

public class TestDOM {
  public static void main(String[] args) throws Exception {
    parse();
  }
  //使用DOM解析XML
  public static void parse() throws ParserConfigurationException, IOException, SAXException {
    //1.获取document构建 工厂对象
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    //2.根据文档构建工厂获取文档构建对象
    /*
     * 将xml变为document
     * 手动的创建document
     * */
    DocumentBuilder db = dbf.newDocumentBuilder();
    //3.使用文档构建对象, 将xml解析为document对象
    Document document = db.parse(new File("stu.xml"));
    //4.根据标签名获取根标签
    NodeList rootList = document.getElementsByTagName("students");
    //5.xml中仅会存在一个根标签, 获取这个根标签
    Node root = rootList.item(0);
    System.out.println("根节点名称: " + root.getNodeName());
    //6.获取标签所有的直接子节点
    NodeList childNodes = root.getChildNodes();
    for (int i = 0; i < childNodes.getLength(); i++) {
      //7.获取每一个子节点
      /*
       * getNodeType(): 结点类型, 常量
       *           1: 标签结点
       *           2: 属性结点
       *           3: 文本结点
       * */
      Node item = childNodes.item(i);
      if (item.getNodeType() == Node.ELEMENT_NODE) {
        System.out.println(" 子节点名称: " + item.getNodeName());
        //8.获取该结点的所有子节点
        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());
          }
        }
      }
    }
  }
}

七、使用DOM生成XML

1. 简介

DOM生成XML时主要是创建节点。然后把节点添加到上层节点。

2. 代码示例

public class TestDOM {
  public static void main(String[] args) throws Exception {
    transform();
  }
  //先构建文档, 再将文档变为xml
  public static void transform() throws ParserConfigurationException, TransformerException, FileNotFoundException {
    //1.获取文档构建器工厂对象
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    //2.构建器工厂对象 获取 构建器对象
    DocumentBuilder db = dbf.newDocumentBuilder();
    //3.创建文档对象
    Document document = db.newDocument();
    //4.创建teachers标签
    Element teachers = document.createElement("teachers");
    //5.创建teacher标签
    Element teacher = document.createElement("teacher");
    teacher.setAttribute("id", "tea"); //设置属性
    //6.创建name标签
    Element name = document.createElement("name");
    name.setAttribute("class", "na"); //设置属性
    name.setTextContent("zs");
    //7.创建age标签
    Element age = document.createElement("age");
    age.setTextContent("18");
    //8.创建sex标签
    Element sex = document.createElement("sex");
    sex.setTextContent("男");

    //9.设置标签之间的关系
    /* 添加teacher的子标签 */
    teacher.appendChild(name);
    teacher.appendChild(age);
    teacher.appendChild(sex);
    /* 添加teachers的子标签 */
    teachers.appendChild(teacher);
    /* 添加文档的子标签 */
    document.appendChild(teachers);
    /* 设置为独立的xml */
    document.setXmlStandalone(true);

    //10.将document对象变为xml
    //10.1 创建转换器工厂对象
    TransformerFactory tff = TransformerFactory.newInstance();
    //10.1 根据转换器工厂对象 获取 转换器
    Transformer tf = tff.newTransformer();
    tf.setOutputProperty(OutputKeys.INDENT, "yes");
    tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
    //10.3 将document转化为xml  通过流输出到指定的位置
    /*
     * 参数1: 指定document源
     * 参数2: 输出的位置
     * */
    tf.transform(new DOMSource(document), new StreamResult(new FileOutputStream("teacher.xml")));
  }
}

八、SAX解析

1. 简介

SAX解析是基于事件模型完成的。所有的API都在org.xml中。

SAX解析时也会识别换行为文本节点,这个坑一定躲避。

2. 代码示例

public class TestSAX {
  public static void main(String[] args) throws Exception {
    parse();
  }
  public static void parse() throws Exception {
    //1.SAX解析器工厂对象
    SAXParserFactory spf = SAXParserFactory.newInstance();
    //2.基于工厂对象获取解析器对象
    SAXParser sp = spf.newSAXParser();
    //3.使用解析器解析xml
    sp.parse(new File("java_day13/teacher.xml"), 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("文档解析结束");
    }
  }

}

九、SAX 生成

1. 简介

SAX 生成XML 和手写XML比较相似。

也是在调用5个操作方法。

2. 代码示例

public class TestSAX {
  public static void main(String[] args) throws Exception {
    parse();
  }
  public void transfom() throws TransformerConfigurationException, FileNotFoundException, SAXException {
    //1.创建转换器工厂
    SAXTransformerFactory stff = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
    //2.根据工厂获取转换器
    /*
     * 传输
     * 创建xml
     * */
    TransformerHandler th = stff.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 FileOutputStream("stu.xml")));
    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();
    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();
  }
}

作业:

使用SAX | DOM 解析xml, 将解析xml的代码封装到一个方法中, 调用该方法返回一个对象(将xml解析的内容创建对象. 设置属性值, 返回对象)

<phone id="iph">
  <name>ls</name>
  <price>1999</price>
  <color>黑色</color>
</phone>

解析后:
	phone对象 属性值 name ls  price 1999 color 黑色

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/371987.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Go-Zero】Error: only one service expected goctl一键转换生成rpc服务错误解决方案

【Go-Zero】Error: only one service expected goctl一键转换生成rpc服务错误解决方案 大家好 我是寸铁&#x1f44a; 总结了一篇Error: only one service expected goctl一键转换生成rpc服务错误解决方案的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 问题背景 今天寸铁在…

云上未来:探索云计算的技术变革与应用趋势

一、云计算的起源和演进 1.1 早期计算模型 在探讨云计算的起源和演进之前&#xff0c;理解早期的计算模型对于构建全面的视角至关重要。早期计算模型的发展奠定了云计算的基础&#xff0c;为其演进提供了技术和理念的支撑。 1.1.1 集中式计算模型 在计算技术的早期阶段&…

苹果 Vision Pro 产地首次公布:原汁原味的中国制造丨 RTE 开发者日报 Vol.143

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

Day4.

单链表 #include <head.h>typedef struct List{int value;struct List *pointe; }*list; list create_space() {list s(struct List *)malloc(sizeof(struct List)); //向堆区申请空间s->pointe NULL;//初始化s->value 0;return s; } list inserhead_list(lis…

揭秘程序员之夜:为何他们与电脑不分昼夜?

在这个数字化飞速发展的时代&#xff0c;程序员已经成为这座高科技城堡中的守夜人。他们的电脑似乎从未进入“睡眠”状态&#xff0c;长明的屏幕背后隐藏着怎样的奥秘&#xff1f;今天&#xff0c;让我们一起探索程序员们坚守岗位的真实理由。 有一种“派对”一直在程序员的电脑…

14.scala隐式转换

目录 概述实践代码执行结果 结束 概述 隐式转换&#xff1a;偷偷的(隐式)对现有功能进行增强(转换) 实践 代码 package com.fun.scalaimport java.io.File import scala.io.Sourceobject ImplicitApp {def main(args: Array[String]): Unit {// implicit 2 to 等价 &…

2.5作业

通过消息队列实现进程之间通信 send #include <myhead.h> struct msgbuf {long int mtype; char mtext[1024]; }; //定义一个消息大小 #define MSGSIZE sizeof(struct msgbuf)-sizeof(long int) int main(int argc, const char *argv[]) {//1、创建key值以便创建消息队…

Java与SpringBoot:实现高效车险理赔信息管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

go消息队列RabbitMQ - 订阅模式-direct

1.发布订阅 在Fanout模式中&#xff0c;一条消息&#xff0c;会被所有订阅的队列都消费。但是&#xff0c;在某些场景下&#xff0c;我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。 在Direct模型下&#xff1a; 队列与交换机的绑定&#xff0c;不能…

ctfshow-web1~10-WP

web1 右键查看源码就能看到flag web2 打开网页提示无法查看源代码,右键也使用不了,那我们就在url前面加上view-source: view-source:http://83a83588-671e-4a94-9c6f-6857f9e20c2f.chall.ctf.show/ 访问后即可获得flag web3 右键源码也没看到信息,去查看一下请求头和响应…

2.05作业

1.请编程实现哈希表的创建存储数组{12,24,234,234,23,234,23}&#xff0c;输入key查找的值&#xff0c;实现查找功能。 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> typedef int datatype; typedef struct Node {datat…

Leetcode24:两两交换链表中的节点

一、题目 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例&#xff1a; 输入&#xff1a;head [1,2,3,4] 输出&#xff…

88.网游逆向分析与插件开发-物品使用-物品使用策略管理UI的设计

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;物品交换的逆向分析与C封装-CSDN博客 码云地址&#xff08;ui显示角色数据 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;f1b9b1a69ac3e2c3…

Python爬虫requests库详解

使用 requests 上一节中&#xff0c;我们了解了 urllib 的基本用法&#xff0c;但是其中确实有不方便的地方&#xff0c;比如处理网页验证和 Cookies 时&#xff0c;需要写 Opener 和 Handler 来处理。为了更加方便地实现这些操作&#xff0c;就有了更为强大的库 requests&…

第97讲:MHA高可用集群模拟主库故障以及修复过程

文章目录 1.分析主库故障后哪一个从库会切换为主库2.模拟主库故障观察剩余从库的状态2.1.模拟主库故障2.3.当前主从架构 3.修复故障的主库3.1.修复主库3.2.当前主从架构3.3.恢复MHA 1.分析主库故障后哪一个从库会切换为主库 在模拟MHA高可用集群主库故障之前&#xff0c;我们先…

微信小程序 使用npm包

1. 微信小程序 使用npm包 1.1. npm初始化 如果你的小程序项目没有安装过npm包的话&#xff0c;你需要先初始化npm npm init1.2. 安装npm包 这里以vant-weapp(小程序UI组件库)为例&#xff1a; npm i vant-weapp -S --production1.3. npm包构建 1.3.1. 点击微信开发者工具右…

数据库管理-第145期 最强Oracle监控EMCC深入使用-02(20240205)

数据库管理145期 2024-02-05 数据库管理-第145期 最强Oracle监控EMCC深入使用-02&#xff08;20240205&#xff09;1 监控方式2 度量配置3 阻塞4 DG监控总结 数据库管理-第145期 最强Oracle监控EMCC深入使用-02&#xff08;20240205&#xff09; 作者&#xff1a;胖头鱼的鱼缸&…

C++学习Day03之类对象作为类成员

目录 一、程序及输出二、分析与总结 一、程序及输出 #include<iostream> using namespace std; #include <string>class Phone { public:Phone(string pName){cout << "phone 的有参构造调用" << endl;m_PhoneName pName;}~Phone(){cout &…

【已解决】Oracle 12541 TNS 无监听程序

目录 1、找到Oracle监听服务&#xff08;OracleOraDb10g_homeTNLListener&#xff09;&#xff0c;停止运行 2、首先查看监听文件是否超过4G 3、修改配置文件 连接oracle突然报错&#xff0c;提示Oracle 12541 TNS 无监听程序&#xff0c;可以按照以下步骤解决 1、找到Ora…