我有一个XML
格式:
<?xml version="1.0" encoding="UTF-8"?>
<semseg:Envelope xmlns:semseg="http://a-random-URL" xmlns="http://another-random-URL">
<semseg:subject>Subject</semseg:subject>
<semseg:Sender>
<semseg:name>Me</semseg:name>
</semseg:Sender>
<Triangle>
<Triangle time='2017-11-29'>
<Triangle key='a' value='b'/>
<Triangle key='c' value='d'/>
<Triangle key='e' value='f'/>
<Triangle key='g' value='h'/>
</Triangle>
</Triangle>
</semseg:Envelope>
我正在尝试使用<Triangle>
来检索元素<Triangle time='2017-11-29'>
(不是 XPath
-元素名称在此XML中有点重复)。部分代码如下:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc = documentBuilder.parse("file.xml");
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
XPathExpression xpr = xPath.compile("/semseg:Envelope/Triangle");
NodeList nodes = (NodeList)xpr.evaluate(doc, XPathConstants.NODESET);
由于没有选择任何元素,因此我为XPath
尝试了许多可能的组合,但没有任何运气。不过,使用this在线XPath
检查器测试相同的XPath
和相同的XML
文件会产生我想要的结果。它甚至可以使用
/semseg:Envelope/Triangle/Triangle/@time
似乎名称空间前缀存在问题。解析XML
而没有任何名称空间前缀的情况对XPath
来说很好。
答案 0 :(得分:2)
您的XML输入实际上有两个名字空间。
第一个是默认值,声明如下:
<semseg:Envelope ... xmlns="http://another-random-URL" ...
作为默认元素,任何没有名称空间的XML元素都属于该默认名称空间。
如此定义:
<semseg:Envelope xmlns:semseg="http://a-random-URL" ...
意味着每个带有semseg
前缀的XML元素都属于该命名空间。
因此,您的目标是要针对
的XPath表达式Triangle
元素(无前缀,因此实际上会转换为Triangle
名称空间中的任何http://another-random-URL
元素)。semseg:Enveloppe
元素的直接子元素(实际上转换为属于“ http://a-random-URL”命名空间的本地名称Enveloppe
的 root元素)。我们创建一个NamespaceContext来描述我们正在使用的名称空间: 我定义了希望使用的前缀,并将其映射到名称空间。这些前缀将由XPath引擎使用。我地图:
main
命名空间的http://a-random-URL
前缀secondary
命名空间的http://another-random-URL
前缀使用我定义的映射,可以将您的需求转换为该XPath:
/main:Envelope/secondary:Triangle
这可行:
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
xPath.setNamespaceContext(new NamespaceContext() {
@Override
public String getNamespaceURI(String prefix) {
if ("main".equals(prefix)) {
return "http://a-random-URL";
}
if ("secondary".equals(prefix)) {
return "http://another-random-URL";
}
return null;
}
@Override
public String getPrefix(String namespaceURI) {
// This should be implemented but I'm lazy and this sample works without it
return null;
}
@Override
public Iterator getPrefixes(String namespaceURI) {
// This should be implemented but I'm lazy and this sample works without it
return null;
}
});
XPathExpression xpr = xPath.compile("/main:Envelope/secondary:Triangle");
NodeList nodes = (NodeList)xpr.evaluate(doc, XPathConstants.NODESET);
System.out.println(nodes.getLength());
输出:
1
在这里,我实现了一个非常愚蠢的名称空间上下文,但是如果您拥有Spring框架,CXF,guava(我认为)或其他可用的框架,则通常会遇到类似SimpleNamespaceContext
或MapBasedNamespaceContext
之类的东西。可能是更好的选择。
答案 1 :(得分:1)
这对我有用
CREATE NONCLUSTERED INDEX NC_wsm_WorkOrderSchedule_tsrjobid
ON wsm_WorkOrderSchedule (tsrjobid);