如何在dom4j selectNotes xpath表达式中使用默认名称空间?

如何在dom4j selectNotes xpath表达式中使用默认名称空间?,xpath,xml-namespaces,dom4j,Xpath,Xml Namespaces,Dom4j,我正在使用Dom4J解析一些Maven Pom文件。当我使用没有默认名称空间的Pom文件时,一切正常。例如: Document pom = DocumentHelper.parseText( "<project>" + " <groupId>xx.gov.xxx.sistema.xxx</groupId>" + " <artifactId>

我正在使用Dom4J解析一些Maven Pom文件。当我使用没有默认名称空间的Pom文件时,一切正常。例如:

Document pom = DocumentHelper.parseText(
                 "<project>" +
                 "   <groupId>xx.gov.xxx.sistema.xxx</groupId>" + 
                 "   <artifactId>sis-teste</artifactId>" + 
                 "   <packaging>war</packaging>" + 
                 "</project>");
//below works fine
String groupId = pom.selectSingleNode("/project/groupId").getText()
Document pom=DocumentHelper.parseText(
"" +
“xx.gov.xxx.sistema.xxx”+
“睾丸sis”+
“战争”+
"");
//下面的工作很好
字符串groupId=pom.selectSingleNode(“/project/groupId”).getText()
但如果我的Pom文件定义了默认名称空间,它将停止工作:

Document pom = DocumentHelper.parseText(
                 "<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/maven-v4_0_0.xsd\">" +
                 "   <groupId>xx.gov.xxx.sistema.xxx</groupId>" + 
                 "   <artifactId>sis-teste</artifactId>" + 
                 "   <packaging>war</packaging>" + 
                 "</project>");
//NullPointerException!!!!!!!!!!!!!!!!!!!!
String groupId = pom.selectSingleNode("/project/groupId").getText()
Document pom=DocumentHelper.parseText(
"" +
“xx.gov.xxx.sistema.xxx”+
“睾丸sis”+
“战争”+
"");
//NullPointerException!!!!!!!!!!!!!!!!!!!!
字符串groupId=pom.selectSingleNode(“/project/groupId”).getText()
奇怪的是,
pom.selectSingleNode(“/project”)
工作正常

如何使xpath查询使用默认名称空间?我只想查询
“/project/groupId”
并获取groupId节点

像这样:

    Document pom = DocumentHelper.parseText(
            "<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/maven-v4_0_0.xsd\">" +
            "   <groupId>xx.gov.xxx.sistema.xxx</groupId>" +
            "   <artifactId>sis-teste</artifactId>" +
            "   <packaging>war</packaging>" +
            "</project>");
    Map<String, String> nsContext = new HashMap<>();
    nsContext.put("p", "http://maven.apache.org/POM/4.0.0");
    XPath xp = pom.createXPath("/p:project/p:groupId");
    xp.setNamespaceURIs(nsContext);
    String groupId = xp.selectSingleNode(pom).getText();
    System.out.println(groupId);
Document pom=DocumentHelper.parseText(
"" +
“xx.gov.xxx.sistema.xxx”+
“睾丸sis”+
“战争”+
"");
Map nsContext=new HashMap();
nsContext.put(“p”http://maven.apache.org/POM/4.0.0");
XPathXP=pom.createXPath(“/p:project/p:groupId”);
xp.setNamespaceURIs(nsContext);
String groupId=xp.selectSingleNode(pom.getText();
System.out.println(groupId);
更新

仔细查看DOM4J代码后,如果您能够容忍设置全局命名空间uri映射,则这是可能的:

    Map<String, String> nsContext = new HashMap<>();
    nsContext.put("p", "http://maven.apache.org/POM/4.0.0");
    DocumentFactory.getInstance().setXPathNamespaceURIs(nsContext);

    Document pom = DocumentHelper.parseText(
            "<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/maven-v4_0_0.xsd\">" +
            "   <groupId>xx.gov.xxx.sistema.xxx</groupId>" +
            "   <artifactId>sis-teste</artifactId>" +
            "   <packaging>war</packaging>" +
            "</project>");
    String groupId = pom.selectSingleNode("/p:project/p:groupId").getText();
    System.out.println(groupId);
Map nsContext=newhashmap();
nsContext.put(“p”http://maven.apache.org/POM/4.0.0");
DocumentFactory.getInstance().SetXPathNamespaceURI(nsContext);
Document pom=DocumentHelper.parseText(
"" +
“xx.gov.xxx.sistema.xxx”+
“睾丸sis”+
“战争”+
"");
字符串groupId=pom.selectSingleNode(“/p:project/p:groupId”).getText();
System.out.println(groupId);

更本地化的解决方案是使用
SAXReader
,并将其配置为专门的
DocumentFactory
,而不是全局的。

我的黑客解决方案只是在创建Dom对象之前删除pom文件的名称空间。不是很漂亮,但它工作得很好,生活还在继续

如果你不想改变你的查询,你需要跳进XPath中的兔子洞。我建议您阅读本文,将xpath与名称空间一起使用是正确的答案,但它迫使我更改所有xpath表达式和所有api调用。直接在文档对象中进行选择时,似乎无法选择名称空间。