Java Xml 简明教程
Java XPath Parser - Parse XML Document
Java XPath 解析器是一个 API,用于使用 XPath 表达式和函数解析 XML 文档。它有助于我们遍历整个 XML 文档,并将元素作为 NodeList 中的节点获取。包“javax.xml.xpath”为 XPath 表达式的评估提供了 API。在本章中,我们将看到如何遍历 XML 文档中的所有节点。
Parse XML Using Java XPath Parser
以下是使用 Java XPath 解析器解析文档时使用的步骤−
-
步骤 1: 创建 DocumentBuilder
-
步骤 2: 读取 XML
-
步骤 3: 从文件或流创建 Document
-
*Step 4: *Building XPath
-
步骤 5: 准备和评估 XPath 表达式
-
步骤 6: 遍历 NodeList
-
*Step 7: *Retrieving Elements
Step 1: Create a DocumentBuilder
DocumentBuilderFactory 是一个工厂 API,用于创建 DocumentBuilder 对象。DocumentBuilderFactory 的 newDocumentBuilder() 方法返回一个 DocumentBuilder 对象,如下所示−
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Step 2: Reading the XML
FileReader 类用于从输入文件读取字符流。如果找不到文件或由于某种原因无法读取文件,则以下语句将抛出 "FileNotFoundException"。
FileReader fileReader = new FileReader("src/input.txt");
除了从文件中读取 XML 内容之外,我们还可以获取内容的字符串形式,并将其转换为字节,如下所示:
StringBuilder xmlBuilder = new StringBuilder();
xmlBuilder.append("<class>xyz</class>");
ByteArrayInputStream input = new ByteArrayInputStream(xmlBuilder.toString().getBytes("UTF-8"));
Step 3: Create a Document from a file or stream
第一步中创建的 DocumentBuilder 对象用于从输入文件或输入流创建文档。parse() 方法将文件或流作为参数,并返回一个 Document 对象,如下所示−
Document doc = builder.parse(input);
Step 4: Building XPath
要使用 XPath 解析 XML 文档,我们需要使用 XPathFactory 的 newXPath() 方法构建一个 newXPath。此方法返回一个新的 XPath,如下所示−
XPath xPath = XPathFactory.newInstance().newXPath();
Step 5: Preparing and Evaluating XPath expression
正如我们在上一章中所讨论的,XPath 具有帮助我们从 XML 文档中检索信息的表达式,在这里我们需要根据要求创建一个这样的表达式并对其进行评估。evaluate() 方法将表达式的结果作为 NodeList 返回,如下所示−
String expression = "/class/student";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(
doc, XPathConstants.NODESET);
Retrieve Root Element
若要从 XML 文档中检索根元素,我们可以使用 XPath 表达式“ / ”。使用此表达式并进行评估,得到只有一个 Node 的 NodeList。
Node 接口的 getNodeName() 方法将节点名称作为 String 对象进行检索,而 getTextContent() 方法将文本内容作为 String 形式进行返回。
Example
在以下示例中,我们已将 XML 内容作为 StringBuilder 对象进行处理,并使用 parse() 函数进行解析。我们只有一个元素,这显然是根元素,并且我们的文本内容是“xyz class”。通过使用上面讨论的方法,我们可以检索根元素的信息。
import java.io.ByteArrayInputStream;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
public class RetrieveRoot {
public static void main(String[] args) {
try {
//Creating a DocumentBuilder
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
//Reading the XML
StringBuilder xmlBuilder = new StringBuilder();
xmlBuilder.append("<class>xyz class</class>");
ByteArrayInputStream input = new ByteArrayInputStream(xmlBuilder.toString().getBytes("UTF-8"));
//Creating Document from file or Stream
Document doc = dBuilder.parse(input);
//Building XPath
XPath xPath = XPathFactory.newInstance().newXPath();
//Preparing and Evaluating XPath expression
String expression = "/";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(
doc, XPathConstants.NODE);
//Iterating over NodeList
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
//Retrieving Root Element
System.out.println("Root Element Name: " + node.getNodeName());
System.out.println("Text Content: " + node.getTextContent());
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
Retrieving Attributes
我们在评估完 XPath 表达式后得到的 NodeList 具有不同的节点类型的节点。如果节点类型等于“ELEMENT_NODE”,我们可以将这些节点转换为元素。Element 接口的 getAttribute("attribute_name") 方法用于以 String 形式检索属性值。
Example
以下 studentData.xml 文件包含三个学生的信息。我们将使用 Java 中的 XPath 解析程序库检索此信息。class 元素是具有三个学生子元素的根元素。我们了解一下如何使用 Java 中的 XPath 库检索三个学生的信息。
<?xml version = "1.0"?>
<class>
<student rollno = "393">
<firstname>dinkar</firstname>
<lastname>kad</lastname>
<nickname>dinkar</nickname>
<marks>85</marks>
</student>
<student rollno = "493">
<firstname>Vaneet</firstname>
<lastname>Gupta</lastname>
<nickname>vinni</nickname>
<marks>95</marks>
</student>
<student rollno = "593">
<firstname>jasvir</firstname>
<lastname>singh</lastname>
<nickname>jazz</nickname>
<marks>90</marks>
</student>
</class>
在以下 RetrieveAttributes.java 程序中,我们解析了 student.xml 文件并构建了一个文档。表达式 '/class/student' 用于将“class”节点中的所有“student”节点获取到一个 NodeList 中。然后迭代 NodeList,获取各个学生的信息。
import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
public class RetrieveAttributes {
public static void main(String[] args) {
try {
//Creating a DocumentBuilder
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
//Reading the XML
File inputFile = new File("studentData.xml");
//Creating Document from file or Stream
Document doc = dBuilder.parse(inputFile);
//Building XPath
XPath xPath = XPathFactory.newInstance().newXPath();
//Preparing and Evaluating XPath expression
String expression = "/class/student";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(
doc, XPathConstants.NODESET);
//Iterating over NodeList
for (int i = 0; i < nodeList.getLength(); i++) {
Node nNode = nodeList.item(i);
System.out.println("\nCurrent Element :" + nNode.getNodeName());
//Retrieving Elements
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
System.out.println("Student roll no :" + eElement.getAttribute("rollno"));
System.out.println("First Name : "
+ eElement
.getElementsByTagName("firstname")
.item(0)
.getTextContent());
System.out.println("Last Name : "
+ eElement
.getElementsByTagName("lastname")
.item(0)
.getTextContent());
System.out.println("Nick Name : "
+ eElement
.getElementsByTagName("nickname")
.item(0)
.getTextContent());
System.out.println("Marks : "
+ eElement
.getElementsByTagName("marks")
.item(0)
.getTextContent());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output
三个学生的所有信息均显示在控制台上。
Current Element :student
Student roll no : 393
First Name : dinkar
Last Name : kad
Nick Name : dinkar
Marks : 85
Current Element :student
Student roll no : 493
First Name : Vaneet
Last Name : Gupta
Nick Name : vinni
Marks : 95
Current Element :student
Student roll no : 593
First Name : jasvir
Last Name : singh
Nick Name : jazz
Marks : 90