使用 XPath 在 Java 中通过命名空间查询 XML
当处理包含绑定到命名空间的元素的 XML 文档时,使用 XPath 查询可能会变得具有挑战性。考虑以下示例:
使用默认的“无命名空间”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:通用匹配和谓词过滤器
或者,可以通过使用元素的通用匹配和指定所需 local-name() 和 namespace-uri() 的谓词过滤器来构造不带命名空间前缀的 XPath 表达式:
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 表达式,可以执行准确可靠的查询。
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3