• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Parsing an XML Document containing Namesapces using XPath and Xalan

 
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 183
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 183
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Guru,
Did you try accesing some other node for eg "/definitions/@name"
does it return null for even that
 
Guru Radhakrishnan
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 183
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic