您的位置:首页 > 编程语言 > Java开发

java解析xml

2015-12-12 11:29 543 查看
最近学习了xml的解析,感觉应该总结一下:

xml在开发中还是非常重要的,主要用来当做配置文件,存储和传输数据用的。所以如何来解析xml就尤为重要。

xml的解析方式有两种:dom和sax。两种方式各有优缺点:

*dom方式解析

根据xml的层级结构在内存中分配一个树形结构,把xml的标签、属性、文本都封装成对象。

缺点:如果文件过大,造成内存溢出

优点:方便实现增删改操作

**sax方式解析

采用事件驱动的方式,边读边解析

- 从上到下,一行一行解析,解析到某个对象,返回对象名称

缺点:不能实现增删改操作

优点:文件过大时,不会造成内存溢出,方便实现查询操作。

java 解析xml:java解析xml的方式称为jaxp。jaxp是javase的一部分。jaxp解析器在jdk的javax.xml.parsers包里面。这里面当然也包含了两种解析方式。

dom解析方式:

先说说jaxp创建dom解析器:

要得到dom解析器还真有点麻烦:先要创建dom解析器工厂,然后根据工厂得到dom解析器,再使用parse方法与xml连接。这样,该对象就代表了所指定的xml文件。

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(PATH);

最后得到的document就代表整个xml文件了。

回写xml:

使用dom可以对xml文件进行增删改查,当然这是在内存中进行操作的,那么如何将修改过的document写回原文件中呢?这时,就需要用到回写xml所需要的类了。

TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer =transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(PATH));


这其中传的参数document就是你得到解析器时的Document对象,PATH为写回的路径。

因为上面两个操作比较固定,所以我把它们封装成了一个工具类:

public class DomUtils {
/*
* 在使用该类时,请先初始化PATH,即先调用setPATH()方法。
* */
private static String PATH = "";
public static void setPATH(String path){
PATH = path;
}
public static String getPATH(){
return PATH;
}
//获取xml的document对象
public static Document getDocument(){
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(PATH);

return document;
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
//根据document回写xml
public static void xmlWriters(Document document){
try{
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer =transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(PATH));
}catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


使用dom解析xml当然少不了对其内容的增删改查:

//使用jaxp添加节点,在school标签下面再添加一个class标签
public static void addNode() throws Exception{
/*
* 1、创建解析器工厂
* 2、创建解析器
* 3、解析xml,得到document
* 4、得到school标签
* 5、创建class标签
* 6、创建文本
* 7、把文本添加到class下
* 8、把class添加到school下
* 9、回写xml
* */
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document= documentBuilder.parse("src\\01.xml");
//4、得到school标签
Node school= document.getElementsByTagName("school").item(0);
//5、创建class标签
Element class1 =document.createElement("class");
//6、创建文本
Text text1=document.createTextNode("shen12");
// 7、把文本添加到class下
class1.appendChild(text1);
//8、吧class添加到school下
school.appendChild(class1);

//回写xml
/*
* 1.创建transformerfactory的对象
* 2、根据transformerfactory的对象创建transformer对象
* 3、使用transformer的transform方法  transform(Source xmlSource, Result outputTarget)
* 		传递两个参数
* 	  		1,DOMSource对象,以 Document Object Model(DOM)树的形式充当转换 Source 树的持有者。
* 			2.streamResult对象,充当转换结果的持有者,可以为 XML、纯文本、HTML 或某些其他格式的标记。
* */
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer=transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src\\01.xml"));

}
}
//删除节点
public static void delNode() throws Exception{
/*
* 删除第三个name标签
*1、创建解析器工厂
*2、创建解析器
*3、解析,得到doucment
*4、得到第三个标签
*5、得到这个标签的父标签
*6、通过父标签删除
*7、回写xml
*
* */
DocumentBuilderFactory documentBuilderFactory= DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
Document document=documentBuilder.parse("src\\01.xml");
NodeList nameList =document.getElementsByTagName("name");
Node nameBy3 =nameList.item(2);
Node namenParent =nameBy3.getParentNode();
namenParent.removeChild(nameBy3);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer=transformerFactory.newTransformer();
transformer.transform(new DOMSource(document),new StreamResult("src\\01.xml"));
<pre name="code" class="java">	//使用jaxp修改节点
public static void setNode() throws Exception{
/*
*修改第二个name的名称为杨泽斌
*1、创建解析器工厂
*2、创建解析器
*3、解析,得到doucment
*4、得到name的list
*5、得到第二的name
*6、修改文本为杨泽斌
*7、回写xml
* */
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder  docmBuilder=documentBuilderFactory.newDocumentBuilder();
Document document=docmBuilder.parse("src\\01.xml");
NodeList nameList =document.getElementsByTagName("name");

Node nameBy2=nameList.item(1);
nameBy2.setTextContent("杨泽斌");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer=transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src\\01.xml"));
}
<pre name="code" class="java">	//遍历xml的所有元素名称,并打印
public static void listNodeName() throws Exception{
/*
*1、创建解析器工厂
*2、创建解析器
*3、解析,得到doucment
*
*4、得到根节点
*5、得到根节点的子节点
*6.。。。。
* */
DocumentBuilderFactory documentBuilderFactory= DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
Document document=documentBuilder.parse("src\\01.xml");
//编写一个方法来实现递归操作
list1(document);

}
private static void list1(Node node) {
//判断nodetype是否为元素,打印(因为xml会解析换行和空格,而这些并不是我们想要的)
if(node.getNodeType()==Node.ELEMENT_NODE){

System.out.println(node.getNodeName());
}
//得到下一层的名称的list
NodeList list =node.getChildNodes();
//得到每一个node
for(int i = 0; i<list.getLength();i++){
Node node1 = list.item(i);
//继续遍历下一层的元素
list1(node1);
}

}

再说说sax解析:

由于sax是基于事件驱动的,遇到事件会自动执行对应方法,所以我们要做的就是改变这些方法的内容,从而使执行后产生不同的效果。

sax是边读边解析,所以:

**当解析到开始标签时候,自动执行startElement方法,该方法中的qName参数就为元素开始标签

**当解析到文本时,自动执行characters方法,该方法的三个参数可转换为String类的构造方法,用此来new String对象

**当解析到结束标签是,自动执行endElement方法,该方法中的qName参数就为元素结束标签

sax只能完成查询操作:

public class saxTest {
public static void main(String[] args) throws Exception{

/*
* 1、创建解析器工厂
* 2、创建解析器
* 3、执行parse方法
* 4、自己创建一个类,继承DefaultHandler
* 5、自己重写其中的三个方法:startElement方法,characters方法,endElement方法
* */
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser =saxParserFactory.newSAXParser();
saxParser.parse("src\\02.xml", new MyDefault2());
}
}

class MyDefault2 extends DefaultHandler{
//获取name标签的值
boolean flag = false;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
//判断qName是否为name标签
if("name".equals(qName)){
flag=true;
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//是Name标签则打印
if(flag){
System.out.println(new String(ch,start,length));
}
}

@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//重置
flag=false;
}
}

class MyDefault1 extends DefaultHandler{

//以整个文档的形式打印
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.print("<"+qName+">");
}

@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
System.out.print(new String(ch,start,length));

}

@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.print("</"+qName+">");
}
}




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  计算机 java dom xml 存储