(四) 使用XPath来定位信息

如果要定位某个XML文档中的一段特定的信息,通过遍历DOM树的众多节点来进行查找显得有些麻烦,XPath语言使得访问树节点变得很容易。
1. 例如,有如下XML文档

 

<configuration>
    ...
    <database>
        <username>dbuser</username>
        <password>secret</password>
    </database>
</configuration>

 

可以通过XPath表达式 /configuration/database/username 求值来得到database中的username的值
下列操作比普通的DOM方式要简单的多:
(1).得到文档节点
(2).枚举它的子元素
(3).定位database元素
(4).获取database元素的第一个子元素,即username元素
(5).获取username元素的第一个子元素,即Text节点
(6).获取Text节点中的数据

2. XPath可以描述XML文档中的一组节点,
例如
    XPath: /gridbag/row
描述了根元素gridbag的子元素中所有的row元素,可以用 [] 操作符来选择特定元素
    /gridbag/row[1]
这表示第一行(索引号从1开始)

3. 使用 @ 操作符可以得到属性值。
    /gridbag/row[1]/cell[1]/@anchor
描述了第一行第一个单元格的anchor属性
    /gridbag/row/cell/@anchor
描述了根元素gridbag下所有子元素row下的所有子元素cell的anchor属性点

4. XPath有很多有用的函数,
例如
    count(/gridbag/row)
返回gridbag根元素下row元素的数量。

5. Java SE 5.0增加了一个API来计算XPath表达式
(1)需要先从XPathFactory创建一个XPath对象:

 

    javax.xml.xpath.XPathFactory xpFactory = XPathFactory.newInstance();
    javax.xml.xpath.XPath xPath = xpFactory.newXPath();
 

(2)然后调用evaluate方法来计算XPath表达式

 

    String username = xPath.evaluate("/configuration/database/username", doc);

 

(3)可以用同样的XPath对象来计算多个表达式,这种形式的evaluate方法将返回一个字符串,适用于检索文本,比如之前例子中的username
例:如果XPath表达式产生了一组节点,使用XPathConstants.NODESET类型

 

    NodeList nodes = (NodeList) xPath.evaluate("gridbag", doc, javax.xml.xpath.XPathConstants.NODESET);
 

例:结果只有一个节点,使用XPathConstants.NODE类型

 

    NodeList nodes = (NodeList) xPath.evaluate("gridbag/row[1]", doc, javax.xml.xpath.XPathConstants.NODE);NUMBER

 

例:结果是一个数字,使用XPathConstants.NUMBER类型

   int count = ((Number)xPath.evaluate("count(/gridbag/row)", doc, javax.xml.xpath.XPathConstants.NUMBER)).intValue();
 

(4)不必从文档的根节点开始搜索,可以从任意一个节点或节点列表开始。
例:如果前一次计算得到一个节点

 

    xPath.evaluate(expression, node);

 

 

DEMO:

 

package xml.XPath;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class MyXPathTest {
	
	private static final Integer PARSE_TYPE_DOM = 1;
	private static final Integer PARSE_TYPE_SAX = 2;
	
	public static void main(String[] args) {
		MyXPathTest xpathTest = new MyXPathTest();
		String fileName = System.getProperty("user.dir") + File.separator + "conf" 
				+ File.separator + "xml" + File.separator + "fontdialog.xml";
		File file = new File(fileName);
		xpathTest.parseXML(file, PARSE_TYPE_DOM);
	}


	private void parseXML(File file, Integer parseTypeDom) {
		try{
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			factory.setValidating(true);
			//指定由此工厂创建的解析器在解析 XML 文档时,必须删除元素内容中的空格
			factory.setIgnoringElementContentWhitespace(true);
			//从DocumentBuilderFactory中得到DocumentBuilder对象
			DocumentBuilder builder = factory.newDocumentBuilder();
			//读入文档
			Document doc = builder.parse(file);
			
			XPathFactory xpFactory = XPathFactory.newInstance();
			XPath xPath = xpFactory.newXPath();
			//检索文本,即一个Text类型节点的值
			String username = xPath.evaluate("/gridbag/row[1]/cell[1]/bean/property/name", doc);
			System.out.println("username:" + username);
			//检索一个节点的属性
			String anchor = xPath.evaluate("/gridbag/row[1]/cell[1]/@anchor", doc);
			System.out.println("anchor:" + anchor);
			//检索一组节点,使用XPathConstants.NODESET类型
			NodeList nodeList = (NodeList) xPath.evaluate("gridbag/row", doc, javax.xml.xpath.XPathConstants.NODESET);
			System.out.println("nodeList......");
			for(int i=0;i<nodeList.getLength();i++){
				Node child = nodeList.item(i);
				System.out.println("nodename:" + child.getNodeName() + ",nodevalue:" + child.getNodeValue());
			}
			//检索一个节点使用XPathConstants.NODE类型
		    Node aNode = (Node) xPath.evaluate("gridbag/row[1]", doc, javax.xml.xpath.XPathConstants.NODE);
		    System.out.println("aNode name:" + aNode.getNodeName() + ",type:" + aNode.getNodeType() + ",value" + aNode.getNodeValue());
		    //返回值为数字类型,使用XPathConstants.NUMBER类型
		    int count = ((Number)xPath.evaluate("count(/gridbag/row)", doc, javax.xml.xpath.XPathConstants.NUMBER)).intValue();
		    System.out.println("count:" + count);
			
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}


	private Element getRoot(String fileName, Integer parseType) {
		try{
			//得到一个DocumentBuilderFactory实例用于生成DocumentBuilder
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			//通知文档生成工厂打开验证特性
			factory.setValidating(true);
			//当通过Schema验证时必须加入以下代码
			if(parseType == PARSE_TYPE_SAX){
				//必须打开对命名空间的支持,即使在XML文件里不使用它
				factory.setNamespaceAware(true);
				//必须通过如下代码来准备处理Schema的工厂
			    final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
			    final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
			    factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
			}
			//指定由此工厂创建的解析器在解析 XML 文档时,必须删除元素内容中的空格
			factory.setIgnoringElementContentWhitespace(true);
			//从DocumentBuilderFactory中得到DocumentBuilder对象
			DocumentBuilder builder = factory.newDocumentBuilder();
			//读入文档
			File file = new File(fileName);
			if(!file.exists()){
				return null;
			}
			Document doc = builder.parse(new File(fileName));
			
			return doc.getDocumentElement();
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
		
	}
}
 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值