第一讲 使用jaxp进行dom解析
一、xml解析方式
dom 文档对象模型 w3c推荐
sax simple api for xml 社区标准,几乎所有解析器都支持
这两种方式的联系与区别:
dom 在解析过程会在内存中建立一个模型,即针对该xml的生成对象树
* 缺点:消耗内存 如果数据过大,产生较大文档消耗内存
* 优点:增删改方便快速 只要得到dom文档,就可以快速删除、定位等
sax 对xml文件从上往下依次读,读取一行处理一行
* 优点:内存消耗小,解析速度快
* 缺点:只适合对文档做读取,不适合做增删改
二、xml解析开发包
Jaxp(sun)<jdom<dom4j (可用度排比)
使用jaxp进行dom解析
* javax.xml.parsers 提供允许处理 XML 文档的类。
* ->(工厂类api) abstract DocumentBuilderFactory 使程序能从xml文档中生成dom对象树的解析器
* abstract DocumentBuilder 定义 API, 使其从 XML 文档获取 DOM 文档实例。使用此类,应用程序员可以从 XML 获取一个 Document。
三、代码说明
以下代码是测试jaxp解析dom的案例
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<page world="all">
<element country="id" street="here">
<a name="zhangsan">
<a1>泰国</a1>
<a2>美国</a2>
</a>
<a age="24">
yingguo
</a>
<b>
<b1>333</b1>
</b>
<c sex="male">333</c>
<d>
<d1>英国</d1>
</d></element>
<element city="num">
<a name="zhangsan">
<a1>泰国</a1>
<a2>222</a2>
</a>
<a age="24">
中国
</a>
<b>
<b1>333</b1>
</b>
<c sex="male">333</c>
<d>
<d1>韩国</d1>
</d></element>
</page>
</pre><pre class="java" name="code">public class demo3 {
/*
* 1、读取xml文档中第二个<a>标签中的内容
* */
@Test
public void read()
{
/*
* 用 jaxp解析dom,解析得到,xml文档的每一个组成部分都会用一个对象表示,如:
* 标签:element 属性:attr 但不管是是什么对象,都是node的子类,所以开发中可以把获取到的任意节点都当作node对待
*
* */
try
{
DocumentBuilderFactory docbuilderfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docbuilder = docbuilderfactory.newDocumentBuilder();
Document doc = docbuilder.parse("src/cn/itcast/xml/dom.xml");
//document已获取,开始调用方法处理,获取数据nodelist
/*getElementsByTagName按 文档顺序返回指定标签内的所有元素(即标签)
* 如果是根标签,则得到所有标签内的内容
*/
NodeList nodelist = doc.getElementsByTagName("a");
Node node = nodelist.item(1); //对指定的标签,查找对应的第几个,这里找到第2个a标签
String content = node.getTextContent(); //然后输出该标签内部的所有元素(即该标签内部所有的子标签)
System.out.println(content);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
//2、如果想得到所有的标签名称,则需要用到递归
@Test
public void read1()throws Exception
{
DocumentBuilderFactory docbuilderfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docbuilder = docbuilderfactory.newDocumentBuilder();
Document doc = docbuilder.parse("src/cn/itcast/xml/dom.xml");
//获得根节点
Node root = doc.getElementsByTagName("page").item(0);
list(root);
}
private void list(Node node)
{
if (node instanceof Element)
{
String nodename = node.getNodeName(); //出现#text,是因为xml里面会把空行等进行解析,无内容但有空行等认为是标签内容;用该判断则可删掉#text
System.out.println(nodename);
}
NodeList list = node.getChildNodes();
for (int i = 0; i < list.getLength(); i++)
{
Node child = list.item(i);
list(child);
}
}
//3、获取标签的属性信息 (先获取跟标签,通过标签获取所有属性,通过item get到所有属性信息)
@Test
public void read3()throws Exception
{
DocumentBuilderFactory docbuilderfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docbuilder = docbuilderfactory.newDocumentBuilder();
Document doc = docbuilder.parse("src/cn/itcast/xml/dom.xml");
//方法一
NodeList elem = doc.getElementsByTagName("element");
Node item = elem.item(0); //指定是第一个element标签
NamedNodeMap map = item.getAttributes(); //获得该标签的所有属性
int len = map.getLength();
System.out.println(len);
System.out.println("是否存在country属性? "+map.getNamedItem("country")); //getNameItem 检索属性名称,获得该属性信息;第一个element对应属性是country不是city,返回null
for (int i = 0;i < len; i++)
{
Node nodelist = map.item(i);
String name = nodelist.getNodeName();
String value = nodelist.getNodeValue();
System.out.println(name+":"+value);
}
//方法二,强转
Element ele = (Element)doc.getElementsByTagName("element").item(0);
NamedNodeMap map1 = ele.getAttributes();
/*剩下一样*/
}
//4、向xml中添加节点 对标签a添加<a4>意大利</a4>
@Test
public void add()
{
try
{
DocumentBuilderFactory docbuilderfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docbuilder = docbuilderfactory.newDocumentBuilder();
Document doc = docbuilder.parse("src/cn/itcast/xml/dom.xml");
//1、创建新节点(元素),设置节点内容
Element e = doc.createElement("a4");
e.setTextContent("意大利");
//2、把创建的节点挂在指定的标签下面(先获得标签,再在该标签下添加子节点)
Element ee = (Element)doc.getElementsByTagName("a").item(0);
ee.appendChild(e);
//3、内存中存在的xml树更新了,但是xml文件没有更新,要从内存写到xml中
/*javax.xml.transform
* transformer类 可以将代表xml文件的document装换成某种格式进行输出(如转换成html文档)
* 也可以将document对象重新写入一个xml文件中
* transformer类--abstract transform(Source xmlSource, Result outputTarget) 方法 将 XML Source 转换为 Result。
transformer类是抽象类,也没有静态方法获取实例,所以要通过工厂来操作 --TransformerFactory 实例可用于创建 Transformer 和 Templates 对象。
* 这里是要将document转换成source DOMSource
*
* */
TransformerFactory transfactory = TransformerFactory.newInstance(); //获取实例
Transformer tformer = transfactory.newTransformer();
DOMSource dsource = new DOMSource(doc); //Source: 创建带有DOM节点的新输入源,这里的新输入源就是document
StreamResult sresult = new StreamResult(new FileOutputStream("src/cn/itcast/xml/dom.xml")); //Result:StreamResult
tformer.transform(dsource, sresult);
/*
//4、已完成添加,现在验证节点是否添加成功
doc = docbuilder.parse("src/cn/itcast/xml/dom.xml");
Element el = (Element) doc.getElementsByTagName("a3");
String attr = el.getAttribute("a3");
System.out.println("属性值是:"+attr);
*/
}
catch(Exception e)
{
System.out.println("错误是:"+e.getMessage());
}
}
}
<pre class="java" name="code">//5、向xml中指定位置添加属性,如在<a>中添加<a3>德国</a3>,放在a4前
//insertBefore(Node newChild, Node refChild) 在现有子节点refChild前添加新节点
@Test
public void test5() throws Exception
{
//创建工厂
DocumentBuilderFactory docbuilderfactory = DocumentBuilderFactory.newInstance();
//获得解析器
DocumentBuilder docbuilder = docbuilderfactory.newDocumentBuilder();
//解析
Document doc = docbuilder.parse("src/cn/itcast/xml/dom.xml");
//创建新节点
Element e = doc.createElement("a3");
e.setTextContent("德国");
//获得基准节点,这里就是a4
Element refNode = (Element) doc.getElementsByTagName("a4").item(0);
//获得代挂的父节点
Element ee = (Element)doc.getElementsByTagName("a").item(0);
//将新节点挂在父节点下的基准节点上方
ee.insertBefore(e,refNode);
//内存中已修改,现在写回到xml中 transformer
DOMSource dsource = new DOMSource(doc);
StreamResult sresult = new StreamResult(new FileOutputStream("src/cn/itcast/xml/dom.xml"));
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.transform(dsource,sresult);