首页 > 代码库 > jaxp使用笔记
jaxp使用笔记
XML文件的解析技术有DOM和SAX方式,在Android中还有pull解析方式,这里不再讨论
DOM解析的方式和js中的DOM操作是一致的,DOM解析一次将文档加载入内存建立树型模型,但是如果XML文档过大,会出现内存溢出的问题,DOM也有优点:方便进行增删改操作
SAX解析方式是根据事件驱动一行一行进行加载解析的,所以不会出现内存溢出的问题,而且方便查询,但是它有个缺点:不能进行增删改操作
目前XML的解析器有:
- sun开发的jaxp(本次记录的)
- dom4j (最为常用)
- jdom (使用较少)
注意:这里说的是解析器,解析器是根据解析技术开发的工具,解析技术记住DOM和SAX即可
因为jaxp是sun公司开发的,直接存在于JDK中,所以还是有必要学习一下
jaxp进行DOM解析
使用jaxp进行DOM解析可以分为四步:
第一步 创建解析器工厂
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
第二步 根据工厂创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();
第三步 使用解析器解析XML文件,得到Document对象
Document document = builder.parse("XML文件");
第四步 根据jaxp的API对Document对象进行操作
例如 getElementsByTagName(标签名)获得节点集合 NodeList类的getLength()方法获得节点个数
NodeList类的item(int)方法获得某个节点 Node类的getTextContent()方法获得节点的文本值 等等
person.xml文件:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<person> <student> <name>lz</name> <age>21</age> </student> <student> <name>zhanshang</name> <age>21</age> </student></person>
先来看一个简单解析XML文件的例子(从name节点集合中获得每个name节点的文本值):
/** * 使用jaxp的DOM解析方法解析XML * @throws Exception */ @Test public void fun1() throws Exception{ //1.创建工厂 DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); //2.根据工厂创建解析器 DocumentBuilder builder = factory.newDocumentBuilder(); //3.解析XML得到Document对象 Document document = builder.parse("src/person.xml"); //4.根据Document对象得到元素集合 NodeList nodeList = document.getElementsByTagName("name"); //5.遍历节点集合,得到节点的值 使用item()方法根据下标获得节点 for (int i = 0; i < nodeList.getLength(); i++) { String value=nodeList.item(i).getTextContent(); System.out.println(value); } }
注意:其中的Document和NodeList,Node等类都是org.w3c.dom包下的,不要导错
结果输出:
lzzhanshang
添加节点
添加节点使用的是appChild()方法,和js中DOM操作的添加节点方法名是一样的,添加节点操作中第四步需要说明一下:我们需要创建节点(创建元素节点createElement()方法,创建文本节点 createTextNode()方法),然后把节点添加到父节点下,其实逻辑和js中DOM一致,然后我们需要回写到XML文件中,因为我们之前的操作都是在内存中,需要回写到XML文件
/** * 添加节点 * @throws Exception */ @Test public void fun2() throws Exception{ //1.创建解析器工厂 DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); //2.根据工厂创建解析器 DocumentBuilder builder = factory.newDocumentBuilder(); //3.解析XML,得到Document Document document = builder.parse("src/person.xml"); //得到第一个student结点,并添加结点(内存中) Node student = document.getElementsByTagName("student").item(0); Element sex = document.createElement("sex"); Text nan = document.createTextNode("男"); sex.appendChild(nan); student.appendChild(sex); //4.回写数据到XML文件中 TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.transform(new DOMSource(document), new StreamResult("src/person.xml")); }
注意:使用javax.xml.transform包下的Transformer类回写,这个类也是先创建工厂,然后根据工厂创建Transformer类,最后使用这个类的transform()方法
person.xml文件变为:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><person> <student> <name>lz</name> <age>21</age> <sex>男</sex> </student> <student> <name>zhanshang</name> <age>21</age> </student></person>
修改操作
修改文本节点的值使用的是Node类的setTextContent()方法,和getTextContent()方法相对
/** * 修改节点 * @throws Exception */ @Test public void fun3() throws Exception{ DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse("src/person.xml"); Node sex = document.getElementsByTagName("sex").item(0); sex.setTextContent("nan"); //回写XML TransformerFactory transformerFactory=TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.transform(new DOMSource(document), new StreamResult("src/person.xml")); }
person.xml文件变为:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><person> <student> <name>lz</name> <age>21</age> <sex>nan</sex>
</student> <student> <name>zhanshang</name> <age>21</age> </student></person>
删除节点
接下来我们就把sex这个节点给删除吧,使用的方法是Node类的removeChild(),注意:使用1添加和删除都是相对于操作的节点的父节点来说的,所以需要先找到其父节点
/** * 删除节点 * @throws Exception */ @Test public void fun4() throws Exception{ DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse("src/person.xml"); Node student1 = document.getElementsByTagName("student").item(0); Node sex1 = document.getElementsByTagName("sex").item(0); student1.removeChild(sex1); //回写XML TransformerFactory transformerFactory=TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.transform(new DOMSource(document), new StreamResult("src/person.xml")); }
person.xml文件又变回:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><person> <student> <name>lz</name> <age>21</age> </student> <student> <name>zhanshang</name> <age>21</age> </student></person>
注意:DOM的增删改操作都需要在最后回写到XML文件中,不然只是在内存中操作
遍历节点
我是想把所有的元素节点遍历出来,遍历节点使用的是Node类的getChildNodes()方法,但是这个方法遍历只可以遍历一层层级关系,所以需要递归调用
/** * 遍历节点 * @throws Exception */ @Test public void fun5() throws Exception{ DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse("src/person.xml"); list1(document); } private void list1(Node node){ //遍历节点 Node类是Document类的父类 if(node.getNodeType()==Node.ELEMENT_NODE){ //判断是否为元素节点 ELEMEN_NODE静态常量量 还有其他的静态常量表示其他类型的节点 System.out.println(node.getNodeName()); } NodeList nodeList = node.getChildNodes(); for(int i=0;i<nodeList.getLength();i++){ list1(nodeList.item(i)); //递归调用 } }
注意:list1()方法中有一个判断,判断该节点类型是否为元素节点,如果为元素节点才输出,如果不判断遍历之后会把空格,换行都当成文本节点输出,js的DOM操作中也有该问题
结果输出为 :
personstudentnameagestudentnameage
jaxp使用笔记