BCSP-玄子Share-Java框基础_解析XML

news2024/12/23 17:22:45

二、XML

2.1 XML 简介

XML(Extensible Markup Language),可扩展标记语言

2.1.1 特点

  • XML 与操作系统、编程语言的开发平台无关
  • 规范统一,实现不同系统之间的数据交换

2.1.2 作用

  • 数据存储
  • 数据交换
  • 数据配置

2.1.3 XML 文档结构

<?xml version="1.0" encoding="UTF-8"?>
<!-- 声明 -->
<books>
<!-- 根元素 -->
	<!-- 图书信息 -->
	<book id="bk101">
        <!-- id="bk101" 属性 -->
		<title>.NET高级编程</title>
		<author>王姗</author>
		<description>包含C#框架和网络编程等</description>
	</book>
	<book id="bk102">
		<title>XML基础编程</title>
		<author>李明明</author>
		<description>包含XML基础概念和基本用法</description>
	</book>
</books>

使用标签描述的文档元素信息,成对出现。

节点不包含子节点可自闭合<title text="自闭合"/>

2.2 XML 标签

XML 文档的内容元素由一系列标签组成

<元素名 属性名="属性值">元素内容(子元素、字符等)</元素名>
<!-- 开始标签 --> <!-- 元素允许是空元素,语法:如<title></title>、<title/>--> <!-- 结束标签 -->

2.2.1 元素命名规则

  • 名称中可以包含字母、数字或者其他的字符
  • 名称不能以数字或者标点符号开始
  • 名称不能以字符xml(或者XML、Xml)开始
  • 名称中不能含空格

2.2.2 属性语法规则

  • 属性可以加在任何一个元素的起始标签上,但不能加在结束标签上
  • 属性值用双引号包裹
  • 一个元素可以有多个属性,多个属性之间用空格隔开
  • 属性值中不能直接包含 <、"、&

2.2.3 XML 中的特殊字符的处理

XML 中的特殊字符包括 < 、> 、' 、" 、&

使用预定义实体对特殊字符进行转义

特殊字符实体名称
<&lt;
>&gt;
""
&apos;
&&amp;

在元素的文本中使用 CDATA 节处理

<description>
         <![CDATA[讲解了元素<title>以及</title>的使用]]>
</description>

2.2.4 编写格式良好的 XML 文档

格式良好的 XML 文档需要遵循如下规则

  • 有 XML 声明语句
  • 有且仅有一个根元素
  • 标签大小写敏感
  • 属性值用双引号
  • 标签成对/空标签关闭
  • 元素正确嵌套

2.3 XML 解析技术

2.3.1 DOM

  • 基于 XML 文档树结构的解析
  • 适用于多次访问的 XML 文档
  • 比较消耗资源

2.3.2 SAX

  • 基于事件的解析
  • 适用于大数据量的 XML 文档
  • 占用资源少,内存消耗小

DOM 和 SAX 不针对特定语言,只是定义了一些接口,以及部分缺省实现(使用空方法实现接口)

2.3.3 JDOM

  • 针对 Java 的特定文档模型
  • 使用具体类而不使用接口
  • API 大量使用了 Java 集合类型

2.3.4 DOM4J

  • 非常优秀的开源 Java XML API
  • 面向接口编程,比 JDOM 更加灵活
  • 使用 Java 集合框架处理 XML

2.4 DOM 解析 XML 文档

2.4.1 DM 解析 XML 原理

文档对象模型(Document Object Model)DOM 把 XML 文档映射成一个倒挂的树

<book >
    <title>三国演义</title>
    <author>罗贯中</author>
    <price>30元</price>
</book>

使用 Oracle 提供的 JAXP(Java API for XML Processing)

  • org.w3c.dom:W3C 推荐的用于使用 DOM 解析 XML 文档的接
  • org.xml.sax:用于使用 SAX 解析 XML 文档的接口
  • javax.xml.parsers:解析器工厂工具,获得并配置特殊的分析器

