wood burning stoves 2.0*
The moose likes XML and Related Technologies and the fly likes Parsing an XML Document containing Namesapces using XPath and Xalan Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Engineering » XML and Related Technologies
Bookmark "Parsing an XML Document containing Namesapces using XPath and Xalan" Watch "Parsing an XML Document containing Namesapces using XPath and Xalan" New topic
Author

Parsing an XML Document containing Namesapces using XPath and Xalan

Guru Radhakrishnan
Greenhorn

Joined: Sep 13, 2005
Posts: 7
Hi,
I have the following xml

<definitions name="FABWSImportManagerService"
targetNamespace="http://service.externalinterface.afi.com.wsdl/FABWSImportManagerService/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:binding="http://service.externalinterface.afi.com.wsdl/FABWSImportManagerBinding/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://service.externalinterface.afi.com.wsdl/FABWSImportManagerService/">
<import location="FABWSImportManagerBinding.wsdl" namespace="http://service.externalinterface.afi.com.wsdl/FABWSImportManagerBinding/"/>
<service name="FABWSImportManagerService">
<port binding="binding:FABWSImportManagerBinding" name="FABWSImportManagerPort">
<soap:address location="http://localhost:9080/AFIWeb/servlet/rpcrouter"/>

</port>
</service>
</definitions>

and i would like to obtain the location attribute with the following XPath expression

"/default efinitions/default:service/default ort/soap:address/@location"

I am using Xalan API's the following sample code describes it

private DocumentBuilderFactory docBuilderFactory = null;
private DocumentBuilder docBuilder = null;
private Document doc = null;

instream = new ByteArrayInputStream(contents);
logger.debug("Data: " + new String(contents));
docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilderFactory.setNamespaceAware(true);
docBuilder = docBuilderFactory.newDocumentBuilder();
doc = docBuilder.parse(instream);
DOMImplementation impl = docBuilder.getDOMImplementation();
Document namespaceHolder = impl.createDocument("http://schemas.xmlsoap.org/wsdl/soap/","soap:namespaceMapping", null);
Element root = namespaceHolder.getDocumentElement();
root.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns efault","http://schemas.xmlsoap.org/wsdl/");
root.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:soap","http://schemas.xmlsoap.org/wsdl/soap/");
if(impl.hasFeature("XPath","3.0")){
System.out.println("XPath 3.0 Feature Supported");
}
XPathEvaluator evaluator= (XPathEvaluator)doc;
XPathNSResolver namespaces = evaluator.createNSResolver(root);
XPathExpression expression = evaluator.createExpression("/default efinitions/default:service/default ort/soap:address/@location",namespaces);

XPathResult nodes = (XPathResult)expression.evaluate(doc,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);

System.out.println(nodes);

I get the following exception at

XPathEvaluator evaluator= (XPathEvaluator)doc

java.lang.ClassCastException: org.apache.xerces.dom.DeferredDocumentImpl

What could be the problem also i am not sure if the namespace apis are used right

Need help.

I dont wish to use JDOM. I would like a Xalan based Solution
Rajagopal Manohar
Ranch Hand

Joined: Nov 26, 2004
Posts: 183
Originally posted by Guru Radhakrishnan:


"/default efinitions/default:service/default ort/soap:address/@location"


To keep it simple you dont need to have those namespace prefixes unless its necessary. i.e. you expect the same element from different namespaces.




XPathEvaluator evaluator= (XPathEvaluator)doc

java.lang.ClassCastException: org.apache.xerces.dom.DeferredDocumentImpl

What could be the problem also i am not sure if the namespace apis are used right



Document does not implement XPathEvaluator thats the problem you cant do that.

use the org.apache.xpath.XPathAPI instead and pass the document and the xpath expression to it. look at selectNodeIterator method.

In your case this expression would do

"/definitions/service/port/address/@location"

If you wish to have namespaces in the expression look at

org.apache.xml.utils.PrefixResolver. specifically JAXPPrefixResolver and NamespaceContext classes

Regards
[ September 13, 2005: Message edited by: Rajagopal Manohar ]
Guru Radhakrishnan
Greenhorn

Joined: Sep 13, 2005
Posts: 7
Using XPathAPI returns me a nullpointerException for the expression you have mentioned. However i am able to traverse the document from the root using getFirstChild() so on and so forth. I would like to use XPath Expression

code sample below

