技术:Java-Web基础|XML解析(二)之JAXP-DOM

简介: XML是标记型文档,js 使用 dom 解析标记型文档是根据 html 的层级结构,在内存中分配一个属性结构,把 html 的标签,属性和文本都封装成 document 对象、element 对象,属性对象、文本对象,node 节点对象。「XML」解析技术xml的解析技术:dom 和 sax。

1 XML介绍和解析方式


「XML解析介绍

XML是标记型文档,js 使用 dom 解析标记型文档是根据 html 的层级结构,在内存中分配一个属性结构,把 html 的标签,属性和文本都封装成 document 对象、element 对象,属性对象、文本对象,node 节点对象。


「XML」解析技术

xml的解析技术:dom 和 sax。

DOM:Document Object Model,文档对象模型。这种方式是 W3C 推荐的处理XML 的一种方式。

SAX:Simple APl for XML。这种方式不是官方标准,属于开源社区 XML-DEV,几乎所有的 XML 解析器都支持它。


「XML-dom」

特点:封装在内存处理。

优点:方便实现增删改的操作。

缺点:如果文件过大,可导致内存溢出。


「XML-sax」

特点:事件驱动,从上到下,依次解析,边读取边解析。

优点:不会导致内存溢出

缺点:不能实现增删改的操作


2 XML解析器

解析 XML 技术(dom 和 sax),需要一个解析器。

  • JAXP(Java AOI for XML Processing):是 SUN 公司推出的解析标准实现。
  • Dom4J:是开源组织推出的解析开发包。(实际开发中常用)
  • JDom:是开源组织推出的解析开发包。


2.1 JAXP-DOM解析

解析的逻辑同Python中差不多,如果了解其中一种语言,其他语言基本上可以去看下。

在JDK中,可以在rt.jar包中找到解析方法。

image.png


「步骤」

1、创建 DOM 解析器的工厂,得到 DOM 解析器对象

2、解析 XML 文档,得到代表整个文档的 Document 对象,将其放在内存中

3、获取根元素集合

4、解析处理


2.2 创建实验xml

首先创建一个xml,这里创建一个persons.xml,文件内容如下:

<?xmlversion="1.0" encoding="utf-8"?><persons><personsid="001"><name>张小帅</name><sex></sex><age>18</age></person><personsid="002"><name>刘晓萌</name><sex></sex><age>21</age></person><personsid="003"><name>王老四</name><sex></sex><age>38</age></person></persons>


2.3 解析技术DOM

创建DomParserXmlTest.java,内容如下。

packagecom.liuyc.tooljdk.xml;
importorg.w3c.dom.*;
importorg.xml.sax.SAXException;
importjavax.xml.parsers.DocumentBuilder;
importjavax.xml.parsers.DocumentBuilderFactory;
importjavax.xml.parsers.ParserConfigurationException;
importjava.io.IOException;
importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.Map;
/*** <p> DomParserXmlTest </p>*/publicclassDomParserXmlTest {
publicstaticvoidmain(String[] args) {
StringxmlPath="./tool-jdk8/src/main/java/com/liuyc/tooljdk/xml/persons.xml";
try {
// 1、创建 DOM 解析器的工厂,得到 DOM 解析器对象DocumentBuilderbuilder=DocumentBuilderFactory.newInstance().newDocumentBuilder();
// 2、解析 XML 文档,得到代表整个文档的 Document 对象,将其放在内存中Documentdocument=builder.parse(xmlPath);
// 3、获取根元素 personsSystem.out.println("----------------------------------------------------------------------");
Elementroot=document.getDocumentElement();
System.out.println("根元素节点名称:"+root.getNodeName());
System.out.println("根元素节点类型(是一个元素:Element = 1):"+root.getNodeType());
System.out.println("----------------------------------------------------------------------");
NodeListpersonNode=document.getElementsByTagName("person");
System.out.println("person节点数量:"+personNode.getLength());
NodepersonEle=personNode.item(1);
System.out.println("person元素节点名称:"+personEle.getNodeName());
System.out.println("person元素节点文本内容:"+personEle.getTextContent());
System.out.println("person元素节点属性名称:"+personEle.getAttributes().item(0).getNodeName());
System.out.println("person元素节点属性值:"+personEle.getAttributes().item(0).getNodeValue());
System.out.println("person元素节点属性类型(是一个属性:Attr = 2):"+personEle.getAttributes().item(0).getNodeType());
System.out.println("----------------------------------------------------------------------");
NodeListnames=document.getElementsByTagName("name");
System.out.println("所有name元素标签内存地址:"+names);
System.out.println("索引为1的name元素标签名称:"+names.item(1).getNodeName());
System.out.println("索引为1的name元素标签的值:"+names.item(1).getTextContent());
System.out.println("----------------------------------------------------------------------");
// 4、解析NodeListlist=root.getChildNodes();
ArrayList<Map<String, Object>>arr=newArrayList<>();
for (inti=0; i<list.getLength(); i++) {
// 遍历所有person节点Nodeitem=list.item(i);
if (item.getNodeType() ==Node.ELEMENT_NODE) {
Map<String, Object>map=newHashMap<>();
NamedNodeMapattributes=item.getAttributes();
// 遍历所有person属性for (intj=0; j<attributes.getLength(); j++) {
NodenodePerson=attributes.item(j);
map.put(nodePerson.getNodeName(), nodePerson.getNodeValue());
                    }
// 遍历所有person节点的内容NodeListlist2=item.getChildNodes();
for (intj=0; j<list2.getLength(); j++) {
Nodeitem2=list2.item(j);
if (item2.getNodeType() ==Node.ELEMENT_NODE) {
Nodenode=item2.getFirstChild();
if (item2.getNodeName().equals("name")) {
map.put("name", node.getTextContent());
                            }
if (item2.getNodeName().equals("sex")) {
map.put("sex", node.getTextContent());
                            }
if (item2.getNodeName().equals("age")) {
map.put("age", Integer.parseInt(node.getTextContent()));
                            }
                        }
                    }
arr.add(map);
                }
            }
arr.forEach(System.out::println);
        } catch (ParserConfigurationExceptione) {
// TODO Auto-generated catch blocke.printStackTrace();
        } catch (SAXExceptione) {
// TODO Auto-generated catch blocke.printStackTrace();
        } catch (IOExceptione) {
// TODO Auto-generated catch blocke.printStackTrace();
        }
    }
}


