技术: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


相关文章
|
9月前
|
机器学习/深度学习 JSON Java
Java调用Python的5种实用方案:从简单到进阶的全场景解析
在机器学习与大数据融合背景下,Java与Python协同开发成为企业常见需求。本文通过真实案例解析5种主流调用方案,涵盖脚本调用到微服务架构,助力开发者根据业务场景选择最优方案,提升开发效率与系统性能。
2060 0
|
9月前
|
Java
Java的CAS机制深度解析
CAS(Compare-And-Swap)是并发编程中的原子操作,用于实现多线程环境下的无锁数据同步。它通过比较内存值与预期值,决定是否更新值,从而避免锁的使用。CAS广泛应用于Java的原子类和并发包中,如AtomicInteger和ConcurrentHashMap,提升了并发性能。尽管CAS具有高性能、无死锁等优点,但也存在ABA问题、循环开销大及仅支持单变量原子操作等缺点。合理使用CAS,结合实际场景选择同步机制,能有效提升程序性能。
|
9月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
604 100
|
10月前
|
存储 缓存 Java
Java数组全解析:一维、多维与内存模型
本文深入解析Java数组的内存布局与操作技巧,涵盖一维及多维数组的声明、初始化、内存模型,以及数组常见陷阱和性能优化。通过图文结合的方式帮助开发者彻底理解数组本质,并提供Arrays工具类的实用方法与面试高频问题解析,助你掌握数组核心知识,避免常见错误。
|
10月前
|
缓存 安全 Java
Java并发性能优化|读写锁与互斥锁解析
本文深入解析Java中两种核心锁机制——互斥锁与读写锁,通过概念对比、代码示例及性能测试,揭示其适用场景。互斥锁适用于写多或强一致性场景,读写锁则在读多写少时显著提升并发性能。结合锁降级、公平模式等高级特性,助你编写高效稳定的并发程序。
449 0
|
8月前
|
存储 安全 Java
《数据之美》:Java集合框架全景解析
Java集合框架是数据管理的核心工具,涵盖List、Set、Map等体系,提供丰富接口与实现类,支持高效的数据操作与算法处理。
|
9月前
|
Java 开发者
Java 函数式编程全解析:静态方法引用、实例方法引用、特定类型方法引用与构造器引用实战教程
本文介绍Java 8函数式编程中的四种方法引用:静态、实例、特定类型及构造器引用,通过简洁示例演示其用法,帮助开发者提升代码可读性与简洁性。
|
9月前
|
安全 Java API
Java SE 与 Java EE 区别解析及应用场景对比
在Java编程世界中,Java SE(Java Standard Edition)和Java EE(Java Enterprise Edition)是两个重要的平台版本,它们各自有着独特的定位和应用场景。理解它们之间的差异,对于开发者选择合适的技术栈进行项目开发至关重要。
1475 1
|
8月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
10月前
|
安全 Oracle Java
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
691 0
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡

推荐镜像

更多
  • DNS