黑马程序员技术交流社区

标题: xml之DOM解析 [打印本页]

作者: 邵天强    时间: 2012-12-17 23:40
标题: xml之DOM解析
1xml解析方式
  Xml解析方式分为两种:domsax
Dom:Document Object Model,即文档对象模型)是w3c组织推荐的处理xml的一种方式Sax:(Simple API for XML)不是官方标准,但是它是XML社区事实上的标准
2xml解析器
Crimson XercesAelfred2
3xml解析开发包
JaxpJdomdom4j
3.1Jaxp
  Jaxp开发包时J2SE的一部分,它由javax.xmlorg.w3c.domorg.xml.sax包及其子包组成。在javax.xml.parsers包中,定义了几个工厂类,程序员调用这些工厂类,可以得到对xml文档进行解析的DOMSAX的解析器对象。
Java.xml.parses包中的DocumentBuilderFactory用于创建DOM模式的解析器对象。DocumentBuilderFactory是一个抽象工厂类,他不能直接实例化,但该类提供了一个newInstance方法,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。要想解析xml,必须获取解析器,解析器一般用工厂生成。
步骤:
1)调用DocumentBuilderFactory.newInstance()方法得到创建DOM解析器的工厂。2)调用工厂对象的newDocumentBuilder方法得到DOM解析器对象3)调用DOM解析器对象的parse()方法解析xml文档,得到代表整个文档的Document对象,进行可以利用DOM特性对整个XML文档进行操作。
例如:获取Document对象
package com.itheima.xml;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.w3c.dom.Document;public class XMLDemo1 {public static void main(String[] args) throws Exception{//获取DocumentBuilderFactory工厂DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();//获取解析器DocumentBuilder builder=factory.newDocumentBuilder();//获取Document文档Document document=builder.parse("src/1.xml");System.out.println(document);}}
3.2、DOM模型
  DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)
  在DOM中,节点之间关系如下:
1)位于一个节点之上的节点是该节点的父节点(parent2)一个节点之下的节点是该节点的子节点(children3)同层次,具有相同父节点的节点是兄弟节点(sibling4)一个机诶单的下一个层次的节点的集合是节点的后代(descendant5)父、祖父节点及所有位于节点上面的,都是节点的祖先(ancestor
节点类型
  Node对象提供了一系列常量来代表节点的类型。当开发人员获得某个Node类型后,就可以把Node节点转换成相应的节点对象(Node的子类对象),以便于调用其特有的方法。


作者: 邵天强    时间: 2012-12-17 23:41
本帖最后由 邵天强 于 2012-12-17 23:42 编辑

应用一:获取所有的节点
public static void list(Node node){
//打印节点的名称
System.out.println(node.getNodeName());
//得到所有的节点
NodeList nl=node.getChildNodes();
for(int i=0;i<nl.getLength();i++){
//获取每一个子节点节点
Node childNode=nl.item(i);
//递归
list(childNode);
}
}
}
上面的方法是利用递归的方法进行获取所有的节点的。
Node是一个接口,xml文档中的所有元素就是一个Node,它有很多子接口
Attr, CDATASection, CharacterData, Comment, Document, DocumentFragment, DocumentType, Element, Entity, EntityReference, Notation, ProcessingInstruction, Text
例如:Attr是为xml中的属性节点的,Element是为标签节点的,Entity是为实体节点的,Text是为文本节点的等等。所以当Node不能满足我们的需求时,我们可以将Node强行转成它的子接口。
Node中的一些常用的方法
方法名
返回类型
描述
appendChild(Node newChild)
Node
添加一个新节点
getChildNodes()
NodeList
获取此节点的所有子节点
getFirstChild()
Node
获取此节点的第一个子节点
getLastChild()
Node
获取此节点的最后一个节点
getNextSibling()
Node
获取此节点之后的节点
getNodeName
String
获取此节点的名称
getNodeValue()
String
获取此节点的值
getParentNode()
Node
获取此节点的父节点
getPreviousSibling()
Node
获取此节点之前的节点
getTestContent()
String
此属性返回此节点及其后代的文本内容
hasAttributes()
Boolean
判断此节点是否有属性
hasChildNodes()
Boolean
判断此节点是否有子节点
RemoveChild(Node oldChild)
Node
移除指定的节点
replaceChild(newNode,oldNode)
Node
用新的节点代替旧的节点
setNodeValue(String nodeValue)
Void
设置此节点的值
setTextContent(String text)
void
此属性返回此节点及其后代的文本内容
应用二:获取指定节点的值
package com.itheima.xml1;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public class XmlDemo1 {
private static Document document;
    @Before//在测试前运行
public void before(){
//创建一个解析器工厂
     DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
     //用工厂创建一个解析器
     try {
DocumentBuilder builder=factory.newDocumentBuilder();
//创建一个文档
document=builder.parse("src/book.xml");
} catch (Exception e) {
e.printStackTrace();
}   
}
    //<书名>javaweb开发</书名>
   @Test
   public void test1(){
  //获取Document
   Document document=this.document;
   //获取书名的标签元素
   Node bookNameNode=document.getElementsByTagName("书名").item(0);
   //获取它的值
   String value=bookNameNode.getTextContent();
   System.out.println(value);
   }
}

作者: 邵天强    时间: 2012-12-17 23:44
邵天强 发表于 2012-12-17 23:41
应用一:获取所有的节点上面的方法是利用递归的方法进行获取所有的节点的。Node是一个接口,xml文档中的所 ...

