使用 XPath 在 Java 中通过命名空间查询 XML
当处理包含绑定到命名空间的元素的 XML 文档时,使用 XPath 查询可能会变得具有挑战性。考虑以下示例:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> <sheets> <sheet name="Sheet1" sheetId="1" r:id="rId1"/> </sheets> </workbook>
使用默认的“无命名空间”XPath 表达式(如“/workbook/sheets/sheet[1]”)将会失败。这是因为 XML 文档中的元素绑定到命名空间,而 XPath 表达式中不考虑命名空间。
解决方案 1:注册命名空间并使用命名空间前缀
推荐的方法是使用名称空间前缀注册名称空间,使 XPath 更易于阅读和使用维护:
NamespaceContext namespaceContext = new NamespaceContext() { @Override public String getNamespaceURI(String prefix) { if (prefix.equals("main")) { return "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; } else if (prefix.equals("r")) { return "http://schemas.openxmlformats.org/officeDocument/2006/relationships"; } return null; } }; XPathFactory xPathFactory = XPathFactory.newInstance(); XPath xPath = xPathFactory.newXPath(); xPath.setNamespaceContext(namespaceContext); NodeList nodes = (NodeList) xPath.evaluate("/main:workbook/main:sheets/main:sheet[1]", document, XPathConstants.NODESET);
使用命名空间前缀,XPath 表达式变为“/main:workbook/main:sheets/main:sheet[1]”,它可以正确寻址绑定到指定命名空间的元素。
解决方案 2:通用匹配和谓词过滤器
或者,使用 XPath没有命名空间前缀的表达式可以通过使用元素的通用匹配和指定所需的 local-name() 和 namespace-uri() 的谓词过滤器来构造:
XPathFactory xPathFactory = XPathFactory.newInstance(); XPath xPath = xPathFactory.newXPath(); NodeList nodes = (NodeList) xPath.evaluate("/*[local-name()='workbook' and namespace-uri()='http://schemas.openxmlformats.org/spreadsheetml/2006/main']" + "/*[local-name()='sheets' and namespace-uri()='http://schemas.openxmlformats.org/spreadsheetml/2006/main']" + "/*[local-name()='sheet' and namespace-uri()='http://schemas.openxmlformats.org/spreadsheetml/2006/main'][1]", document, XPathConstants.NODESET);
此方法很详细并且如果 XML 文档中存在混合词汇,可能会带来风险。
结论
处理时对于带有名称空间的 XML 文档,必须考虑名称空间绑定。通过使用前缀注册命名空间或精心设计通用 XPath 表达式,可以执行准确可靠的查询。
以上是如何使用 XPath 在 Java 中通过命名空间查询 XML?的详细内容。更多信息请关注PHP中文网其他相关文章!