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包中找到解析方法。
「步骤」
1、创建 DOM 解析器的工厂,得到 DOM 解析器对象
2、解析 XML 文档,得到代表整个文档的 Document 对象,将其放在内存中
3、获取根元素集合
4、解析处理
2.2 创建实验xml
首先创建一个xml,这里创建一个persons.xml,文件内容如下:
<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已经增加进来。
也可以看出来,我们新增的节点并没有美化展示到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
可以看到我们增加的标签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这个节点元素了。
3 DOM技术
在DOM中,主要适用的是元素和节点以及属性。
针对元素有如下方法:
针对节点有如下方法:
DocumentBuilder API
DocumentBuilderFactory API
w3c标准