Java中如何使用XPath表达式查询XML节点

来源:Python编程网作者:香港程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《Java中如何使用XPath表达式查询XML节点》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Java中如何使用XPath表达式查询XML节点》有用,将其分享出去将是对创作者最好的鼓励。

在Java开发中,处理XML格式的数据是常见需求,当XML结构复杂、层级较深时,手动遍历节点树的方式不仅代码冗余,还容易出错。XPath是一门在XML文档中查找信息的语言,通过简洁的路径表达式就能快速定位到目标节点,大幅提升XML解析效率。Java标准库已经内置了对XPath的支持,不需要额外引入第三方依赖就能完成相关操作。

Java中如何使用XPath表达式查询XML节点

准备工作

Java中使用XPath需要依赖两个核心类:DocumentBuilder用于解析XML文件得到文档对象,XPath用于执行XPath表达式。这两个类都来自Java标准库,不需要额外添加依赖,只需要导入对应的包即可。

需要导入的包如下:

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.File;

基础使用步骤

Java中使用XPath查询XML节点的整体流程分为四步:解析XML得到文档对象、创建XPath对象、编写XPath表达式、执行表达式获取结果。下面通过一个示例XML文件演示完整流程。

示例XML文件内容如下,保存为test.xml

<?xml version="1.0" encoding="UTF-8"?>
<students>
    <student id="1">
        <name>张三</name>
        <age>20</age>
        <course>Java</course>
    </student>
    <student id="2">
        <name>李四</name>
        <age>22</age>
        <course>Python</course>
    </student>
    <student id="3">
        <name>王五</name>
        <age>20</age>
        <course>Java</course>
    </student>
</students>

第一步:解析XML得到Document对象

使用DocumentBuilderFactoryDocumentBuilder解析XML文件,得到代表整个XML文档的Document对象,后续XPath查询都是基于这个对象进行。

public static Document parseXml(String filePath) throws Exception {
    // 创建文档构建器工厂
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    // 创建文档构建器
    DocumentBuilder builder = factory.newDocumentBuilder();
    // 解析XML文件得到Document对象
    return builder.parse(new File(filePath));
}

第二步:创建XPath对象

通过XPathFactory创建XPath实例,这个实例用于执行后续的XPath表达式。

public static XPath createXPath() {
    // 创建XPath工厂
    XPathFactory xPathFactory = XPathFactory.newInstance();
    // 创建XPath对象
    return xPathFactory.newXPath();
}

第三步:编写XPath表达式并执行查询

XPath表达式的语法和文件路径类似,/代表根节点,//代表任意位置的节点,@用于获取属性。下面演示几个常见的查询场景。

场景1:查询所有学生节点的姓名

表达式//student/name表示查找所有student节点下的name子节点。

public static void queryAllStudentNames(Document document, XPath xPath) throws Exception {
    // 编写XPath表达式
    String expression = "//student/name";
    // 执行表达式,返回节点列表
    NodeList nodeList = (NodeList) xPath.evaluate(expression, document, XPathConstants.NODESET);
    // 遍历结果
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node node = nodeList.item(i);
        System.out.println("学生姓名:" + node.getTextContent());
    }
}

场景2:查询id为2的学生信息

表达式//student[@id='2']表示查找所有带有id属性且值为2的student节点,[@属性名='值']是属性筛选的语法。

public static void queryStudentById(Document document, XPath xPath) throws Exception {
    String expression = "//student[@id='2']";
    Node node = (Node) xPath.evaluate(expression, document, XPathConstants.NODE);
    if (node != null) {
        // 获取子节点内容
        String name = xPath.evaluate("name", node);
        String age = xPath.evaluate("age", node);
        String course = xPath.evaluate("course", node);
        System.out.println("id为2的学生信息:姓名=" + name + ",年龄=" + age + ",课程=" + course);
    }
}

场景3:查询年龄为20岁的学生姓名

表达式//student[age='20']/name表示先筛选age子节点值为20的student节点,再获取这些节点的name子节点。

public static void queryStudentByAge(Document document, XPath xPath) throws Exception {
    String expression = "//student[age='20']/name";
    NodeList nodeList = (NodeList) xPath.evaluate(expression, document, XPathConstants.NODESET);
    System.out.println("年龄为20岁的学生姓名:");
    for (int i = 0; i < nodeList.getLength(); i++) {
        System.out.println(nodeList.item(i).getTextContent());
    }
}

常见问题处理

处理XML命名空间

如果XML文档带有命名空间,直接写节点名会查询不到结果,需要在XPath中设置命名空间上下文。示例如下:

import javax.xml.namespace.NamespaceContext;
import java.util.Iterator;

// 自定义命名空间上下文
class CustomNamespaceContext implements NamespaceContext {
    @Override
    public String getNamespaceURI(String prefix) {
        if ("ns".equals(prefix)) {
            return "http://www.example.org/student";
        }
        return null;
    }
    @Override
    public String getPrefix(String namespaceURI) {
        return null;
    }
    @Override
    public Iterator<String> getPrefixes(String namespaceURI) {
        return null;
    }
}

// 使用命名空间查询
public static void queryWithNamespace(Document document, XPath xPath) throws Exception {
    // 设置命名空间上下文
    xPath.setNamespaceContext(new CustomNamespaceContext());
    // 表达式中使用命名空间前缀
    String expression = "//ns:student/ns:name";
    NodeList nodeList = (NodeList) xPath.evaluate(expression, document, XPathConstants.NODESET);
    for (int i = 0; i < nodeList.getLength(); i++) {
        System.out.println(nodeList.item(i).getTextContent());
    }
}

处理表达式中的特殊字符

如果节点名或者属性值包含空格、连字符等特殊字符,需要用单引号包裹,或者使用concat函数处理,避免表达式语法错误。

完整测试代码

将上述方法整合,编写主函数测试所有查询场景:

public static void main(String[] args) {
    try {
        // 解析XML
        Document document = parseXml("test.xml");
        // 创建XPath对象
        XPath xPath = createXPath();
        // 测试查询所有学生姓名
        System.out.println("所有学生姓名:");
        queryAllStudentNames(document, xPath);
        // 测试查询id为2的学生
        queryStudentById(document, xPath);
        // 测试查询年龄为20的学生
        queryStudentByAge(document, xPath);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

运行上述代码就能看到对应的查询结果,开发者可以根据实际的XML结构和查询需求调整XPath表达式,实现更灵活的节点查询。

JavaXPathXMLXML节点查询修改时间:2026-07-04 12:06:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。