2.4 执行结果


执行上面代码获取的结果如下:


------------------------------------------

根元素节点名称:persons

根元素节点类型(是一个元素:Element = 1):1

------------------------------------------

person节点数量:3

person元素节点名称:person

person元素节点文本内容:

 刘晓萌

 女

 21


person元素节点属性名称:sid

person元素节点属性值:002

person元素节点属性类型(是一个属性:Attr = 2):2

------------------------------------------

所有name元素标签内存地址:com.sun.org.apache.xerces.internal.dom.DeepNodeListImpl@27d6c5e0

索引为1的name元素标签名称:name

索引为1的name元素标签的值:刘晓萌

------------------------------------------

{sex=男, name=张小帅, age=18, sid=001}

{sex=女, name=刘晓萌, age=21, sid=002}

{sex=男, name=王老四, age=38, sid=003}


还有一些其他方法,例如:

获取第一个节点:getFirstChild()

获取最后一个节点:getLastChild()

其他的一些属性,建议参考下JDK的源代码来加深理解。


2.5 新增节点

「步骤」

1、创建position_level元素

2、创建position_level的文本

3、把文本添加到position_level

4、把 position_level 添加到 索引为1的 person 下面

5、回写 xml

// --------------------------------------------------------------------------// 5、为person新增一个标签:职级等级(position_level),他的内容是:三级// 创建position_level元素ElementpLevel=document.createElement( "position_level" );
// 创建position_level的文本TextpLevelText=document.createTextNode( "三级" );
// 把文本添加到position_levelpLevel.appendChild(pLevelText);
// 把 position_level 添加到 索引为1的 person 下面personEle.appendChild(pLevel);
// 回写 xmlTransformerFactorytransformerFactory=TransformerFactory.newInstance();
Transformertransformer=transformerFactory.newTransformer();
transformer.transform(newDOMSource(document), newStreamResult(xmlPath));
// --------------------------------------------------------------------------

执行完成代码之后,我们查看下原来的persons.xml,可以看到我们增加的标签position_level已经增加进来。

image.png

也可以看出来,我们新增的节点并没有美化展示到xml中,而且还给我们增加了一个属性standalone="no"


2.6 修改节点

「步骤」

1、得到age元素

2、修改age值,设置到age元素上

3、回写xml,使之生效

// --------------------------------------------------------------------------// 6、修改第一个人的年龄为28System.out.println("----------------------------------------------------------------------");
// 得到ageNodeageNode=document.getElementsByTagName("age").item(0);
System.out.println("原始年龄:"+ageNode.getTextContent());
// 修改age值ageNode.setTextContent("28");
System.out.println("修改后的年龄:"+ageNode.getTextContent());
// 回写xmlTransformerFactorytransformerFactory=TransformerFactory.newInstance();
Transformertransformer=transformerFactory.newTransformer();
transformer.transform(newDOMSource(document), newStreamResult(xmlPath));
// --------------------------------------------------------------------------

执行完成代码之后,我们查看下原来的persons.xml

原始年龄:18修改后的年龄:28

image.png

可以看到我们增加的标签age已经增加进来。


2.7 删除节点

删除刚才的新增的position_level节点。


「步骤」

1、获取position_level节点元素

2、得到position_level父节点

3、使用父节点删除当前节点操作

4、回写xml,使之生效


