I'm trying to access the methodName element of an XML document开发者_运维问答 using XPATH in Cocoa via the NSXMLElement object.
This is the XML representation of element
<iq type='set'
from='requester@company-b.com/jrpc-client'
to='responder@company-a.com/jrpc-server'
id='rpc1'>
<query xmlns='jabber:iq:rpc'>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>6</i4></value>
</param>
</params>
</methodCall>
</query>
</iq>
I've tried,
NSArray *nodes = [element nodesForXPath:@"iq/query/methodCall/methodName"
error:&err];
but it always returns an empty NSArray.
It works fine without the namespace.
Solution
/*[name()='iq']/*[name()='query' and namespace-uri()='jabber:iq:rpc']/*[name()='methodCall']/*[name()='methodName']
This is a FAQ about how to construct an XPath expression agains a document with default namespace. There are a lot of answers in SO.
The reason for this problem is that
<query xmlns='jabber:iq:rpc'>
contains a default namespace and all of its descendent elements are in this namespace.
The solution is either to use location steps of the type:
*[name()='xxx']
Then an XPath expression of the kind:
*[name()='iq']/*[name()='query']/*[name()='methodCall']/*[name()='methodName']
selects the desired nodes.
In even more complicated cases where there are multiple (nested) default namespaces, it may be necessary to use location steps of the kind:
*[name()='xxx' and namespace-uri()='theCorrectNamespace']
Or, (recommended) in the hosting language (usually possible) to register the 'jabber:iq:rpc'
namespace and associate a prefix, say "x:"
to it.
Then an XPath expression selecting the desired nodes will look like:
iq/x:query/x:methodCall/x:methodName
where the prefix "x:"
has been associated to the registered namespace 'jabber:iq:rpc'
.
精彩评论