Java Web学习笔记之XML解析(一)

什么是XML解析

所谓的XML解析就是通过java程序对XML文档进行操作。

XML解析方式

  • DOM解析
  • SAX 解析
  • JDOM解析
  • DOM4J解析

    p.s.本人的XML解析系列文章只介绍DOM解析、SAX 解析和DOM4J解析

XML解析开发包

  • XML解析开发包:JAXP、Dom4j、JDOM
  • JAXP:全称 Java API for XML Processing,即解析XML文档的Java API。
    由 javax.xml ; org.w3c.dom ; org.xml.sax 包及其子包组成。在java.xml.parsers包中,定义了几个工厂类,程序员调用这些工厂类,可以得到XML文件的DOM解析器SAX解析器,从而实现对XML文档的解析。
  • Dom4j:由早期开发JDOM的人分离出来而后独立开发的,与JDOM不同的是,DOM4J使用抽象基类接口

DOM解析

将XML文档全部加载到内存中,整个XML文档变成Document对象标签变成Element对象文本变成Text对象属性变成Attribute对象,根据XML标签间的关系,对应建立对象间的关系,构造出一棵DOM树

  • 优点:增删改查容易
  • 缺点:内存消耗大

DOM解析步骤

  1. 创建解析工厂
  2. 得到DOM解析器
  3. 解析XML文档,得到代表文档的document对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("xml文件的路径");

获得了代表XML文档的document之后,就可以对XML进行增删改查(CRUD)了。
p.s. 1.注意不要导错Document的包:org.w3c.dom.Document;2.上述代码会有编译时异常,这里我们在方法名后面直接 throws Exception就可以;

获得指定标签中的内容

为了方便理解,在这里给出一份XML文档,路径是”src/book.xml”

<?xml version="1.0" encoding="UTF-8"?>
<书架>
    <>
        <书名>Java Web高级编程</书名>
        <作者 国籍="美国">Nicholas S.Williams</作者>
        <译者>王肖峰</译者>
        <出版社>清华大学出版社</出版社>
        <售价>¥99.80</售价> 
    </>
    <>
        <书名>Java编程思想</书名>
        <作者 国籍="美国">Bruce Eckel</作者>
        <译者>陈昊鹏</译者>
        <出版社>机械工业出版社</出版社>
        <售价>¥108.00</售价>    
    </>
</书架>

p.s.注意使用中文时的编码问题

这里我们想得到第二本书<书名>标签中的值,即Java编程思想:

//根据标签名获得节点集合
NodeList bookNameList = document.getElementsByTagName("书名");
//根据下标获得第二个节点
Node bookNameNode = bookNameList.item(1);
//获取标签间的内容,即Java编程思想
String bookName = bookNameNode.getTextContent();
//控制台输出检验一下是不是我们想得到的那本书的书名
System.out.println(bookName);

运行结果:
查询书名
p.s. 不要导错Node的包:org.w3c.dom.Node;

获得指定标签的属性值

在XML文档中,有许多标签是包含属性的,例如上述XML文档中的<作者>标签就含有国籍这一条属性,现在我们要获取作者名为Bruce Eckel的国籍

//获得第二个名为作者的标签,转换为Element对象
Element author = (Element) document.getElementsByTagName("作者").item(1);
//根据属性的名字获取属性的值
String nationality = author.getAttribute("国籍");
//控制台输出检验
System.out.println(nationality);

运行结果:
查询属性
p.s.1.想获得属性值时,Node对象没有这样的方法,在我们明知Node对象是标签时,可以将Node替换成Element类型;2.注意不要导错Element的包:org.w3c.dom.Element。

扫描二维码关注公众号,回复: 2872055 查看本文章

添加新标签

在第二本书中添加<页数>标签,值为880

//创建页数标签
Element number = document.createElement("页数");
//设置标签中的值
number.setTextContent("880");
//将新标签添加到第二本书中,先获得第二本书的Node对象
Node book = document.getElementsByTagName("书").item(1);
//添加新标签
book.appendChild(number);

运行后我们发现book.xml文档中并没有新增加的节点,这是因为我们新增的节点只是添加到了内存中的document对象里,实际上并没有改动我们的XML文档,因此我们应该将改动后的document对象写回book.xml文档中。
javax.xml.transform包中有Transformer类transform方法

transform(Source xmlSource,Result outputTarget);

对于这个方法我个人是这样理解的:将Source类型的对象传输到Result类型的对象中。那么,在使用transform方法时,Source类型的参数就是在内存中的新增标签的document对象;另一个Result类型的参数就应该是要写入的book.xml这个文档
在java中,Source和Result是接口,Sun公司自己写好了几个接口的实现类,我们直接使用实现类就可以。对于Source接口,调用DOMSource这个类,使用它的有参构造方法DOMSource(Node n);document对象作为参数传进去即可;对于Result接口,调用StreamResult这个类,使用它的有参构造方法StreamResult(OutputStream outputstream);这个方法需要的参数是输出流,我们就将book.xml文档以文件流的形式传进去new FileOutputStream("src/book.xml");

