java - Java XPath 处理器忽略命名空间上下文
问题描述
我正在尝试使用默认命名空间查询 XML 文档。我想在默认命名空间中获取节点的文本内容。
我相信我已经正确设置了。但是,我没有得到结果。我创建了一个 NamespaceContext 并将它传递给 XPath 处理器。从输出看,似乎没有引用上下文。因此,命名空间感知处理器不会在默认命名空间中找到节点。
当我尝试使用忽略命名空间的非常丑陋的 XPath 表达式进行查询时,我得到了预期的结果。
我已经包含了一个示例程序,正在查询的 XML 文件和输出。
谢谢。
该程序
import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.xml.sax.InputSource;
public class Example {
public static void main(String[] args) throws IOException, XPathExpressionException {
List<String> pomLines = Files.readAllLines(Paths.get("example.xml"));
String document = String.join(System.lineSeparator(), pomLines);
// XPathFactory xpathFactory = new net.sf.saxon.xpath.XPathFactoryImpl();
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpathNS = xpathFactory.newXPath();
xpathNS.setNamespaceContext(new NamespaceContext() {
@Override
public String getNamespaceURI(String prefix) {
System.out.println("*** getNamespaceURI, prefix='" + prefix + "'");
if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
System.out.println("*** returning a URL");
return "http://maven.apache.org/POM/4.0.0";
}
System.out.println("*** returning NULL_NS_URI");
return XMLConstants.NULL_NS_URI;
}
@Override
public String getPrefix(String namespaceURI) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Iterator<String> getPrefixes(String namespaceURI) {
throw new UnsupportedOperationException("Not supported yet.");
}
});
XPathExpression xpathExpressionNS = xpathNS.compile("/project/name/text()");
String artifactIdNS = xpathExpressionNS
.evaluate(new InputSource(new StringReader(document)));
System.out.println("artifactIdNS='" + artifactIdNS + "'");
XPath xpath = xpathFactory.newXPath();
XPathExpression xpathExpression = xpath
.compile("/*[local-name()='project']/*[local-name()='name']/text()");
String artifactId = xpathExpression.evaluate(new InputSource(new StringReader(document)));
System.out.println("artifactId='" + artifactId + "'");
}
}
XML 文档
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>parent-test-repo</artifactId>
<version>0.1.0</version>
</parent>
<artifactId>test-repo-1</artifactId>
<name>test-repo-1</name>
<version>1.1.0</version>
</project>
实际输出
~/temp% java Example
artifactIdNS=''
artifactId='test-repo-1'
我会期待一些带有***
.
解决方案
如果 xpath 表达式不包含前缀,则 xpath 编译器不会调用名称空间解析器。此 xpath 将显示预期消息但不显示预期值
XPathExpression xpathExpressionNS = xpathNS.compile("/:project/name/text()");
结果:
*** getNamespaceURI, prefix=''
*** returning a URL
artifactIdNS=''
映射默认命名空间的虚拟前缀可用于查询 xml
if ("mvn".equals(prefix)) {
System.out.println("*** returning a URL");
return "http://maven.apache.org/POM/4.0.0";
}
// code
XPathExpression xpathExpressionNS = xpathNS.compile("/mvn:project/mvn:name/text()");
结果:
*** getNamespaceURI, prefix='mvn'
*** returning a URL
*** getNamespaceURI, prefix='mvn'
*** returning a URL
artifactIdNS='SO-68977962'
artifactId='SO-68977962'
推荐阅读
- python - Divio Cloud 部署错误:ENOGIT git 未安装或不在 PATH 中
- java - 我们如何修复“java.sql.SQLSyntaxErrorException:
- ios - 应用程序仅在从 Xcode 运行时才发现蓝牙设备
- python - 使用 Python 将字符串转换为字典列表
- c# - 打开文件对话过滤器未按预期工作
- javascript - 单击时显示和隐藏具有匹配类名称的 Div
- openstreetmap - 如何在 OSM(使用立交桥)中获得全国的公共交通站点?
- python - 在循环中对多个数据帧在 python 中运行回归
- sql - 创建从两列创建一列的查询
- node.js - 格式错误的响应:从 dialogflow Web 挂钩获取响应时出现 Webhook 错误