// 7、删除position_level节点System.out.println("----------------------------------------------------------------------");
// 获取position_level节点元素NodepLevel=document.getElementsByTagName("position_level").item(0);
// 得到position_level父节点NodepLevelParentNode=pLevel.getParentNode();
// 使用父节点删除当前节点操作pLevelParentNode.removeChild(pLevel);
// 回写xmlTransformerFactorytransformerFactory=TransformerFactory.newInstance();
Transformertransformer=transformerFactory.newTransformer();
transformer.transform(newDOMSource(document), newStreamResult(xmlPath));

执行完成代码之后,我们查看下原来的persons.xml已经没有position_level这个节点元素了。

image.png


3 DOM技术

在DOM中,主要适用的是元素和节点以及属性。

针对元素有如下方法:

image.png

针对节点有如下方法:

image.png

DocumentBuilder API

image.png

DocumentBuilderFactory API

image.png

w3c标准

image.png


相关文章
|
15天前
|
监控 Cloud Native Java
Quarkus 云原生Java框架技术详解与实践指南
本文档全面介绍 Quarkus 框架的核心概念、架构特性和实践应用。作为新一代的云原生 Java 框架,Quarkus 旨在为 OpenJDK HotSpot 和 GraalVM 量身定制,显著提升 Java 在容器化环境中的运行效率。本文将深入探讨其响应式编程模型、原生编译能力、扩展机制以及与微服务架构的深度集成,帮助开发者构建高效、轻量的云原生应用。
108 44
|
9天前
|
安全 Java API
Java Web 在线商城项目最新技术实操指南帮助开发者高效完成商城项目开发
本项目基于Spring Boot 3.2与Vue 3构建现代化在线商城,涵盖技术选型、核心功能实现、安全控制与容器化部署,助开发者掌握最新Java Web全栈开发实践。
88 1
|
30天前
|
安全 Java 编译器
new出来的对象,不一定在堆上?聊聊Java虚拟机的优化技术:逃逸分析
逃逸分析是一种静态程序分析技术,用于判断对象的可见性与生命周期。它帮助即时编译器优化内存使用、降低同步开销。根据对象是否逃逸出方法或线程,分析结果分为未逃逸、方法逃逸和线程逃逸三种。基于分析结果,编译器可进行同步锁消除、标量替换和栈上分配等优化,从而提升程序性能。尽管逃逸分析计算复杂度较高,但其在热点代码中的应用为Java虚拟机带来了显著的优化效果。
50 4
|
1月前
|
Java API Maven
2025 Java 零基础到实战最新技术实操全攻略与学习指南
本教程涵盖Java从零基础到实战的全流程,基于2025年最新技术栈,包括JDK 21、IntelliJ IDEA 2025.1、Spring Boot 3.x、Maven 4及Docker容器化部署,帮助开发者快速掌握现代Java开发技能。
358 1
|
29天前
|
Java 测试技术 API
2025 年 Java 开发者必知的最新技术实操指南全览
本指南涵盖Java 21+核心实操,详解虚拟线程、Spring Boot 3.3+GraalVM、Jakarta EE 10+MicroProfile 6微服务开发,并提供现代Java开发最佳实践,助力开发者高效构建高性能应用。
261 4
|
9天前
|
安全 Cloud Native Java
Java 模块化系统(JPMS)技术详解与实践指南
本文档全面介绍 Java 平台模块系统(JPMS)的核心概念、架构设计和实践应用。作为 Java 9 引入的最重要特性之一,JPMS 为 Java 应用程序提供了强大的模块化支持,解决了长期存在的 JAR 地狱问题,并改善了应用的安全性和可维护性。本文将深入探讨模块声明、模块路径、访问控制、服务绑定等核心机制,帮助开发者构建更加健壮和可维护的 Java 应用。
71 0
|
1月前
|
JavaScript 安全 前端开发
Java开发:最新技术驱动的病人挂号系统实操指南与全流程操作技巧汇总
本文介绍基于Spring Boot 3.x、Vue 3等最新技术构建现代化病人挂号系统,涵盖技术选型、核心功能实现与部署方案,助力开发者快速搭建高效、安全的医疗挂号平台。
131 3
|
11月前
|
JavaScript
DOM 节点列表长度(Node List Length)
DOM 节点列表长度(Node List Length)
|
11月前
|
JavaScript
HTML DOM 节点树
HTML DOM 节点是指在 HTML 文档对象模型中,文档中的所有内容都被视为节点。整个文档是一个文档节点,每个 HTML 元素是元素节点,元素内的文本是文本节点,属性是属性节点,注释是注释节点。DOM 将文档表示为节点树,节点之间有父子和同胞关系。
|
11月前
|
JavaScript
HTML DOM 节点
HTML DOM(文档对象模型)将HTML文档视为节点树,其中每个部分都是节点:文档本身是文档节点,HTML元素是元素节点,元素内的文本是文本节点,属性是属性节点,注释是注释节点。节点间存在父子及同胞关系,形成层次结构。