使用XPath获取已选中节点的子节点
有如下的一个XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<Students>
	<Student id="001" grade="C">
		<Age>16</Age>
		<Name>phoebe</Name>
		<Address>
			<Country>USA</Country>
			<City>Alaska</City>
		</Address>
	</Student>
	<Student id="002" grade="A">
		<Age>18</Age>
		<Name>eileen</Name>
		<Address>
			<Country>USA</Country>
			<City>Chicago</City>
		</Address>
	</Student>
	<Student id="003" grade="C">
		<Age>15</Age>
		<Name>angela</Name>
		<Address>
			<Country>USA</Country>
			<City>Boston</City>
		</Address>
	</Student>
	<Student id="004" grade="B">
		<Age>17</Age>
		<Name>mars</Name>
		<Address>
			<Country>CHN</Country>
			<City>BeiJing</City>
		</Address>
	</Student>
	<Student id="005" grade="C">
		<Age>19</Age>
		<Name>grace</Name>
		<Address>
			<Country>UK</Country>
			<City>London</City>
		</Address>
	</Student>
</Students>
需要从此文件中找出grade为C的Student,并输出其ID和详细信息。使用/Students/Student[@grade=\"C\"]即可选择出满足条件的Student:
List<Element> students = root.selectNodes("/Students/Student[@grade=\"C\"]");
if(!students.isEmpty()){
	for(Element student : students){
		System.out.println(student.attributeValue("id"));
	}
}
然后需要从选中的Student中再次获取其子节点,一开始我使用//Name来选取姓名,使用selectSingleNode("//Name")获得的结果都是第一个,再用selectNodes("//Name")选取,看到的结果是选取了所有的Student的Name,正确的方式应该是使用selectSingleNode(".//Name")或直接取Name:selectSingleNode("Name")。
完整的代码如下:
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
public class XPathXmlTest {
	public static void main(String[] args) {
		try {
			SAXReader reader = new SAXReader();
			Document document = reader.read(XPathXmlTest.class.getResourceAsStream("/Students.xml"));
			Element root = document.getRootElement();
			List<Element> students = root.selectNodes("/Students/Student[@grade=\"C\"]");
			if(!students.isEmpty()){
				Node name = null;
				Node age = null;
				Node country = null;
				Node city = null;
				String format = "%s\t%s\t%s\t%s,%s";
				System.out.println(String.format(format, "ID", "Name", "Age", "City", "Country"));
				for(Element student : students){
					name = student.selectSingleNode("Name");
					age = student.selectSingleNode("Age");
					country = student.selectSingleNode("Address/Country");
					city = student.selectSingleNode("Address/City");
					System.out.println(String.format(format, student.attributeValue("id"), name.getText(), age.getText(), city.getText(), country.getText()));
				}
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
}
- 程序输出:
| ID | Name | Age | City,Country | 
|---|---|---|---|
| 001 | phoebe | 16 | Alaska,USA | 
| 003 | angela | 15 | Boston,USA | 
| 005 | grace | 19 | London,UK | 
注:需要依赖dom4j和’jaxen’
 参考资料
-  XPath路径表达式 
| 路径表达式 | 说明 | 
|---|---|
| nodename | 选取此节点的所有子节点 | 
| / | 从根节点选取 | 
| // | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 | 
| . | 选取当前节点 | 
| .. | 选取当前节点的父节点 | 
| @ | 选取属性 |