前言

这几天在手写Spring IOC的时候遇上了xml文件的解析,通过解析Spring.xml配制文件的方式来创建对象。因为之前从来都没遇见过相关的需求,所以对此做一份记录
XML (eXtensible Markup Language) 意为可扩展标记语言,被多数技术人员用以选择作为数据传输的载体,成为一种通用的数据交换格式,xml的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的便利。在不同的语言中,解析mxl的方式都是一样的,只不过实现的语法不同而已。
XML解析主要有两种方式,一种称为DOM解析,另外一种称之为SAX解析

  • DOM解析:Document Object Model,简单的来讲,DOM解析就是读取XML文件,然后在文件文档描述的内容在内存中生成整个文档树。
  • SAX解析:Simple API for XML,简单的来讲,SAX是基于事件驱动的流式解析模式,一边去读文件,一边解析文件,在解析的过程并不保存具体的文件内容。

这两种方式都是原生的解析方式,在编码的时候难免会有一些繁琐,所以我们经常会用到一些第三方的框架,目前主流的有:JDOM、StAX、XPath、DOM4j
为了方便后面的测试,先给出一份xml配制文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans><bean id="userDao" class="cuit.pymjl.entity.UserDao"/><bean id="userService" class="cuit.pymjl.entity.UserService"><property name="id" value="2"/><property name="userDao" ref="userDao"/></bean></beans>

Dom解析

  1. 概述

DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。DOM是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的。

  • 优点:在内存中形成了整个文档树,有了文档树,就可以随便对文档中任意的节点进行操作(增加节点、删除节点、修改节点信息等),而且由于已经有了整个的文档树,可以实现对任意节点的随机访问。
  • 缺点:由于需要在内存中形成文档树,需要消耗的内存比较大,尤其是当文件比较大的时候,消耗的代价还是不容小视的。
  1. 代码示例
public class XmlReader {public static void main(String[] args) {parse();}public static void parse() {// Spring.xml的内容为上面所示XML代码内容File file = new File("C:\\Users\\Admin\\JavaProjects\\blog-code-demo\\xml-parse\\src\\main\\resources\\spring.xml");try {// 创建文档解析的对象DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();// 解析文档,形成文档树,也就是生成Document对象Document document = builder.parse(file);// 获得根节点Element rootElement = document.getDocumentElement();System.out.printf("Root Element: %s\n", rootElement.getNodeName());// 获得根节点下的所有子节点NodeList students = rootElement.getChildNodes();for (int i = 0; i < students.getLength(); i++) {// 获得第i个子节点Node childNode = students.item(i);// 由于节点多种类型,而一般我们需要处理的是元素节点// 元素节点就是非空的子节点,也就是还有孩子的子节点if (childNode.getNodeType() == Node.ELEMENT_NODE) {Element childElement = (Element) childNode;System.out.printf(" Element: %s\n", childElement.getNodeName());System.out.printf("  Attribute: id = %s\n", childElement.getAttribute("id"));System.out.printf("  Value: class= %s\n", childElement.getAttribute("class"));// 获得第二级子元素NodeList childNodes = childElement.getChildNodes();for (int j = 0; j < childNodes.getLength(); j++) {Node child = childNodes.item(j);if (child.getNodeType() == Node.ELEMENT_NODE) {Element eChild = (Element) child;String value = eChild.getAttribute("value");String ref = eChild.getAttribute("ref");if (value != null && value.length() > 0) {System.out.printf("  sub Element %s:  name= %s value= %s\n", eChild.getNodeName(),eChild.getAttribute("name"), value);} else {System.out.printf("  sub Element %s:  name= %s ref= %s\n", eChild.getNodeName(), eChild.getAttribute("name"),ref);}}}}}} catch (ParserConfigurationException | SAXException | IOException e) {e.printStackTrace();}}
}

因为我使用的原生的Dom解析,所以就不需要引入任何其他的依赖

  1. 运行结果:

SAX解析

  1. 概述

SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。一般来说,SAX还比它的替代者DOM快许多。

  • 优点:SAX解析由于是一边读取文档一边解析的,所以所占用的内存相对来说比较小。
  • 缺点:无法保存文档的信息,无法实现随机访问节点,当文档需要编辑的时候,使用SAX解析就比较麻烦了。

SAX解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag.特别是当开发人员只需要处理文档中所包含的部分数据时,SAX这种扩展能力得到了更好的体现。但用SAX解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据

