Java 如何在具有默认命名空间的xml文档上使用XPath
我想操作具有默认名称空间但没有前缀的xml文档。有没有一种方法可以像没有命名空间一样使用没有命名空间uri的xpath?Java 如何在具有默认命名空间的xml文档上使用XPath,java,xml,xpath,Java,Xml,Xpath,我想操作具有默认名称空间但没有前缀的xml文档。有没有一种方法可以像没有命名空间一样使用没有命名空间uri的xpath? 我相信,如果我们将documentBuilderFactory的namespaceAware属性设置为false,这应该是可能的。但就我而言,它不起作用。 是我的理解不正确还是我在代码中犯了错误 这是我的密码: DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); d
我相信,如果我们将documentBuilderFactory的namespaceAware属性设置为false,这应该是可能的。但就我而言,它不起作用。
是我的理解不正确还是我在代码中犯了错误 这是我的密码:
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(false);
try {
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document dDoc = builder.parse("E:/test.xml");
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nl = (NodeList) xPath.evaluate("//author", dDoc, XPathConstants.NODESET);
System.out.println(nl.getLength());
} catch (Exception e) {
e.printStackTrace();
}
以下是我的xml:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://www.mydomain.com/schema">
<author>
<book title="t1"/>
<book title="t2"/>
</author>
</root>
使用默认名称空间(无前缀)的文档的XPath处理与使用前缀的文档的XPath处理相同: 对于名称空间限定文档,可以在执行XPath时使用名称空间上下文。您需要在XPath中为片段添加前缀,以匹配名称空间上下文。您使用的前缀不需要与文档中使用的前缀匹配
import java.util.Iterator;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
public class Demo {
public static void main(String[] args) {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
try {
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document dDoc = builder.parse("E:/test.xml");
XPath xPath = XPathFactory.newInstance().newXPath();
xPath.setNamespaceContext(new MyNamespaceContext());
NodeList nl = (NodeList) xPath.evaluate("/ns:root/ns:author", dDoc, XPathConstants.NODESET);
System.out.println(nl.getLength());
} catch (Exception e) {
e.printStackTrace();
}
}
private static class MyNamespaceContext implements NamespaceContext {
public String getNamespaceURI(String prefix) {
if("ns".equals(prefix)) {
return "http://www.mydomain.com/schema";
}
return null;
}
public String getPrefix(String namespaceURI) {
return null;
}
public Iterator getPrefixes(String namespaceURI) {
return null;
}
}
}
注:
我还使用了建议的正确XPath
以下内容似乎也起到了作用,更接近您的原始问题:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
public class Demo {
public static void main(String[] args) {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document dDoc = builder.parse("E:/test.xml");
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nl = (NodeList) xPath.evaluate("/root/author", dDoc, XPathConstants.NODESET);
System.out.println(nl.getLength());
} catch (Exception e) {
e.printStackTrace();
}
}
}
正确,所附代码正确。问题出在埃利斯的某个地方。我在EclipseIDE中通过ApplicationLauncher运行所有测试,但什么都不起作用。然后我发现Eclipse项目是所有悲伤的原因。我从命令提示符运行我的类,它工作了。创建了一个新的eclipse项目并在那里粘贴了相同的代码,它也在那里工作。
感谢大家的时间和努力。我已经编写了一个简单的
namespacecoxt
实现(),这可能会有所帮助。它将映射
作为输入,其中键
是前缀,值
是名称空间
它遵循规范化,您可以看到它在中是如何工作的
Map mappings=newhashmap();
mappings.put(“foo”http://foo");
mappings.put(“foo2”http://foo");
mappings.put(“bar”http://bar");
上下文=新的SimpleNamespaceContext(映射);
context.getNamespaceURI(“foo”);//"http://foo"
context.getPrefix(“http://foo"); // “foo”或“foo2”
context.getPrefixes(“http://foo"); // [“foo”,“foo2”]
请注意,它依赖于,因此我将不得不转到名称空间场景。好主意,但如果我这么做的话,我会下地狱的。我有大量的代码目前正在使用xpath处理没有名称空间的xml。为了验证(通过IDE和编程)目的,我不得不添加默认名称空间。有什么办法一箭双雕吗?我的意思是,我可能不必编辑所有的xpath表达式,同时可以在IDE中以编程方式验证文档?我想删除名称空间。在这种情况下,我将不会面临xpath问题,对于程序验证,我可以在运行时添加名称空间。也许,我只需要在验证之前解析文档。这是可以接受的,但在这样做之后,我看不到任何方法可以通过IDE验证我的xml文档。还有其他想法吗?将XPath更改为Dennis建议的值将使原始代码正常工作。不使用名称空间方法。哦,真的吗?那么肯定还有其他错误,因为这段代码在我的机器上不起作用。你能帮我找到吗?我添加了一个对我有效的版本,它使用了一个不支持名称空间的DocumentBuilderFactory。这看起来和XML名称空间、JDOM和XPath的问题一样
Map<String, String> mappings = new HashMap<>();
mappings.put("foo", "http://foo");
mappings.put("foo2", "http://foo");
mappings.put("bar", "http://bar");
context = new SimpleNamespaceContext(mappings);
context.getNamespaceURI("foo"); // "http://foo"
context.getPrefix("http://foo"); // "foo" or "foo2"
context.getPrefixes("http://foo"); // ["foo", "foo2"]