「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」
特点:事件驱动,从上到下,依次解析,边读取边解析。
优点:不会导致内存溢出。
缺点:不能实现增删改的操作。
解析 XML 技术(dom 和 sax),需要一个解析器。
解析的逻辑同Python中差不多,如果了解其中一种语言,其他语言基本上可以去看下。
在JDK中,可以在rt.jar包中找到解析方法。
「步骤」
1、创建 DOM 解析器的工厂,得到 DOM 解析器对象
2、解析 XML 文档,得到代表整个文档的 Document 对象,将其放在内存中
3、获取根元素集合
4、解析处理
首先创建一个xml,这里创建一个persons.xml,文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<persons>
<person sid="001">
<name>张小帅</name>
<sex>男</sex>
<age>18</age>
</person>
<person sid="002">
<name>刘晓萌</name>
<sex>女</sex>
<age>21</age>
</person>
<person sid="003">
<name>王老四</name>
<sex>男</sex>
<age>38</age>
</person>
</persons>
创建DomParserXmlTest.java,内容如下。
package com.xxx.tooljdk.xml;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* <p> DomParserXmlTest </p>
*/
public class DomParserXmlTest {
public static void main(String[] args) {
String xmlPath = "./tool-jdk8/src/main/java/com/xxx/tooljdk/xml/persons.xml";
try {
// 1、创建 DOM 解析器的工厂,得到 DOM 解析器对象
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
// 2、解析 XML 文档,得到代表整个文档的 Document 对象,将其放在内存中
Document document = builder.parse(xmlPath);
// 3、获取根元素 persons
System.out.println("----------------------------------------------------------------------");
Element root = document.getDocumentElement();
System.out.println("根元素节点名称:" + root.getNodeName());
System.out.println("根元素节点类型(是一个元素:Element = 1):" + root.getNodeType());
System.out.println("----------------------------------------------------------------------");
NodeList personNode = document.getElementsByTagName("person");
System.out.println("person节点数量:" + personNode.getLength());
Node personEle = 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("----------------------------------------------------------------------");
NodeList names = 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、解析
NodeList list = root.getChildNodes();
ArrayList<Map<String, Object>> arr = new ArrayList<>();
for (int i = 0; i < list.getLength(); i++) {
// 遍历所有person节点
Node item = list.item(i);
if (item.getNodeType() == Node.ELEMENT_NODE) {
Map<String, Object> map = new HashMap<>();
NamedNodeMap attributes = item.getAttributes();
// 遍历所有person属性
for (int j = 0; j < attributes.getLength(); j++) {
Node nodePerson = attributes.item(j);
map.put(nodePerson.getNodeName(), nodePerson.getNodeValue());
}
// 遍历所有person节点的内容
NodeList list2 = item.getChildNodes();
for (int j = 0; j < list2.getLength(); j++) {
Node item2 = list2.item(j);
if (item2.getNodeType() == Node.ELEMENT_NODE) {
Node node = 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 (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
执行上面代码获取的结果如下:
------------------------------------------
根元素节点名称: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的源代码来加深理解。
「步骤」
1、创建position_level元素
2、创建position_level的文本
3、把文本添加到position_level
4、把 position_level 添加到 索引为1的 person 下面
5、回写 xml
// --------------------------------------------------------------------------
// 5、为person新增一个标签:职级等级(position_level),他的内容是:三级
// 创建position_level元素
Element pLevel = document.createElement( "position_level" );
// 创建position_level的文本
Text pLevelText = document.createTextNode( "三级" );
// 把文本添加到position_level
pLevel.appendChild(pLevelText);
// 把 position_level 添加到 索引为1的 person 下面
personEle.appendChild(pLevel);
// 回写 xml
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(xmlPath));
// --------------------------------------------------------------------------
执行完成代码之后,我们查看下原来的persons.xml,可以看到我们增加的标签position_level已经增加进来。
也可以看出来,我们新增的节点并没有美化展示到xml中,而且还给我们增加了一个属性standalone="no"。
「步骤」
1、得到age元素
2、修改age值,设置到age元素上
3、回写xml,使之生效
// --------------------------------------------------------------------------
// 6、修改第一个人的年龄为28
System.out.println("----------------------------------------------------------------------");
// 得到age
Node ageNode = document.getElementsByTagName("age").item(0);
System.out.println("原始年龄:" + ageNode.getTextContent());
// 修改age值
ageNode.setTextContent("28");
System.out.println("修改后的年龄:" + ageNode.getTextContent());
// 回写xml
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(xmlPath));
// --------------------------------------------------------------------------
执行完成代码之后,我们查看下原来的persons.xml
原始年龄:18
修改后的年龄:28
可以看到我们增加的标签age已经增加进来。
删除刚才的新增的position_level节点。
「步骤」
1、获取position_level节点元素
2、得到position_level父节点
3、使用父节点删除当前节点操作
4、回写xml,使之生效
// 7、删除position_level节点
System.out.println("----------------------------------------------------------------------");
// 获取position_level节点元素
Node pLevel = document.getElementsByTagName("position_level").item(0);
// 得到position_level父节点
Node pLevelParentNode = pLevel.getParentNode();
// 使用父节点删除当前节点操作
pLevelParentNode.removeChild(pLevel);
// 回写xml
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(xmlPath));
执行完成代码之后,我们查看下原来的persons.xml已经没有position_level这个节点元素了。
在DOM中,主要适用的是元素和节点以及属性。
针对元素有如下方法:
针对节点有如下方法:
DocumentBuilder API
DocumentBuilderFactory API
👏👏👏
好了,今天的分享就到了这里,下次再见!!!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。