tags:

views:

76

answers:

4

I want to manipulate xml doc having default namespace but no prefix. Is there a way to use xpath without namespace uri just as if there is no namespace?
I believe it should be possible if we set namespaceAware property of documentBuilderFactory to false. But in my case it is not working.
Is my understanding is incorrect or I am doing some mistake in code?

Here is my code:

    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();
    }

Here is my xml:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://www.mydomain.com/schema"&gt;
  <author>
    <book title="t1"/>
    <book title="t2"/>
  </author>
</root>
A: 

This looks like the same problem Default XML namespace, JDOM, and XPath

belwood
+1  A: 

Your XPath expression author will always return an empty sequence because there is no author root element.

Probably, you should correct your test using:

/root/author
Dennis Knochenwefel
+1 for correct XPath expression.
Alejandro
This was a typo mistake that I corrected in my question but this is not part of the issue.
Leslie Norman
+1  A: 

The XPath processing for a document that uses the default namespace (no prefix) is the same as the XPath processing for a document that uses prefixes:

For namespace qualified documents you can use a NamespaceContext when you execute the XPath. You will need to prefix the fragments in the XPath to match the NamespaceContext. The prefixes you use do not need to match the prefixes used in the document.

Here is how it looks with your code:

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;
        }

    }

}

Note: I also used the corrected XPath suggested by Dennis.

The following also appears to work, and is closer to your original question:

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();
        }
    }

}
Blaise Doughan
+1 Good explanation for a FAQ.
Alejandro
So I will have to move to namespaced scenario. Well, a good idea but I will be in the hell in doing so. I have tons of code that is currently handling xml without namespace, through using xpath. I had to add default namespace for validation (by IDE and programmatically) purpose. Is there any way to kill two birds with one stone? I mean I may not have to edit all of the xpath expressions, and at the same time could get the document validated both in IDE and programmatically?
Leslie Norman
I thought to remove namespace. In that case I will not face xpath issue and for programmatical validation I may add namespace at runtime. Perhaps, I will only have to parse my documents before validation. It could be acceptable but after doing so, I don’t see any way to validate my xml docs by the IDE.Any other idea?
Leslie Norman
Changing your XPath to what Dennis suggested will get your original code to work. Without using the namespace approach.
Blaise Doughan
Oh really? then there must be some other error too as this code is not working on my machine. Can you please help me find that?
Leslie Norman
I have added the version that works for me that uses a non-namespace-aware DocumentBuilderFactory.
Blaise Doughan
A: 

Blaise Doughan is right, attached code is correct.
Problem was somewhere elese. I was running all my tests through Application launcher in Eclipse IDE and nothing was working. Then I discovered Eclipse project was cause of all grief. I ran my class from command prompt, it worked. Created a new eclipse project and pasted same code there, it worked there too. Thank you all guys for your time and efforts.

Leslie Norman
Happy to help, up votes and accepted answers are always welcomed.
Blaise Doughan