Java XML DOM解析(xPath)
(一) XML概念
在电子计算机中,标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种的信息比如文章等。它可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 它非常适合万维网传输,提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。是Internet环境中跨平台的、依赖于内容的技术,也是当今处理分布式结构信息的有效工具。早在1998年,W3C就发布了XML1.0规范,使用它来简化Internet的文档信息传输。
(二)XML作用
1. 描述带关系的数据(常用做软件的配置文件):描述包含于被包含的关系,适用范围非常广泛,比如 tomcat SSH框架全部都使用到了XML
例如配置主机和端口号:
host.xml
<host>
<ip>255.43.12.55</ip>
<port>1521</port>
</host>
2. 作为数据的载体(存储数据,小型的“数据库”)
例如存储信息:
teacher.xml
<teacher>
<name>张三</name>
<email>zhangsan@qq.com</email>
<workage>2</workage>
</teacher>
(三)XML语法
xml文件以xml后缀名结尾。
xml文件需要使用xml解析器去解析。浏览器内置了xml解析器
3.1 标签
语法: <student></student> 开始标签 标签体内容 结束标签
1)<student/> 或 <student></student> 空标签。没有标签体内容
2)xml标签名称区分大小写。
3)xml标签一定要正确配对。
4)xml标签名中间不能使用空格
5)xml标签名不能以数字开头
6)注意: 在一个xml文档中,有且仅有一个根标签
3.2 属性
语法: <Student name="eric">student</Student>
注意:
1)属性值必须以引号包含,不能省略,也不能单双引号混用!
2)一个标签内可以有多个属性,但不能出现重复的属性名!
3.3 转义字符
在xml中内置了一些特殊字符,这些特殊字符不能直接被浏览器原样输出。如果希望把这些特殊字符按照原样输出到浏览器,对这些特殊字符进行转义。转义之后的字符就叫转义字节。
特殊字符 转义字符
< <
> >
" "
& &
空格 &nsbp;
(四) XML的DOM解析:
XML文档除了需要供开发者来阅读、配置相关信息,还需要让程序能够读懂其中包含的信息,这就叫做XML文档的解析。
其中XML文档主要有两种解析方式,DOM解析和SAX解析,这里我们主要讲DOM解析方式,而这种方式也是SSH三大框架的解析XML的方式。
4.1 DOM解析:
DOM解析原理:xml解析器一次性把整个xml文档加载进内存,然后在内存中构建一颗Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到xml文档的内容。
Document对象代表了一个完整的xml文档,通过Document对象,可以得到其下面的其他节点对象,通过各个节点对象来访问xml文档的内容。
其中主要包括:标签节点,属性节点,文本节点和注释节点;并且各类节点也被封装成对应的对象,通过操作不同的对象来访问xml的内容:
树只有一个根标签,树上的分支叫做节点(node)
4.2 Domj4读取xml文件
首先创建xml解析器对象,获取到Document对象:
public static Document getDocument(){ //创建一个XML解析器
SAXReader saxReader = new SAXReader();
try {
//读取Document对象
Document document = null;
document = saxReader.read("./src/xml/User.xml");
return document;
} catch (DocumentException e) {
e.printStackTrace();
}
return null;
}
节点:
Iterator Element.nodeIterator(); //获取当前标签节点下的所有子节点
标签:
Element Document.getRootElement(); //获取xml文档的根标签
Element ELement.element("标签名") //指定名称的第一个子标签
Iterator<Element> Element.elementIterator("标签名");// 指定名称的所有子标签
List<Element> Element.elements(); //获取所有子标签
代码示例:
/**
* 遍历所有的标签节点
* @param document
*/
public static void gerAll(Document document){ //获取XML文档的根标签
Element rootElement = document.getRootElement();
getChildNodes(rootElement);
} /**
* 递归获取传入标签下的所有子节点
* @param element
*/
public static void getChildNodes(Element element){
System.out.println(element.getName());
// 迭代器获取当前节点下的所有子节点
Iterator<Node> it = element.nodeIterator();
while (it.hasNext()){
Node node = it.next();
//1 判断是否是标签
if (node instanceof Element){
//如果仍然是标签节点,那个递归获取子节点
getChildNodes((Element) node);
} }
} /**
* 获取当前标签的指定名称的第一个子标签
* @param element 当前标签
*/
public static Element getElementByName(Element element, String elemName){ //获取当前标签下的指定名称的第一个子标签
Element elem = element.element(elemName);
System.out.println(elem.getName());
return elem;
} /**
* 获取当前标签下指定名称的所有子标签
* @param element 当前标签
* @param elemName 指定的名称
*/
public static Iterator<Element> getElementsByName(Element element, String elemName){ //获取当前标签下的指定名称的所有子标签
Iterator<Element> itElement = element.elementIterator(elemName);
while (itElement.hasNext()){
Element elem = itElement.next();
System.out.println(elem.getName());
}
return itElement;
} /**
* 获取当前标签下所有子标签
* @param element 当前标签
*/
public static List<Element> getElements(Element element){ //获取当前标签下的指定名称的所有子标签
List<Element> elementList = element.elements();
for (Element elem : elementList) {
System.out.println(elem.getName());
} return elementList;
}
属性:
String Element.attributeValue("属性名") //获取指定名称的属性值
Attribute Element.attribute("属性名");//获取指定名称的属性对象
Attribute.getName() //获取属性名称
Attibute.getValue() //获取属性值
List<Attribute> Element.attributes(); //获取所有属性对象
Iterator<Attribute> Element.attibuteIterator(); //获取所有属性对象
代码示例:
/**
* 获取属性信息
*/ /**
* 根据属性名称获取指定的属性 和属性值
* @param element 所在标签节点
* @param attName 属性名
*/
public static void getAttributeByName(Element element,String attName){ //想要获取属性,首先要获取属性所在的标签 即传入的标签 // 直接根据id获取属性值
element.attributeValue(attName); // 获取attribute对象,然后获取name和value值
Attribute attribute = element.attribute(attName);
String str = attribute.getName() + "=" + attribute.getValue();
System.out.println(str);
} public static void getAttributes(Element element){ List<Attribute> attributeList = element.attributes();
for (Attribute attribute : attributeList) {
System.out.println( attribute.getName() + "="+ attribute.getValue() );
} //Iterator<Attribute> itAttribute = element.attributeIterator();
}
文本:
Element.getText(); //获取当前标签的文本
Element.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容
代码示例:
/**
* 获取文本信息
*/ public static String getText(Element element){
//注意:空格和换行也是xml的内容
String text = element.getText();
return text;
}
4.3 Domj4修改xml文件
增加:
DocumentHelper.createDocument() 增加文档
addElement("名称") 增加标签
addAttribute("名称",“值”) 增加属性
代码示例:
/**
* 增加:文档,标签 ,属性
*/
@Test
public void AddNode() throws Exception{ //创建文档
Document doc = DocumentHelper.createDocument();
//增加标签
Element rootElem = doc.addElement("UserList");
Element userElem = rootElem.addElement("User");
userElem.addElement("username");
//增加属性值
userElem.addAttribute("id", "001");
userElem.addAttribute("username", "eric"); writeXml(doc);
}
修改:
Attribute.setValue("值") 修改属性值
Element.addAtribute("同名的属性名","值") 修改同名的属性值
Element.setText("内容") 修改文本内容
代码示例:
/**
* 修改:属性值,文本
* @throws Exception
*/
@Test
public void updateNode() throws Exception{
Document doc = new SAXReader().read(new File("./src/xml/userWrite.xml")); /**
* 方案一: 修改属性值 1.得到标签对象 2.得到属性对象 3.修改属性值
*/
//1.1 得到标签对象
/*
Element userElem = doc.getRootElement().element("User");
//1.2 得到属性值
Attribute idAttr = userElem.attribute("id");
//1.3 修改属性值
idAttr.setValue("003");
*/
/**
* 方案二: 修改属性值
*/
//1.1 得到标签对象
/*
Element userElem = doc.getRootElement().element("User");
//1.2 通过增加同名属性的方法,修改属性值
userElem.addAttribute("id", "004");
*/ /**
* 修改文本 1.得到标签对象 2.修改文本
*/
Element nameElem = doc.getRootElement().element("User").element("username");
nameElem.setText("王五"); //把修改后的Document对象写出到xml文档中
writeXml(doc);
}
删除
Element.detach(); 删除标签
Attribute.detach(); 删除属性
代码示例:
/**
* 删除:标签,属性
* @throws Exception
*/
@Test
public void deleteNode() throws Exception{
Document doc = new SAXReader().read(new File("./src/xml/userWrite.xml")); /**
* 1.删除标签 1.1 得到标签对象 1.2 删除标签对象
*/
// 1.1 得到标签对象
/*
Element ageElem = doc.getRootElement().element("User").element("age");
//1.2 删除标签对象
ageElem.detach();
//ageElem.getParent().remove(ageElem);
*/
/**
* 2.删除属性 2.1得到属性对象 2.2 删除属性
*/
//2.1 得到属性对象
//到第二个user标签
Element userElem = (Element)doc.getRootElement().
elements().get(0);
//2.2 得到属性对象
Attribute idAttr = userElem.attribute("id");
//2.3 删除属性
idAttr.detach();
//idAttr.getParent().remove(idAttr); writeXml(doc);
}
写出内容到xml文档
XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)
wirter.write(Document);
代码示例:
/**
* 把修改后的Document对象写出到xml文档中
* @param document
* @throws IOException
*/
public void writeXml(Document document) throws IOException {
//把修改后的Document对象写出到xml文档中
FileOutputStream out = new FileOutputStream("./src/xml/userWrite.xml");
//比较美观的排版方式 用于人阅读
OutputFormat format = OutputFormat.createPrettyPrint(); //紧凑型的排版方式 ,主要用于程序运行中使用 减少不必要的空格换行等
//OutputFormat format2 = OutputFormat.createCompactFormat(); format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(out,format);
writer.write(document);
writer.close(); }
其中使用的到xml文件:
<?xml version="1.0" encoding="utf-8"?> <UserList>
<User id="001">
<username>张三</username>
<passwprd>33333</passwprd>
<age>33</age>
<address>aaaaaaaa</address>
</User> <User id="002">
<username>李四</username>
<passwprd>44444</passwprd>
<age>44</age>
<address>bbbbbbbbb</address>
</User>
<abc></abc> </UserList>
(五)xPath技术
5.1 引入
问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦!
5.2 xPath作用
主要是用于快速获取所需的节点对象。
5.3 在dom4j中如何使用xPath技术
1)导入xPath支持jar包 。 jaxen-1.1-beta-6.jar
2)使用xpath方法 :这里使用的是多态技术,因为不管是标签还是属性或者文本类型的对象都是节点对象
List<Node> selectNodes("xpath表达式"); 查询多个节点对象
Node selectSingleNode("xpath表达式"); 查询一个节点对象
5.4 xPath语法
/ | 绝对路径 | 表示从xml的根位置开始或子元素(一个层次结构) |
// | 相对路径 | 表示不分任何层次结构的选择元素。 |
* | 通配符 | 表示匹配所有元素 |
[] | 条件 | 表示选择什么条件下的元素 |
@ | 属性 | 表示选择属性节点 |
and | 关系 | 表示条件的与关系(等价于&&) |
text() | 文本 | 表示选择文本内容 |
语法示例:
/AAA |
选择根元素AAA |
|
/AAA/CCC |
选择AAA的所有CCC子元素 |
|
/AAA/DDD/BBB |
选择AAA的子元素DDD的所有子元素 |
|
如果路径以双斜线 // 开头, 则表示选择文档中所有满足双斜线//之后规则的元素(无论层级关系)
//BBB |
选择所有BBB元素 |
|
//DDD/BBB |
选择所有父元素是DDD的BBB元素 |
|
星号 * 表示选择所有由星号之前的路径所定位的元素
/AAA/CCC/DDD/* |
选择所有路径依附于/AAA/CCC/DDD的元素 |
|
/*/*/*/BBB |
选择所有的有3个祖先元素的BBB元素 |
|
方块号里的表达式可以进一步的指定元素, 其中数字表示元素在选择集里的位置, 而last()函数则表示选择集中的最后一个元素.
/AAA/BBB[1] |
选择AAA的第一个BBB子元素 |
|
/AAA/BBB[last()] |
选择AAA的最后一个BBB子元素 |
|
属性通过前缀 @ 来指定
//@id |
选择所有的id属性 |
|
//BBB[@id] |
选择有id属性的BBB元素 |
|
//BBB[@name] |
选择有name属性的BBB元素 |
|
//BBB[@*] |
选择有任意属性的BBB元素 |
|
属性的值可以被用来作为选择的准则, normalize-space函数删除了前部和尾部的空格, 并且把连续的空格串替换为一个单一的空格
//BBB[@id='b1'] |
选择含有属性id且其值为'b1'的BBB元素 |
|
count()函数可以计数所选元素的个数
//*[count(BBB)=2] |
选择含有2个BBB子元素的元素 |
|
本文所涉及到的代码:https://git.oschina.net/infaraway/basisJava/tree/master/src/xml
Java XML DOM解析(xPath)的更多相关文章
- Java XML Dom解析工具
Java XML Dom解析工具 缩进等 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); ...
- Java XML文件解析
四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例) 蓝色字体内容由上一篇博文中补充进来的,写作风格比较好,大家有兴趣可以去查看原文 众所周知,现在解析XML的方法越来越多,但主流的方法也就四 ...
- XML与web开发-01- 在页面显示和 XML DOM 解析
前言: 关于 xml 特点和基础知识,可以菜鸟教程进行学习:http://www.runoob.com/xml/xml-tutorial.html 本系列笔记,主要介绍 xml 在 web 开发时需要 ...
- python 解析XML python模块xml.dom解析xml实例代码
分享下python中使用模块xml.dom解析xml文件的实例代码,学习下python解析xml文件的方法. 原文转自:http://www.jbxue.com/article/16587.html ...
- JAVA与DOM解析器提高(DOM/SAX/JDOM/DOM4j/XPath) 学习笔记二
要求 必备知识 JAVA基础知识.XML基础知识. 开发环境 MyEclipse10 资料下载 源码下载 sax.dom是两种对xml文档进行解析的方法(没有具体实现,只是接口),所以只有它们是无 ...
- Java中Dom解析XML
DOM将整个XML文件加载到内存中,并构建出节点树:应用程序可以通过遍历节点树的方式来解析XML文件中的各个节点.属性等信息:这种方式便于对XML节点的添加修改等,而且解析也很方便,然后它比较耗费内存 ...
- JavaEE XML DOM解析之DOM4J
DOM解析之DOM4J @author ixenos DOM4J常用API 读取xml文档: Document doc = new SAXReader().read("xml文件" ...
- 浅谈 Java Xml 底层解析方式
XML 使用DTD(document type definition)文档类型来标记数据和定义数据,格式统一且跨平台和语言,已成为业界公认的标准. 目前 XML 描述数据龙头老大的地位渐渐受到 Jso ...
- JAVA与DOM解析器基础 学习笔记
要求 必备知识 JAVA基础知识.XML基础知识. 开发环境 MyEclipse10 资料下载 源码下载 文件对象模型(Document Object Model,简称DOM),是W3C组织推荐的 ...
随机推荐
- spring mvc 与 jasper Report集成
http://blog.csdn.net/jia20003/article/details/8471169 注意其中的图片地址说明: 如果有子报表,也会到class文件夹中去寻找: 如果子报表有路径的 ...
- EM算法 大白话讲解
假设有一堆数据点,它是由两个线性模型产生的.公式如下: 模型参数为a,b,n:a为线性权值或斜率,b为常数偏置量,n为误差或者噪声. 一方面,假如我们被告知这两个模型的参数,则我们可以计算出损失. 对 ...
- leetcode刷题总结
题外话 今年大三,现正值寒假时间,开学就开始大三下学期的生活了. 在大三临近结束的时间,也就是复习考试的时间里,我每天都会用早上的时间来刷codewars.刚开始玩的时候,一到8kyu的题目如果稍微难 ...
- UTF编码检测
最近工作上正好需要进行UTF编码检测,自己写了一个,分享给大家,希望可以帮得上有需要用的朋友 public bool isUtf8(byte[] rawText) { bool result = tr ...
- [CSS3] 学习笔记-CSS3盒子样式
1.盒子的类型 在CSS3中,使用display来定义盒子的类型,包括block,inline,inline-block类型.div元素和P元素,属于block类型,span元素和a元素,属于inli ...
- 第七届蓝桥杯javaB组真题解析-煤球数目(第一题)
题目 /* 煤球数目 有一堆煤球,堆成三角棱锥形.具体: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形), .... 如果一共有100层,共有 ...
- 蓝桥网试题 java 基础练习 特殊的数字
-------------------------------------------------------- 笑脸 :-) ------------------------------------ ...
- Codeforces 708A Letters Cyclic Shift
A. Letters Cyclic Shift time limit per test:1 second memory limit per test:256 megabytes input:stand ...
- TypeScript入门 2--代码调试
代码调试(debug)是日常开发中必不可少的手段之一,无法进行代码调试会让我们痛苦不已,本文主要介绍如何调试TypeScript代码 很多刚接触TypeScript的人或许有疑问,我们编写的TypeS ...
- DllRegisterServer的调用失败的问题解决方法
1'按键盘上的win+x键调出常用命令. 2'选择“命令提示符(管理员)“ 3'在”命令提示符“中输入”regsvr32 c:\Windows\SysWOW64\comdlg32.ocx“或其他ocx ...