2.4.2 解析 XML 文档实现步骤

  1. 创建解析器工厂 DocumentBuilderFactory 对象
  2. 由解析器工厂对象创建解析器 DocumentBuilder 对象
  3. 由解析器对象对 XML 文件进行解析、构建 DOM 树,创建相应的 Document 对象
  4. 以Document 对象为起点对 DOM 树的节点进行增加、删除、修改、查询等操作

2.4.3 解析 XML 部分常用 API

常用接口说明常用方法
Node代表了文档树中的一个抽象节点,有 Document、Element、Text 等子对象NodeList getChildNodes()
Node getFirstChild()
Node getLastChild()
Node getNextSibling()
Node getPreviousSibling()
Node appendChild(Node child)
String getNodeName()
String getNodeValue()
short getNodeType()
NodeList包含了一个或多个节点(Node)的列表int getLength()
Node item(int index)
Document表示整个 XML 文档NodeList getElementsByTagName(String tagname)
Element getElementById(String id)
Element getDocumentElement()
Element createElement(String tagname)
ElementXML 文档中的一个元素,是 Node 最主要的子对象String getAttribute(String name)
NodeList getElementsByTagName(String tagname)
String getTagName()

2.4.4 访问 DOM 树节点属性

显示 XML 文件中收藏的手机品牌和型号

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<PhoneInfo>
    <Brand name="华为">
        <Type name="P90"/>
        <Item>
            <title>标题信息</title>
            <link>链接</link>
            <description>描述</description>
            <pubDate>2023-02-01</pubDate>
        </Item>
    </Brand>
    <Brand name="苹果">
        <Type name="iPhone Z"/>
        <Type name="iPhone ZL"/>
    </Brand>
    <Brand name="三星">
        <Type name="NoteX"/>
    </Brand>
</PhoneInfo>
  • 演示案例一
public class Book {
    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse("src/main/java/CH15_XML/PhoneInfo.xml");
        NodeList bookList = doc.getElementsByTagName("Brand");
        for (int i = 0; i < bookList.getLength(); i++) {
            Node brand = bookList.item(i);
            Element element = (Element) brand;
            String attrVal = element.getAttribute("name");
            NodeList types = element.getChildNodes();
            for (int j = 0; j < types.getLength(); j++) {
                Node typeNode = types.item(j);
                if (typeNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element typeElement = (Element) typeNode;
                    String type = typeElement.getAttribute("name");
                    System.out.println("手机:" + attrVal + type);
                }
            }
        }
    }
}
  • 演示案例二
public class Xz01 {
    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
        NodeList brandList = DocumentBuilderFactory
                .newInstance()
                .newDocumentBuilder()
                .parse("src/main/resources/PhoneInfo.xml")
                .getElementsByTagName("Brand");

        for (int i = 0; i < brandList.getLength(); i++) {
            Element brandElement = (Element) brandList.item(i);
            System.out.println(brandElement.getTagName() + ":" + brandElement.getAttribute("name"));

            NodeList typeList = brandElement.getElementsByTagName("Type");
            for (int j = 0; j < typeList.getLength(); j++) {
                Element typeElement = (Element) typeList.item(j);
                System.out.println("\t" + typeElement.getTagName() + ":" + typeElement.getAttribute("name"));

                NodeList itemList = brandElement.getElementsByTagName("Item");
                for (int k = 0; k < itemList.getLength(); k++) {
                    Element itemElement = (Element) itemList.item(k);
                    NodeList pubDateList = itemElement.getElementsByTagName("pubDate");
                    System.out.print("\t" + itemElement.getTagName() + ":");
                    for (int l = 0; l < pubDateList.getLength(); l++) {
                        String textContent = pubDateList.item(l).getTextContent();
                        System.out.println(textContent);
                    }
                }
            }
        }
    }
}
//  Brand:华为
//        Type:P90
//        Item:2023-02-01
//  Brand:苹果
//        Type:iPhone Z
//        Type:iPhone ZL
//  Brand:三星
//        Type:NoteX

调用 Node 对象的 getChildNodes() 方法有时会包含 XML 文档中的空白符,导致调用 Node 对象方法出错,解决办法包括:

  1. 取得 Node 对象后判断node.getNodeType() == Node.ELEMENT_NODE,即判断是否是元素节
  2. 点将 Node 对象转换为 Element 对象,使用 Element 的 getElementsByTagName(String name)

