论坛首页 Java企业应用论坛

DOM 与 DOM 解析详解(四)以DOM方式解析XML

浏览 15185 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (2) :: 隐藏帖 (1)
作者 正文
   发表时间:2009-06-02   最后修改:2009-06-02
OO

    以 DOM 方式解析XML文档,示例如下(标有详细注释)

 

package Test_DOM;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Test {
	public static void main(String[] args) throws ParserConfigurationException,
			SAXException, IOException {
		DocumentBuilderFactory builderFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder builder = builderFactory.newDocumentBuilder();
		/*
		 * builder.parse()方法将给定文件的内容解析为一个 XML 文档, 并且返回一个新的 DOM Document对象。
		 */
		Document document = builder.parse(new File("books.xml"));
		//打印document节点
		printNode(document,0);
		
		//获取文档的根元素,赋值给rootElement变量
		Element rootElement = document.getDocumentElement();
		//获取元素的count属性
		int countOfBooks = Integer.parseInt(rootElement.getAttribute("count"));
		System.out.println("There are "+countOfBooks+" books , they are ");
		//获取rootElement的所有子节点(不包括属性节点),返回一个NodeList对象
		NodeList childNodes = rootElement.getChildNodes();
		for(int i = 0;i < childNodes.getLength();i++){
			//获取childNodes的第i个节点
			Node childNode = childNodes.item(i);
			//判断childNode是不是一个元素节点,并且它的 nodeName 值为book
			if(childNode.getNodeType() == Node.ELEMENT_NODE 
					&& childNode.getNodeName().equals("book")){
				//若是,则获取childNode的所有子节点(不包括属性节点),返回一个NodeList对象
				NodeList childNodes_2 = childNode.getChildNodes();
				for(int j = 0;j < childNodes_2.getLength();j++){
					//获取childNodes_2的第j个节点
					Node childNode_2 = childNodes_2.item(j);
					//判断childNode_2是不是一个元素节点,并且它的 nodeName 值为name
					if(childNode_2.getNodeType() == Node.ELEMENT_NODE 
							&& childNode_2.getNodeName().equals("name")){
						//若是,则获取childNode_2的所有子节点(不包括属性节点),返回一个NodeList对象
						NodeList childNodes_3 = childNode_2.getChildNodes();
						for(int k = 0;k < childNodes_3.getLength();k++){
							//获取childNodes_3的第k个节点
							Node childNode_3 = childNodes_3.item(k);
							//判断childNodes_3是不是一个文本节点
							if(childNode_3.getNodeType() == Node.TEXT_NODE){
								//若是,则打印输出这个文本节点的nodeValue
								System.out.println("  <<"+childNode_3.getNodeValue()+">>");
							}
						}
					}
				}
			}
		}
	}
	
	/*
	 * 打印 DOM 节点
	 * 输出格式为:
	 *     nodeType(nodeName,nodeValue)
	 *     	   "ATTRIBUTE"(attributeName=attributeValue)
	 *         ...
	 *         childNodeType[childNodeName,childNodeValue]
	 *         ...
	 */
	public static void printNode(Node node,int count) {
		if (node != null) {
			String tmp = "";
			for(int i = 0 ; i < count ; i++) tmp += "  ";
			//获取node节点的节点类型,赋值给nodeType变量
			int nodeType = node.getNodeType();
			switch (nodeType) {
				case Node.ATTRIBUTE_NODE: tmp += "ATTRIBUTE";break;
				case Node.CDATA_SECTION_NODE: tmp += "CDATA_SECTION";break;
				case Node.COMMENT_NODE:tmp += "COMMENT";break;
				case Node.DOCUMENT_FRAGMENT_NODE:tmp += "DOCUMENT_FRAGMENT";break;
				case Node.DOCUMENT_NODE:tmp += "DOCUMENT";break;
				case Node.DOCUMENT_TYPE_NODE:tmp += "DOCUMENT_TYPE";break;
				case Node.ELEMENT_NODE:tmp += "ELEMENT";break;
				case Node.ENTITY_NODE:tmp += "ENTITY";break;
				case Node.ENTITY_REFERENCE_NODE:tmp += "ENTITY_REFERENCE";break;
				case Node.NOTATION_NODE:tmp += "NOTATION";break;
				case Node.PROCESSING_INSTRUCTION_NODE:tmp += "PROCESSING_INSTRUCTION";break;
				case Node.TEXT_NODE:tmp += "TEXT";break;
				default:return;//invalid node type.
			}
			
			System.out.println(tmp+" ("+node.getNodeName()+","+node.getNodeValue()+")");
			/*
			 * node.getAttributes()方法返回
			 * 包含node节点的属性的 NamedNodeMap(如果它是 Element)
			 */
			NamedNodeMap attrs = node.getAttributes();
			if(attrs != null)
				for(int i = 0 ; i < attrs.getLength() ; i++){
					printNode(attrs.item(i),count+1);
				}
			/*
			 * node.getChildNodes()方法返回
			 * 包含node节点的所有子节点的 NodeList。
			 */
			NodeList childNodes = node.getChildNodes();
			for(int i = 0 ; i < childNodes.getLength() ; i++){
				printNode(childNodes.item(i),count+1);
			}
		}
	}
}

 