  1. 代码示例:
package cuit.pymjl;import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.io.IOException;/*** @author Pymjl* @version 1.0* @date 2022/7/4 13:01**/
public class SAXHandler extends DefaultHandler {@Overridepublic void startDocument() throws SAXException {System.out.println("====================Starting parse the document=======================");}@Overridepublic void endDocument() throws SAXException {System.out.println("=================Ending parse the document=======================");}@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {if (qName.equals("bean")) {System.out.println("Bean{id=" + attributes.getValue(0) +",class=" + attributes.getValue(1) + "}");} else if (qName.equals("property")) {System.out.println("Property{name=" + attributes.getValue(0) +",value=" + attributes.getValue(1) + "}");}}public static void parser() {try {File file = new File("C:\\Users\\Admin\\JavaProjects\\blog-code-demo\\xml-parse\\src\\main\\resources\\spring.xml");// 创建一个SAX解析器SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();javax.xml.parsers.SAXParser parser = saxParserFactory.newSAXParser();// 解析对应的文件parser.parse(file, new SAXHandler());} catch (ParserConfigurationException | SAXException | IOException e) {e.printStackTrace();}}public static void main(String[] args) {parser();}
}
  1. 运行截图

小结

好了,关于XML解析我就说在这里,我是直接参照的原生的方式写的xml解析,并没有使用第三方库,如果其他小伙伴对此感兴趣可以自行研究其他的框架
最后,贴上我在写Spring解析xml的代码(这里用到了Hutool的工具类,但是其实只是对原生的一个简单的封装)