应用三:获取指定节点的属性值
//获取属性的值<售价 type="rmb">19元</售价>
   @Test
   public void test2(){
   Document document=this.document;
   //获取售价的标签
   Node priceNode=document.getElementsByTagName("售价").item(1);
   //因为Node中没有直接获取属性的值的方法,所以找他的子接口,售价为标签所以找Element
   Element priceElement=(Element) priceNode;
   //获取属性
   String typeAttribute=priceElement.getAttribute("type");
   System.out.println(typeAttribute);
   }
  注意:当我们用程序创建一个新的节点并挂在了指定的节点下面,只是存放在了内存中,如果要改变到xml中,我们需要把内存中的数据写到xml中。
更新XML文档
  Java.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换为某种格式后进行输出,例如把xml文件应用样式表后转成一个html文档,利用这个对象,当然也可以把Document对象又重新写入到一个XML文件中。
  Transformer类通过transform方法完成转换操作,该方法接收一个源和一个目的。我们可以通过:
1javax.xml.transform.dom.DOMSource类来关联要转换的document对象
2)用javax.xml.transform.stream.StreamResult对象来表示数据的目的地。
Transformer对象通过TransformerFactory工厂产生。
TransformerFactory
  TransformerFactory类专门用来产生Transformer类的,我们知道工厂一般是单例的,所以我发直接new对象,
//创建一个工厂
   TransformerFactory factory=TransformerFactory.newInstance();
Transformer
  此类为抽象类,作用就是将源树转换为结果树。
Transformer factory=tff.newTransformer();
Transformer类中的transform方法
transform(Source xmlSource, Result outputTarget)
将XMLSource转化成Result,就是将源树转成结果树。
Source接口
实现此接口的对象包含充当源输入(XML源或转换指令)所需的信息
它的实现类如下:
DOMSource:构造函数DOMSource(Node n)
StreamSource:流源
Result接口
实现此接口的对象包含构建转换结果数所需的信息。实现类:
DOMResult:用文档作为结果树
StreamResult:用流作为输出结果树
上面的SourceResult简单的理解就是,Source:源写到Result:目的上面。
应用四:向xml中添加节点
@Test
   public void test3(){
   //首先获取第一本书的节点
   Node bookNode=document.getElementsByTagName("书").item(0);
   //创建一个新的售价节点
   Node newPriceNode=document.createElement("售价");
   //向新的售价节点添加文本值
   newPriceNode.setTextContent("59元");
   //然后把新的节点挂到书上面
   bookNode.appendChild(newPriceNode);
   //上面的是写到了内存中,要想把内存中的数据写到xml中
   //创建一个工厂
   TransformerFactory tff=TransformerFactory.newInstance();
   //创建一个输出的
   try {
Transformer former=tff.newTransformer();
former.transform(new DOMSource(document),
                                       new StreamResult(new File("src/book.xml")));
} catch (Exception e) {
e.printStackTrace();
}   
  }
应用五:删除节点
//删除节点<作者 id="12">张孝祥</作者>
   @Test
   public void test4(){
   //首先获取这个节点
   Node authorNode=document.getElementsByTagName("作者").item(0);
   //因为自己不能删除自己,只能他的父节点删除它所以要得到她的父节点
   Node parentNode=authorNode.getParentNode();
   //调用Node中的方法删除之
   parentNode.removeChild(authorNode);
   //上面的是在内存中删除的,需要把它写到xml文档中去
   //创建一个输入输入工厂
   TransformerFactory factory=TransformerFactory.newInstance();
   try { //获取Transformer对象
Transformer former=factory.newTransformer();
//从源到目的
former.transform(new DOMSource(document),
                                        new StreamResult(new File("src/book.xml")));
} catch (Exception e) {
e.printStackTrace();
}
   }


作者: 邵天强    时间: 2012-12-17 23:45
邵天强 发表于 2012-12-17 23:44
应用三:获取指定节点的属性值  注意:当我们用程序创建一个新的节点并挂在了指定的节点下面,只是存放在 ...

应用六:更新节点
//更新节点<书名>JavaScript网页开发</书名>
   @Test
   public void test5(){
   //首先获取第二本书的书名节点
   Node bookNameNode=document.getElementsByTagName("书名").item(1);
   //更新节点的值
   bookNameNode.setTextContent("Strus2教程");
//创建一个输入输入工厂
   TransformerFactory factory=TransformerFactory.newInstance();
   try { //获取Transformer对象
Transformer former=factory.newTransformer();
//从源到目的
former.transform(new DOMSource(document), new StreamResult(new File("src/book.xml")));
} catch (Exception e) {
e.printStackTrace();
}
   }
综上所述,利用DOM解析xml的步骤如下:
步骤一:创建解析器工厂
DocumentBuilderFactoryfactory=
                                 DocumentBuilderFactory.newInstance();
步骤二:用工厂创建解析器(有异常)
DocumentBuilder builder=factory.newDocumentBuilder();
步骤三:用解析器获取文档Document(有异常)
document=builder.parse("src/book.xml");
步骤四:获取节点进行增删改查,不同的节点可能需要不同的子接口去实现
对于增删改而言,上面的步骤只是写到了内存中,要想写到xml文档中,还需如下步骤
步骤五:创建输出工厂
TransformerFactory tff=TransformerFactory.newInstance();
步骤六:创建输出类(有异常)
Transformer former=tff.newTransformer();
步骤七:调用输出类中的transform方法进行输出(有异常):从源到目的
former.transform(new DOMSource(document),
                           new StreamResult(new File("src/book.xml")));





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2