System.out.println(doc);
Node eventNode = XPathAPI.selectSingleNode(doc, "/definitions/service/port/address/@location");//Returns Null here for eventNode

String eventString = eventNode.getFirstChild().getNodeValue();
System.out.println(eventString);

I tried using NodeIterator NodeList etc., no good all return null. what am i missing
Rajagopal Manohar
Ranch Hand

Joined: Nov 26, 2004
Posts: 183
Guru,
Did you try accesing some other node for eg "/definitions/@name"
does it return null for even that
Guru Radhakrishnan
Greenhorn

Joined: Sep 13, 2005
Posts: 7
Yes no luck. if you look closely at the xml it has a default namespace xmlns = "http://schemas.xmlsoap.org/wsdl/" which means i have to prefix all of my elements with a some prefix say "foo" and point this prefix to default namespace declaration like xmln:foo = "http://schemas.xmlsoap.org/wsdl/" and use the xpath expression like "/foo efinitions/foo:service/foo ort/foo:address/@location" which i didn't like i quickly descarded that idea since i donot have the ability to modify this xml since it is not in my control. I had a doubt on how xpath deals undeclared namespace versus default namespace. how is xpath designed? which one does it consider?. In order to investigate it i went through the spec and found the following statement on the spec.

"Every axis has a principal node type. If an axis can contain elements, then the principal node type is element; otherwise, it is the type of the nodes that the axis can contain. Thus,

For the attribute axis, the principal node type is attribute.
For the namespace axis, the principal node type is namespace.
For other axes, the principal node type is element.

A node test that is a QName is true if and only if the type of the node (see [5 Data Model]) is the principal node type and has an expanded-name equal to the expanded-name specified by the QName. For example, child: ara selects the para element children of the context node; if the context node has no para children, it will select an empty set of nodes. attribute::href selects the href attribute of the context node; if the context node has no href attribute, it will select an empty set of nodes."

In order to confirm that i wrote a xml with some elements in undeclared namespace and some in namespace then plain simple xpath expression workes. Still i wasn't convinced. There is got to be a way to access elements in default namespace with xpath query. I came across the following article which offers a good explanation on how to solve this problem

http://www.xml.com/pub/a/2004/02/25/qanda.html

just about the simplest approach i have seen so far without using bunch of apis
's and jumping through the hoops to get this simple value from this simple xml as far as i am concerned
[ September 15, 2005: Message edited by: Guru Radhakrishnan ]
Guru Radhakrishnan
Greenhorn

Joined: Sep 13, 2005
Posts: 7
I discovered following two things about XPath Now.

1) If you use setNameSpaceAware(false) while parsing the document then you dont have to worry about the namespace prefix. You can skip the prefix and fetch the Node that you want by specifying the node name in the xpath expression for ex: "/definitions/service/port/address/@location"

2) If you use setNameSpaceAware(true) while parsing the document then you have to specify namespace prefix for fetching nodes. For fetching elements in default namespace just specify the noargs prefix, in other words just specify : before the element name
for ex:"/ efinitions/:service/ ort/soap:address/@location"

that is all there is to it. xalan will do the rest.No jumping through the hoops. atlast a simple solution after two days of research .

P.S. Do you know the propulsion system used in Apollo 13 is an amazingly simple system which brought the crew back

[ September 15, 2005: Message edited by: Guru Radhakrishnan ]

[ September 15, 2005: Message edited by: Guru Radhakrishnan ]

[ September 15, 2005: Message edited by: Guru Radhakrishnan ]
[ September 15, 2005: Message edited by: Guru Radhakrishnan ]
Rajagopal Manohar
Ranch Hand

Joined: Nov 26, 2004
Posts: 183
If you use setNameSpaceAware(false) while parsing the document then you dont have to worry about the namespace prefix.


Ok that explains why I never faced the problem before. Infact I think the property is by default false. So you need not worry if you simply dont use the setNameSpaceAware method at all


I came across the following article which offers a good explanation on how to solve this problem

http://www.xml.com/pub/a/2004/02/25/qanda.html

just about the simplest approach i have seen so far without using bunch of apis


That was a real eye opener :roll: Thanks a lot for the link
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Parsing an XML Document containing Namesapces using XPath and Xalan
 
Similar Threads
problem in 'generate client' for WSDL in WSAD
Convert the existing soap:binding style="document" to RPC.
Please help, Axis problem
Convert the existing soap:binding style="document" to RPC.
Convert the existing soap:binding style="document" to RPC.