2.4.5 访问 DOM 树节点内容

显示XML文件中手机新闻的发布日期

  • 演示案例
public class Book2 {
    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse("src/main/java/CH15_XML/PhoneInfo.xml");
        NodeList bookList = doc.getElementsByTagName("pubDate");
        Element pubDateElement = (Element) bookList.item(0);
        String nodeValue = pubDateElement.getFirstChild().getNodeValue();
        System.out.println(nodeValue);
    }
}
// 2023-02-01

2.4.6 添加 DOM 节点并保存

  • 演示案例
public class Book3 {
    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, TransformerException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse("src/main/java/CH15_XML/PhoneInfo.xml");
        
        Element brandElement = doc.createElement("Brand");
        brandElement.setAttribute("name", "三星");
        
        Element typeElement = doc.createElement("Type");
        typeElement.setAttribute("name", "NoteX");
        
        brandElement.appendChild(typeElement);
        
        Element phoneInfoElement = (Element) doc.getElementsByTagName("PhoneInfo").item(0);
        phoneInfoElement.appendChild(brandElement);
        
        TransformerFactory tff = TransformerFactory.newInstance();
        Transformer tf = tff.newTransformer();
        DOMSource domSource = new DOMSource(doc);
        tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        StreamResult streamResult = new StreamResult(Files.newOutputStream(Paths.get("src/main/java/CH15_XML/PhoneInfo.xml")));
        tf.transform(domSource, streamResult);
    }
}
    <Brand name="三星">
        <Type name="NoteX"/>
    </Brand>

2.4.7 修改或删除 DOM 节点

  • 演示案例
public class Book4 {
    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, TransformerException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse("src/main/java/CH15_XML/PhoneInfo.xml");
        NodeList list = doc.getElementsByTagName("Brand");
        for (int i = 0; i < list.getLength(); i++) {
            Element brandItem = ((Element) list.item(i));
            String brandName = brandItem.getAttribute("name");
            if ("三星".equals(brandName)) {
                // ElementBrand.setAttribute("name", "OPPO");
                brandItem.getParentNode().removeChild(brandItem);
                // 先获取父节点,再删除子节点
            }
        }
        
        TransformerFactory tff = TransformerFactory.newInstance();
        Transformer tf = tff.newTransformer();
        DOMSource domSource = new DOMSource(doc);
        tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        StreamResult streamResult = new StreamResult(Files.newOutputStream(Paths.get("src/CH15_XML/PhoneInfo.xml")));
        tf.transform(domSource, streamResult);
    }
}

2.5 DOM4J 解析 XML 文档

2.5.1 DOM4J 常用 API

DOM4J 的主要接口都定义在 org.dom4j 包里

接口说明
Node:为所有的 DOM4J 中的 XML 节点定义了多态行为
Branch:为能够包含子节点的节点定义了公共行为
Element:定义 XML 元素
Document:定义 XML 文档
Entity:定义 XML 实体
Attribute:定义了 XML 的属性
DocumentType:定义 XML DOCTYPE 声明
ProcessingInstruction:定义 XML 处理指令
CharacterData:标识接口,标识基于字符的节点
Text:定义 XML 文本节点
CDATA:定义了 XML CDATA 区域
Comment:定义了 XML 注释的行为
常用接口常用方法
BranchElement elementById(String id)
Element addElement(String name)
boolean remove(Node node)
DocumentElement getRootElement()
ElementElement element(String name)
List elements()
List elements(String tagname)
Iterator elementIterator()
Iterator elementIterator(String name)
Attribute attribute(String name)
Element addAttribute(String name, String value)
String getText()

2.5.2 DOM4J 读取收藏信息

  • 演示案例
package CH15_XML;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.Iterator;