//创建Transformer工厂
TransformerFactory tffactory = TransformerFactory.newInstance();
//获得Transformer类的实例,即转换器
Transformer tf = tffactory.newTransformer();
//获得第一个参数
DOMSource source = new DOMSource(document);
//获得第二个参数
StreamResult result = new StreamResult(new FileOutputStream("src/book.xml"));
//将document写回xml文件
tf.transform(source, result);

再次运行后,查看book.xml文件:
新增节点

从运行结果我们发现,在没有指定插入位置的时候,新节点是直接插入到末尾的。下面,在第一本书的<出版社>节点前面添加<字数>节点,值为1389
这里用到的方法是insertBefore(Node newChild,Node refChild);从参数名上很容易看出来两个参数的意义:第一个参数是新添加的节点,第二个是在哪个节点前面插入,参数就是哪个节点。

//创建字数标签
Element count = document.createElement("字数");
//设置标签值为1389
count.setTextContent("1389");
//获取出版社节点
Node publish = document.getElementsByTagName("出版社").item(0);
//获取第一个书的节点
Node book = document.getElementsByTagName("书").item(0);
//在出版社节点前插入字数节点
book.insertBefore(count, publish);

运行结果:
新增字数节点
p.s.不要忘记将document写回book.xml文档,方法同上。

为标签添加新属性

类似的添加操作例如在某个节点上添加属性,就是调用setAttribute(String name,String value);方法即可,第一个参数是属性的名字,第二个参数是属性的
为新增的<字数>标签添加单位属性,值为千字

//获取字数节点,转换成Element类型
Element count = (Element) document.getElementsByTagName("字数").item(0);
//添加属性
count.setAttribute("单位","千字");

运行结果:
新增属性

p.s.1.有关属性的操作Node类里没有相应的方法,同上面一样,将Node类型转换为Element类型;2.不要忘记将document写回book.xml文档,方法同上。

删除指定节点

经过上面的添加操作,我们的book.xml文档已经变成了下面的样子(格式化之后):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<书架>
    <>
        <书名>Java Web高级编程</书名>
        <作者 国籍="美国">Nicholas S.Williams</作者>
        <译者>王肖峰</译者>
        <字数 单位="千字">1389</字数>
        <出版社>清华大学出版社</出版社>
        <售价>¥99.80</售价> 
    </>
    <>
        <书名>Java编程思想</书名>
        <作者 国籍="美国">Bruce Eckel</作者>
        <译者>陈昊鹏</译者>
        <出版社>机械工业出版社</出版社>
        <售价>¥108.00</售价>    
        <页数>880</页数>
    </>
</书架>

我们删除第二本书的<售价>标签:
想要删除指定位置的节点,在获得该节点之后还要获得该节点的父节点,父节点调用removeChild(Node oldChild);方法,将要删除的节点当作参数传进去即可:

//获取第二本书的售价节点
Node price = document.getElementsByTagName("售价").item(1);
//获取售价节点的父节点
Node book = price.getParentNode();
//删除节点
book.removeChild(price);

运行结果:
删除节点
p.s.不要忘记将document写回book.xml文档,方法同上。

删除标签的属性

同删除标签类似,删除属性不必获取父节点,在想要删除属性的节点上调用removeAttribute(String name);方法,将要删除的属性名当作参数传进去即可,这里我们删除第一本书中<作者>标签中的国籍属性:

//获取第一本书的作者标签
Element author = (Element) document.getElementsByTagName("作者").item(0);
//删除国籍属性
author.removeAttribute("国籍");

运行结果:
删除国籍属性
p.s.1.有关属性的操作Node类里没有相应的方法,同上面一样,将Node类型转换为Element类型;2.不要忘记将document写回book.xml文档,方法同上。

更新标签中的值

所谓的更新操作,实质上就是将标签中的值重新设置一下,用到的方法是上面写过的setTextContext(String textContent);方法,把更新后的值当作参数传进去即可。更新第一本书的<售价>标签中的值,更新为¥998.00:

//获得第一本书的售价节点
Node price = document.getElementsByTagName("售价").item(0);
//更新节点中的值
price.setTextContent("¥998.00");

运行结果:
更新售价
p.s.不要忘记将document写回book.xml文档,方法同上。

以上便是DOM解析XML文档的几个小例子。


p.s.第一次写文章有哪些不足的地方还请大家谅解;如果有内容上的错误大家可以在评论中指出;也希望大神们可以在评论区给出建议,可以但不限于文章结构、内容、代码质量等方面,交流学习,共同进步;其他的两个解析方式将不定期更新(逃

猜你喜欢

转载自blog.csdn.net/adminhyh/article/details/81811865