Java中声明XML Schema后XPath查询无法返回对应元素如何解决
问题原因
- 你的第二个XML声明了默认命名空间
xmlns="https://www.w3schools.com",文档内所有未显式指定前缀的元素,都默认归属该命名空间。 - 你代码中已经开启了命名空间感知(
factory.setNamespaceAware(true)),此时XPath表达式必须匹配元素的命名空间才能命中结果,但你原来的/note/heading没有指定命名空间,只会匹配无命名空间的note元素,因此返回空结果。
解决方法
两种常用方案可选:
方案1:注册命名空间前缀(推荐,符合XML规范)
首先自定义NamespaceContext实现类,给目标命名空间绑定自定义前缀,再修改XPath表达式使用该前缀匹配元素。
示例修改后的代码:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse("inventory.xml"); XPathFactory xpathfactory = XPathFactory.newInstance(); XPath xpath = xpathfactory.newXPath(); // 新增:绑定命名空间前缀 xpath.setNamespaceContext(new NamespaceContext() { @Override public String getNamespaceURI(String prefix) { if ("ws".equals(prefix)) { // 和XML里的默认命名空间地址保持一致 return "https://www.w3schools.com"; } return XMLConstants.NULL_NS_URI; } @Override public String getPrefix(String namespaceURI) { return null; } @Override public Iterator getPrefixes(String namespaceURI) { return null; } }); // 修改XPath表达式,使用绑定的ws前缀 XPathExpression expr = xpath.compile("/ws:note/ws:heading/text()"); Object result = expr.evaluate(doc, XPathConstants.NODESET); NodeList nodes = (NodeList) result; for (int i = 0; i < nodes.getLength(); i++) { System.out.println(nodes.item(i).getNodeValue()); }
方案2:使用local-name()忽略命名空间校验(快速兼容,不推荐)
如果不想处理命名空间,可以直接在XPath中通过local-name()匹配元素的本地名称,跳过命名空间校验,适合临时调试场景,缺点是如果有重名元素会匹配错误:
修改XPath表达式为:
/*[local-name()='note']/*[local-name()='heading']/text()
内容的提问来源于stack exchange,提问作者Thorsten Niehues
相关产品推荐
相关产品推荐