   /*** 加载BeanDefinition的具体实现方法,对xml进行解析,并且将解析后的bean定义信息放入bean定义注册表中** @param inputStream 输入流* @throws ClassNotFoundException 类没有发现异常*/protected void doLoadBeanDefinitions(InputStream inputStream) throws ClassNotFoundException {// 1. 获取xml文档对象Document doc = XmlUtil.readXML(inputStream);// 2. xml文件的获取根节点Element root = doc.getDocumentElement();// 3. 获取根节点下的所有子节点NodeList childNodes = root.getChildNodes();// 4. 遍历所有子节点for (int i = 0; i < childNodes.getLength(); i++) {// 5.判断元素的类型,是否是元素节点if (!(childNodes.item(i) instanceof Element)) {continue;}// 6.判断对象if (!"bean".equals(childNodes.item(i).getNodeName())) {continue;}// 7.解析标签Element bean = (Element) childNodes.item(i);String id = bean.getAttribute("id");String name = bean.getAttribute("name");String className = bean.getAttribute("class");// 8.获取 Class,方便获取类中的名称Class<?> clazz = Class.forName(className);// 9.优先级 id > nameString beanName = StrUtil.isNotEmpty(id) ? id : name;if (StrUtil.isEmpty(beanName)) {beanName = StrUtil.lowerFirst(clazz.getSimpleName());}// 10.定义BeanBeanDefinition beanDefinition = new BeanDefinition(clazz);// 11.读取属性并填充for (int j = 0; j < bean.getChildNodes().getLength(); j++) {if (!(bean.getChildNodes().item(j) instanceof Element)) {continue;}if (!"property".equals(bean.getChildNodes().item(j).getNodeName())) {continue;}// 12.解析标签:propertyElement property = (Element) bean.getChildNodes().item(j);String attrName = property.getAttribute("name");String attrValue = property.getAttribute("value");String attrRef = property.getAttribute("ref");// 13.获取属性值:引入对象、值对象Object value = StrUtil.isNotEmpty(attrRef) ? new BeanReference(attrRef) : attrValue;// 14.创建属性信息PropertyValue propertyValue = new PropertyValue(attrName, value);beanDefinition.getPropertyValues().addPropertyValue(propertyValue);}if (getRegistry().containsBeanDefinition(beanName)) {throw new BeansException("Duplicate beanName[" + beanName + "] is not allowed");}// 15.注册 BeanDefinitiongetRegistry().registerBeanDefinition(beanName, beanDefinition);}

Java中的XML解析相关推荐

  1. java解析xml实例_在java中使用dom解析xml的示例分析

    本篇文章介绍了,在java中使用dom解析xml的示例分析.需要的朋友参考下 dom是个功能强大的解析工具,适用于小文档 为什么这么说呢?因为它会把整篇xml文档装载进内存中,形成一颗文档对象树 总之 ...

  2. JAVA中利用DOM解析XML文档

    JAVA中利用DOM解析XML文档 package org.sws.utils; import java.io.File;import java.io.IOException; import java ...

  3. 如何从Java中打印XML?

    本文翻译自:How to pretty print XML from Java? I have a Java String that contains XML, with no line feeds ...

  4. matlab分析xml文件_如何在Java中读取XML文件(DOM分析器)

    matlab分析xml文件 Today we will learn how to read the XML file in Java. We will also learn how to parse ...

  5. matlab分析xml文件_修改Java中的XML文件(DOM分析器)

    matlab分析xml文件 We can modify XML file in Java using DOM parser. We can add elements, remove elements, ...

  6. Java中操作Xml使用备忘

    List item 文章目录 Java中操作Xml使用备忘 1. Hutool中XmlUtil的使用简介 2. Hutool中XmlUtil快速读取Xml字符串某个节点值 [简单取值时,推荐使用] 2 ...

  7. Java 中的 XML:Java 文档模型的用法

    Java 中的 XML:Java 文档模型的用法 英文原文 内容: 代码对比 DOM JDOM dom4j Electric XML XPP 结束语 下一次... 参考资料 关于作者 对本文的评价 相 ...

  8. java中拼写xml

    本文为博主原创,未经博主允许,不得转载: xml具有强大的功能,在很多地方都会用的到.比如在通信的时候,通过xml进行消息的发送和交互. 在项目中有很多拼写xml的地方,进行一个简单的总结. 先举例如 ...

  9. 宣布EAXY:使Java中的XML更容易

    Java中的XML库是一个雷区. 操作和读取XML所需的代码量令人震惊,使用不同的库遇到类路径问题的风险很大,并且对名称空间的处理带来许多混乱和错误. 最糟糕的是,情况似乎并没有改善. 一位同事让我意 ...

最新文章

  1. R语言plotly可视化:可视化直方图、归一化的直方图、水平直方图、互相重叠的直方图、堆叠的直方图、累积直方图、通过bingroup参数设置多个直方图使用相同的bins设置、自定义直方图条形的间距
  2. Openwrt按键检测分析-窥探Linux内核与用户空间通讯机制netlink使用
  3. 多媒体技术 PI 第一期:OSS 圆桌预告
  4. What day is that day?(快速幂,打表找周期,或者求通项公式)
  5. mysql数据库cms数据库文件_PbootCMS 默认数据库转Mysql数据库教程 - 老蒋SEO博客
  6. 前沿讲座之计算机图形学
  7. Ubuntu关机重启卡死在关机动画界面
  8. 欧拉降幂公式(扩展欧拉定理)证明
  9. VS code编辑器出现open a floder or workspace... (File -> Open Folder)错误
  10. 360极速浏览器浏览网页字体模糊的解决方法
  11. Centos7安装docker并更改阿里云下载镜像地址(附带windows10安装docker教程)
  12. 1年时间从12K到30K,一位外卖小哥的真实逆袭历程!
  13. 红米note3 android go,离完美只差一步:MI 小米 红米Note5 智能手机 体验评测(含高通骁龙636性能测试)...
  14. OpenStack 运维 - 部署Nova组件 [T版]
  15. dreamweaver网页大作业 我的家乡——南京玄武湖旅游攻略(4页) 学生网页设计作业源码
  16. 趁火打劫!“疫情做饵”的网络攻击来了
  17. 22071班(11月29日)
  18. JS教程()js弹出小窗口(没有浏览器窗口地址栏,工具栏,菜单栏,显示栏,只有关闭和最小化按钮)
  19. Python:OS 异常 的17种情况
  20. CentOS6.5 安装宝塔

热门文章

  1. 滁州学院元旦晚会计算机,滁州学院机械学院2017元旦晚会精彩上演
  2. 安装lux:推荐一款网页视频下载工具。并简单使用。(win)
  3. 史上最全的安卓WebView之WebSettings说明
  4. 我的世界服务器告示牌不显示,我的世界告示牌没有字_我的世界告示牌不显示字怎么用_攻略...
  5. i2c-test工具说明文档
  6. 用python进行精细中文分句(基于正则表达式)
  7. 产品研发记录05:产品研发人员应当具备的特质
  8. 怎样给CSDN博客添加微信二维码
  9. ei会议和ei源刊的区别_EI论文发表EI期刊发表EI会议论文EI检索EI源刊
  10. at89c2051 定时器用法 c语言编程资料,用AT89C2051单片机制作的数字电容表.doc