books.xml 的内容如下:

 

<?xml version="1.0" encoding="GB2312"?>
<books  count="3"
	xmlns="http://test.org/books">
	<!--books's comment-->
	<book id="1">
		<name>Thinking in JAVA</name>
	</book>
	<book id="2">
		<name>Core JAVA2</name>
	</book>
	<book id="3">
		<name>C++ primer</name>
	</book>
</books>

 

运行结果如下:

DOCUMENT (#document,null)
    ELEMENT (books,null)
        ATTRIBUTE (count,3)
            TEXT (#text,3)
        ATTRIBUTE (xmlns,http://test.org/books)
            TEXT (#text,http://test.org/books)
        TEXT (#text,
    )
        COMMENT (#comment,books's comment)
        TEXT (#text,
    )
        ELEMENT (book,null)
            ATTRIBUTE (id,1)
                TEXT (#text,1)
            TEXT (#text,
        )
            ELEMENT (name,null)
                TEXT (#text,Thinking in JAVA)
            TEXT (#text,
    )
        TEXT (#text,
    )
        ELEMENT (book,null)
            ATTRIBUTE (id,2)
                TEXT (#text,2)
            TEXT (#text,
        )
            ELEMENT (name,null)
                TEXT (#text,Core JAVA2)
            TEXT (#text,
    )
        TEXT (#text,
    )
        ELEMENT (book,null)
            ATTRIBUTE (id,3)
                TEXT (#text,3)
            TEXT (#text,
        )
            ELEMENT (name,null)
                TEXT (#text,C++ primer)
            TEXT (#text,
    )
        TEXT (#text,
)
There are 3 books , they are
    <<Thinking in JAVA>>
    <<Core JAVA2>>
    <<C++ primer>>


 

 

 

 

 

 

 

 

 

 

 

   发表时间:2009-06-02   最后修改:2009-06-02
java的DOM解析实在有点无里头

比如这个
  DocumentBuilderFactory builderFactory = DocumentBuilderFactory   
              .newInstance();   
 DocumentBuilder builder = builderFactory.newDocumentBuilder();   



这些语义不清楚的Factory和builder就是让语句看得更复杂。
0 请登录后投票
   发表时间:2009-06-02  
ray_linn 写道
java的DOM解析实在有点无里头

比如这个
  DocumentBuilderFactory builderFactory = DocumentBuilderFactory   
              .newInstance();   
 DocumentBuilder builder = builderFactory.newDocumentBuilder();   



这些语义不清楚的Factory和builder就是让语句看得更复杂。

呵呵 所以更多的人喜欢用jdom 和 dom4j
但是理解JAVA DOM里的一些概念还是必要的
毕竟它是W3C DOM的JAVA标准实现,
而且大部分开源DOM解析器,都支持与JAVA
标准DOM之间的转换,
至于factory和builder我也觉得敲起来有点
麻烦,但是语义还是比较明确的 就是用工厂类
创建一个文档(Document)构造器,至于为什么
这么麻烦,可能是为了让DOM API更容易扩展。
0 请登录后投票
   发表时间:2009-06-03  
XPathFactory xpathFactory = XPathFactory.newInstance();
		XPath xpath = xpathFactory.newXPath();
		/*
		 * 如果这个XPath表达式会被求值多次最好用下面这种求值方式
		 * 先编译XPath表达式
		 * XPathExpression xpathExpr = xpath.compile("//book/name/text()");
		 * NodeList nodeList = (NodeList)xpathExpr.evaluate(document, XPathConstants.NODESET);
		 */
		NodeList nodeList = (NodeList)xpath.evaluate("//book/name/text()", doc, XPathConstants.NODESET);
		if(nodeList != null){
			for(int i = 0; i < nodeList.getLength();i++){
				System.out.println("  <<"+nodeList.item(i).getNodeValue()+">>");
			}
		}

这段用XPath来查找所有书名的代码比上面的代码简单多了
(实际上用DOM解析xml是最复杂的,有很多途径可以
轻松解析XML,比如用JDOM。。)
输出结果为:
    <<Thinking in JAVA>>
    <<Core JAVA2>>
    <<C++ primer>>
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics