Anss
Anss

Reputation: 674

XPathExpression selecting by namespace attribute selects nothing

I am trying to extract the database credentials from standalone.xml(Wildfly 9.0) (link to 8.1 version). Using XPath for this, I am facing the issue that my XPathExpression is not working correctly,

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
builder = factory.newDocumentBuilder();
org.w3c.dom.Document doc = builder.parse(System.getProperty("jboss.server.config.dir") + "/standalone.xml");

XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("/server/subsystem[@xmlns='urn:jboss:domain:datasources:3.0']/text()");

NodeList nl = (NodeList)expr.evaluate(doc, XPathConstants.NODESET);

System.out.println("NodeList count " + nl.getLength());

the line,

"/server/subsystem[@xmlns='urn:jboss:domain:datasources:3.0']/text()"

is not fetching the nodes from the subsystem element(NodeList count is 0),

"/server"

works fine(NodeList count is 7).Below is the file,

<server xmlns="urn:jboss:domain:3.0">
    <profile>            
        <subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/>
        <subsystem xmlns="urn:jboss:domain:datasources:3.0">
            <datasources>
                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                    <driver>h2</driver>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
            </datasources>
        </subsystem>
        <subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0">
            <deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" runtime-failure-causes-rollback="${jboss.deployment.scanner.rollback.on.failure:false}"/>
        </subsystem>
    </profile>
</server>

Can anyone please tell me what is the issue here?

Upvotes: 3

Views: 691

Answers (1)

Abel
Abel

Reputation: 57149

/server/subsystem[@xmlns='urn:jboss:domain:datasources:3.0']/text()

This expression is testing against an attribute xmlns, which cannot possibly exist, because it is forbidden. That pseudo-attribute is used to declare a namespace and like any namespace attribute, including xmlns:xsl and the like, you cannot access them directly.

Instead, use:

 /server/subsystem[namespace-uri()='urn:jboss:domain:datasources:3.0']/text()

But this doesn't make sense unless the default namespace is already urn:jboss:domain:datasources:3.0.


Better approach

The problem is: the expression will look for subsystem in no-namespace, finds nothing, and then the predicate will never be used.

To resolve this, use either:

/server/*
    [namespace-uri()='urn:jboss:domain:datasources:3.0']
    [local-name() = 'subsystem']

Or declare the namespace, for instance for the prefix ds3, and then, much, much simpler, this works:

/server/ds3:subsystem

While this fixes your expression, it won't find anything, because subsystem is not a child of server. Use:

/server/profile/ds3:subsystem

Upvotes: 3

Related Questions