public class Book5 {
    public static void main(String[] args) throws DocumentException {
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new File("src/main/java/CH15_XML/PhoneInfo.xml"));
        Element rootElement = document.getRootElement();
        for (Iterator<Element> itBrand = rootElement.elementIterator(); itBrand.hasNext(); ) {
            Element brand = itBrand.next();
            System.out.println(brand.attributeValue("name"));
            for (Iterator<Element> itType = brand.elementIterator(); itType.hasNext(); ) {
                Element type = itType.next();
                System.out.println("\t" + type.attributeValue("name"));
            }
        }
    }
}
//  华为
//	    P90
//	    null
//  苹果
//	    iPhone Z
//	    iPhone ZL
//  三星
//	    NoteX

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

专业课130+上岸哈尔滨工业大学803信号与系统和数字逻辑电路考研大纲真题参考书哈工大

​专业课130上岸哈尔滨工业大学803信号与系统和数字逻辑电路考研大纲真题参考书哈工大 政治&#xff1a; 9月开始&#xff0c;用肖秀荣的精讲精练&#xff0c;做1000题&#xff0c;一章视频做一章题&#xff0c;错题标记。以后会不定时看&#xff0c;每天大概2个小时。时间可…

navicat访问orcal数据库

1&#xff09;因为不能直接访问服务器&#xff0c;所以通过中介进行了端口转发&#xff1b; 2&#xff09;依然不能访问&#xff0c;提示netadmin权限什么错误&#xff1b; 3&#xff09;下载了一个 PLSQL Developer 13.0.0.1883 版本&#xff0c;自带的instantclient 好像不…

C语言:选择+编程(每日一练Day15)

目录 选择题&#xff1a; 题一&#xff1a; 题二&#xff1a; 题三&#xff1a; 题四&#xff1a; 题五&#xff1a; 编程题&#xff1a; 题一&#xff1a;寻找奇数 思路一&#xff1a; 题二&#xff1a;寻找峰值 思路一&#xff1a; 本人实力有限可能对一些地方解…

Compression Bypass Logic

默认,EDT逻辑中包含bypass逻辑,bypass电路可以bypass EDT逻辑,访问设计core中未压缩的扫描链。 bypass EDT逻辑可以应用未压缩test patterns到设计中 Debug 压缩test patterns。应用附加自定义未压缩扫描链。应用来自其他ATPG工具的test patterns。在扫描插入时,bypass可以…

SpringBoot运维实用篇、打包、运行、高级配置、多环境开发、日志

文章目录 SpringBoot运维实用篇YW-1.SpringBoot程序的打包与运行程序打包程序运行SpringBoot程序打包失败处理命令行启动常见问题及解决方案SpringBoot项目快速启动&#xff08;Linux版&#xff09; YW-2.配置高级YW-2-1.临时属性设置YW-2-2.配置文件分类YW-2-3.自定义配置文件…

精益创业就是想控制:到底浪费在哪里?

精益创业就是想控制&#xff1a;到底浪费在哪里&#xff1f;【安志强趣讲278期】 趣讲大白话&#xff1a;创业的浪费是惊人的 **************************** 现代社会的问题不是能不能制造出来&#xff1f; 而是该不该制造 产能过剩是社会的核心矛盾 精益创业就是预见浪费 系统…

【mybatis-plus进阶】多租户场景中多数据源自定义来源dynamic-datasource实现

Springbootmybatis-plusdynamic-datasourceDruid 多租户场景中多数据源自定义来源dynamic-datasource实现 文章目录 Springbootmybatis-plusdynamic-datasourceDruid 多租户场景中多数据源自定义来源dynamic-datasource实现0.前言1. 作者提供了接口2. 基于此接口的抽象类实现自…

行军遇到各种复杂地形怎么处理?

行军遇到各种复杂地形怎么处理&#xff1f; 【安志强趣讲《孙子兵法》第30讲】 【原文】 凡军好高而恶下&#xff0c;贵阳而贱阴&#xff0c;养生而处实&#xff0c;军无百疾&#xff0c;是谓必胜。 【注释】 阳&#xff0c;太阳能照到的地方。阴&#xff0c;太阳照不到的地方。…

如何把DAYi-51开发板_做成?

DAYi-51开发板 1> 思维认知1.1> 凡是遇到卡壳&#xff0c;学不下去的情况&#xff0c;只有1个原因1.2> 什么叫掌握了&#xff1f;1.3> 深度练习1.4> 极度专注 2> 环境2.1> 大环境2.2> 贴身环境 3> 技术层面3.1> 找高手 1> 思维认知 1.1> 凡…

Redis之缓存和数据库双写一致方案讨论解读

目录 什么是缓存双写一致 更新缓存还是删除缓存&#xff1f; 先删除缓存,再更新数据库 场景描述 解决方案&#xff1a;延时双删策略 先更新数据库&#xff0c;再删除缓存 场景描述 解决方案&#xff1a;重试机制引入MQ ​编辑 什么是缓存双写一致 只要用缓存&#xf…

如何合并为pdf文件?合并为pdf文件的方法

在数字化时代&#xff0c;人们越来越依赖电子文档进行信息交流和存储。合并为PDF成为一种常见需求&#xff0c;它能将多个文档合而为一&#xff0c;方便共享和管理。无论是合并多个单页文档&#xff0c;还是将多页文档合并&#xff0c;操作都变得简单高效。那么。如何合并为pdf…

哈夫曼编码实现文件的压缩和解压

程序示例精选 哈夫曼编码实现文件的压缩和解压 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《哈夫曼编码实现文件的压缩和解压》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0…

【Sentinel】核心API-Entry与Context

文章目录 一、Entry1、Entry的声明2、使用API自定义资源3、基于SentinelResource注解标记资源 二、Context1、Context介绍2、Context的初始化3、AbstractSentinelInterceptor4、ContextUtil 一、Entry 1、Entry的声明 默认情况下&#xff0c;Sentinel会将controller中的方法作…

关于人工智能的担忧

人工智能的快速发展引发了一系列关于其潜在风险和担忧的讨论。以下是一些常见的人们对人工智能的担忧&#xff1a; 失业问题&#xff1a;人工智能的出现可能会导致很多工作岗位的消失&#xff0c;特别是那些需要重复性劳动的工作。人们担心机器取代人类工作将导致大规模失业和社…

W5500-EVB-PICO进行MQTT连接订阅发布教程(十二)

前言 上一章我们用开发板通过SNTP协议获取网络协议&#xff0c;本章我们介绍一下开发板通过配置MQTT连接到服务器上&#xff0c;并且订阅和发布消息。 什么是MQTT&#xff1f; MQTT是一种轻量级的消息传输协议&#xff0c;旨在在物联网&#xff08;IoT&#xff09;应用中实现设…

计算机毕业设计 社区买菜系统 Vue+SpringBoot+MySQL

作者主页&#xff1a;Designer 小郑 作者简介&#xff1a;Java全栈软件工程师一枚&#xff0c;来自浙江宁波&#xff0c;负责开发管理公司OA项目&#xff0c;专注软件前后端开发、系统定制、远程技术指导。CSDN学院、蓝桥云课认证讲师&#xff0c;全栈领域优质创作者。 项目内容…

JavaScript中的原型链(prototype chain)

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ JavaScript中的原型链⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏…

如何访问GitHub

1、手动修改hosts 1.1、查找到最新的GitHub的hosts信息 通过链接&#xff1a;https://raw.hellogithub.com/hosts 进行查找最新的GitHub的hosts信息 1.2、查找到hosts文件位置 先找到 hosts 文件的位置&#xff0c;不同操作系统&#xff0c;hosts 文件的存储位置也不同&…

量化:基于RSRS的市场择时复现

文章目录 资源研报解读概念Q&ARSRS指标构建交易逻辑 资源 《阻力支撑相对强度RSRS研究报告》 链接&#xff1a;https://pan.baidu.com/s/1EhtoC25WSO7WpNiyZpcKYA 提取码&#xff1a;2023 合吾~~~祝投资顺利愉快&#xff01; 研报复现系列&#xff08;5&#xff09;基于阻力…

Dev-C++中,不使用include <string>也可以用string name1, name2; 为什么?

Dev-C中&#xff0c;不使用 include <string> 也可以用 string name1, name2; 为什么&#xff1f; 例如&#xff1a; #include <iostream> //#include <string> using namespace std; int main() { string s1, s2; cout << "请输入两个…