You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-users@xalan.apache.org by "Jesus M. Salvo Jr." <je...@migasia.com> on 2003/02/04 06:08:42 UTC
Namespace-aware XPath expression
How do you get a node via XPath that is namespace-aware?
I realise it has to do with the PrefixResolver that you pass in as an argument to either the XPath constructor or to the XPath.execute(), but I am not sure how to go about it.
e.g.:
1) Do you need to pass the same resolver in both the constructor and the execute method?
2) How do I specify my expressions?
Take for example this fragment of XML
<mm7:SubmitReq xmlns:mm7="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2">
<mm7:MM7Version>5.5.0</mm7:MM7Version>
<mm7:SenderIdentification>
<mm7:VASPID>MIG</mm7:VASPID>
<mm7:VASID>Mig-test4</mm7:VASID>
<mm7:SenderAddress>
<mm7:Number>+6140955555</mm7:Number>
</mm7:SenderAddress>
</mm7:SenderIdentification>
... The above SubmitReq element is not the root element, but is obtained via Apache-SOAP:
Node submitReqNode = (Node) envelope.getBody().getBodyEntries().get( 0 );
Now once I got the SubmitReq node above, here's what I do:
PrefixResolverDefault resolver = new PrefixResolverDefault( submitReqNode );
XPath xpath = new XPath( "//SenderIdentification/SenderAddress/Number", this.locator, resolver, XPath.SELECT );
XObject xobject = xpath.execute( context, submitReqNode, resolver );
String senderString = (String) xobject.castToType( XObject.CLASS_STRING, context );
The above code will not retrieve the the number +6140955555.
... but it will if I remove the mm7 prefixes.
So what do I need to do?
I would have assumed that PrefixResolverDefault would have been namespace-aware.
Re: Namespace-aware XPath expression
Posted by "Jesus M. Salvo Jr." <je...@migasia.com>.
Jesus M. Salvo Jr. wrote:
>
> Wouldn't it have been better if instead of the prefix as part of the
> expression, you instead use the namspace URI itslef is used?
> e.g.:
>
> //http:mynamespace.org:ElementA/http:yournamespace.org:ElementB/
Nah. That would not work either, because of the : that is part of the
namespace URI
Re: Namespace-aware XPath expression
Posted by "Jesus M. Salvo Jr." <je...@migasia.com>.
Jesus M. Salvo Jr. wrote:
> Jeff Greif wrote:
>
>> That's what I explained in my previous mail. MyPrefixResolver gets a
>> map
>> that looks like this {"__mm7__" -> "namespace1",
>> "__ns8__" ->"othernamespace", ...}. You write your xpath using
>> /__mm7__:foo/__mm7__:bar without any regard for what prefixes are
>> used in
>> the document. The resolver resolves prefix __mm7__ to namespace1, which
>> will match to corresponding nodes from namespace1 in the document,
>> regardless of what prefix is used in the document.
>
> OK ... I misunderstood ....That's the part that I missed. I have to
> try this to believe it.
> Maybe somebody needs to setup an FAQ on how to do this ... because I
> would probably not be the last one to ask this question.
>
It actually works! Thanks.
Re: Namespace-aware XPath expression
Posted by "Jesus M. Salvo Jr." <je...@migasia.com>.
Jeff Greif wrote:
>That's what I explained in my previous mail. MyPrefixResolver gets a map
>that looks like this {"__mm7__" -> "namespace1",
>"__ns8__" ->"othernamespace", ...}. You write your xpath using
>/__mm7__:foo/__mm7__:bar without any regard for what prefixes are used in
>the document. The resolver resolves prefix __mm7__ to namespace1, which
>will match to corresponding nodes from namespace1 in the document,
>regardless of what prefix is used in the document.
>
OK ... I misunderstood ....That's the part that I missed. I have to try
this to believe it.
Maybe somebody needs to setup an FAQ on how to do this ... because I
would probably not be the last one to ask this question.
>The only way you'd be
>messed up is if someone actually used __mm7__ in the document to refer to
>some other namespace, which is why I suggested using unlikely prefixes in
>the map and the xpath.
>
>
>
If your above suggestion works ... then I am ok with it in my specific
case... although it be better to have a solution that works on all cases. :)
Re: Namespace-aware XPath expression
Posted by Jeff Greif <jg...@alumni.princeton.edu>.
----- Original Message -----
From: "Jesus M. Salvo Jr." <je...@migasia.com>
To: "Jeff Greif" <jg...@alumni.princeton.edu>
Cc: <xa...@xml.apache.org>
Sent: Monday, February 03, 2003 11:10 PM
Subject: Re: Namespace-aware XPath expression
> What the problem is I do not know in advance the prefix that may be used
> by a given namespace.
> All I know is that there will be two namespaces used, the SOAP
> namespace and the MM7 namespace.
> Also, the same namespace could be used in a single XML document with
> different prefixes. Argh!
>
> So how do you specify an expression if you do not know in advance the
> namespace prefixes used in the document?
That's what I explained in my previous mail. MyPrefixResolver gets a map
that looks like this {"__mm7__" -> "namespace1",
"__ns8__" ->"othernamespace", ...}. You write your xpath using
/__mm7__:foo/__mm7__:bar without any regard for what prefixes are used in
the document. The resolver resolves prefix __mm7__ to namespace1, which
will match to corresponding nodes from namespace1 in the document,
regardless of what prefix is used in the document. The only way you'd be
messed up is if someone actually used __mm7__ in the document to refer to
some other namespace, which is why I suggested using unlikely prefixes in
the map and the xpath.
>
> Wouldn't it have been better if instead of the prefix as part of the
> expression, you instead use the namspace URI itslef is used?
> e.g.:
>
> //http:mynamespace.org:ElementA/http:yournamespace.org:ElementB/
Yes, IMHO it would be better to have a scheme like:
/{http://mynamespace.org}:eltA/{http://yournamespace.org}:eltB/...
if it could be made to work. However, there are difficulties with the / and
: characters in the namespace uri getting confused with xpath syntax, and
many other problems. That's why there are prefixes. We're stuck with XPath
as it is.
>
>
> ... so you do not have to worry about prefixes in your xpath expression.
>
> Oh well.
>
>
>
>
>
>
Re: Namespace-aware XPath expression
Posted by "Jesus M. Salvo Jr." <je...@migasia.com>.
Jeff Greif wrote:
>No, if you omit a prefix from an element name in an xpath, you tell the
>xpath processor the element you want is in no namespace.
>
OK .. granted.
>
>As far as I can tell, the prefix resolver is only called on the xpath (not
>on nodes of the document). So you might provide a prefix resolver extending
>PrefixResolverDefault which knows the mappings of a certain set of prefixes
>which you use in your xpath, and lets the default resolver's method handle
>all others.
>
With a quick test, the PrefixResolverDefault returns the proper
namespace via its getNamespaceForPrefix() method ... so does the
XPathNSResolverImpl via the same method and the lookupNamespaceURI()
method. So the resolver is fine.
What the problem is I do not know in advance the prefix that may be used
by a given namespace.
All I know is that there will be two namespaces used, the SOAP
namespace and the MM7 namespace.
Also, the same namespace could be used in a single XML document with
different prefixes. Argh!
So how do you specify an expression if you do not know in advance the
namespace prefixes used in the document?
Wouldn't it have been better if instead of the prefix as part of the
expression, you instead use the namspace URI itslef is used?
e.g.:
//http:mynamespace.org:ElementA/http:yournamespace.org:ElementB/
... so you do not have to worry about prefixes in your xpath expression.
Oh well.
Re: Namespace-aware XPath expression
Posted by Jeff Greif <jg...@alumni.princeton.edu>.
No, if you omit a prefix from an element name in an xpath, you tell the
xpath processor the element you want is in no namespace.
As far as I can tell, the prefix resolver is only called on the xpath (not
on nodes of the document). So you might provide a prefix resolver extending
PrefixResolverDefault which knows the mappings of a certain set of prefixes
which you use in your xpath, and lets the default resolver's method handle
all others.
class MyPrefixResolver extends PrefixResolverDefault {
private HashMap prefixes;
public MyPrefixResolver(HashMap namespaceByPrefix, Node context) {
super(context);
prefixes = namespaceByPrefix;
}
public String getNamespaceForPrefix(prefix}{
String ns = (String)prefixes.get(prefix);
if (ns != null) return ns;
return super(prefix);
}
etc. -- other methods as needed
}
You might have to use ugly prefixes to attempt to avoid clashes with
prefixes that might appear in a document created by someone else with
another namespace as their resolution.
Jeff
----- Original Message -----
From: "Jesus M. Salvo Jr." <je...@migasia.com>
To: "Simon Kitching" <si...@ecnetwork.co.nz>
Cc: <xa...@xml.apache.org>
Sent: Monday, February 03, 2003 9:49 PM
Subject: Re: Namespace-aware XPath expression
>
> Hi Simon,
>
> ( Sorry if you got this more than once. Forgot to cc the list )
>
> I relalise I can do that ... but I would like NOT to specify the
> namespace in the XPath expression ( is that possible as per XPath
> specification? ).
>
> The reason is that the incoming SOAP message may have a different prefix
> for the same namespace.
> Furthermore, while PrefixResolver has a method called
> getNamespaceForPrefix(), it does not have a method called
> getPrefixForNamespace().
> If there was a method called getPrefixForNamespace()., then at least I
> could build the XPath expression by adding the prefix.
>
>
> Simon Kitching wrote:
>
> >Hi Jesus,
> >
> >
> >
> >><mm7:SubmitReq
xmlns:mm7="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL
-5-MM7-1-2">
> >><mm7:MM7Version>5.5.0</mm7:MM7Version>
> >><mm7:SenderIdentification>
> >> <mm7:VASPID>MIG</mm7:VASPID>
> >> <mm7:VASID>Mig-test4</mm7:VASID>
> >> <mm7:SenderAddress>
> >> <mm7:Number>+6140955555</mm7:Number>
> >> </mm7:SenderAddress>
> >></mm7:SenderIdentification>
> >>
> >>
> >>
> >
> >Have you tried
> >
> >
> >> XPath xpath = new XPath(
"//SenderIdentification/SenderAddress/Number", this.locator, resolver,
XPath.SELECT );
> >>
> >>
> >XPath xpath = new
> >XPath("//mm7:SenderIdentification/mm7:SenderAddress/mm7:Number", ...); ?
> >
> >Regards,
> >
> >Simon
> >
> >
> >
> >
> >
>
>
> --
> Jesus M. Salvo Jr.
> Mobile Internet Group Pty Ltd
> (formerly Softgame International Pty Ltd)
> M: +61 409 126699
> T: +61 2 94604777
> F: +61 2 94603677
>
> PGP Public key:
http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xC0BA5348
>
>
>
Re: Namespace-aware XPath expression
Posted by Jeff Greif <jg...@alumni.princeton.edu>.
No.
----- Original Message -----
From: "Jesus M. Salvo Jr." <je...@migasia.com>
To: <xa...@xml.apache.org>
Cc: "Simon Kitching" <si...@ecnetwork.co.nz>
Sent: Monday, February 03, 2003 10:00 PM
Subject: Re: Namespace-aware XPath expression
>
> Also ... shouldn't an XPath processor simply compare the Node's
> getLocalName() ( which returns a String without the prefix ) instead of
> its getNodeName() ( which returns a String with the prefix )?
>
Re: Namespace-aware XPath expression
Posted by "Jesus M. Salvo Jr." <je...@migasia.com>.
Also ... shouldn't an XPath processor simply compare the Node's
getLocalName() ( which returns a String without the prefix ) instead of
its getNodeName() ( which returns a String with the prefix )?
Jesus M. Salvo Jr. wrote:
>
> Hi Simon,
>
> ( Sorry if you got this more than once. Forgot to cc the list )
>
> I relalise I can do that ... but I would like NOT to specify the
> namespace in the XPath expression ( is that possible as per XPath
> specification? ).
>
> The reason is that the incoming SOAP message may have a different
> prefix for the same namespace.
> Furthermore, while PrefixResolver has a method called
> getNamespaceForPrefix(), it does not have a method called
> getPrefixForNamespace().
> If there was a method called getPrefixForNamespace()., then at least I
> could build the XPath expression by adding the prefix.
>
>
> Simon Kitching wrote:
>
>> Hi Jesus,
>>
>>
>>
>>> <mm7:SubmitReq
>>> xmlns:mm7="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2">
>>> <mm7:MM7Version>5.5.0</mm7:MM7Version>
>>> <mm7:SenderIdentification>
>>> <mm7:VASPID>MIG</mm7:VASPID>
>>> <mm7:VASID>Mig-test4</mm7:VASID>
>>> <mm7:SenderAddress>
>>> <mm7:Number>+6140955555</mm7:Number>
>>> </mm7:SenderAddress>
>>> </mm7:SenderIdentification>
>>>
>>>
>>
>>
>> Have you tried
>>
>>
>>> XPath xpath = new XPath(
>>> "//SenderIdentification/SenderAddress/Number", this.locator,
>>> resolver, XPath.SELECT );
>>>
>>
>> XPath xpath = new
>> XPath("//mm7:SenderIdentification/mm7:SenderAddress/mm7:Number", ...); ?
>>
>> Regards,
>>
>> Simon
>>
>>
>>
>>
>>
>
>
--
Jesus M. Salvo Jr.
Mobile Internet Group Pty Ltd
(formerly Softgame International Pty Ltd)
M: +61 409 126699
T: +61 2 94604777
F: +61 2 94603677
PGP Public key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xC0BA5348
Re: Namespace-aware XPath expression
Posted by "Jesus M. Salvo Jr." <je...@migasia.com>.
The confusion that I had was that I initially thought that you have to
specify the exact prefix that is used in the XML document in your xpath
expression.
As it turns out and mentioned by Jeff Greff ... you can create a
PrefixResolver that resolves the prefix that you used in the xpath
expression to a given namespace URI, and that the prefix that you use in
the xpath expression and in the PrefixResolver does NOT have to match
the prefix in the actual XML document.
After that was cleared, then things are working as I expected.
Of course, there is a caveat there that Jeff mentioned, but I'll leave
it at that.
Brenda Bell wrote:
> Jesus M. Salvo Jr. wrote:
>
>>
>> I have also tried using the XPathNSResolverImpl instead of
>> PrefixResolverDefault.
>> I still have to specify the prefix in the xpath expression.
>>
>> Anyone ...help please!
>
>
> I've been watching this thread from the start and believe that part of
> the confusion has to do with namespaces in general -- frankly, it's
> one of the most misunderstood XML concepts.
>
> You really have to think about your source document in more concrete
> terms. Namespaces are not a simple decoration -- they are a necessary
> means of establishing element "ownership" and distinguishing between
> two elements that may have the same name but mean entirely different
> things.
>
> Just because you have a priori knowledge that there are no conflicts
> in your source document doesn't mean you get to break the rules. In
> XPath, you get to ask certain types of questions... one of them being
> "give me element x". Asking for plain element x is asking for the
> element x that is not associated with any namespace. If you want an
> element x that has been associated with a namespace, you have to
> include the namespace when you ask the question... not because there
> are conflicts in your document but because the potential for conflicts
> exists in general.
>
> That said... it would be nice if XPath processors allowed you to ask
> the question "give me element x in any namespace". I'm new to Xalan,
> but have worked with other parsers -- none of which support a simple
> syntax for doing this. AFAIK, the only way to do this is to ask for
> "/*[local-name()='x']" which is much less efficient.
>
> Namespaces are there to help you... really!!! Don't get tied up in
> the prefixes -- they are a convenience. If you get in the habit of
> declaring your own prefixes for namespace URI's that you need to
> consume in your program, you'll developer more robust XML applications.
>
> Brenda
> http://opensource.theotherbell.com
>
>
--
Jesus M. Salvo Jr.
Mobile Internet Group Pty Ltd
(formerly Softgame International Pty Ltd)
M: +61 409 126699
T: +61 2 94604777
F: +61 2 94603677
PGP Public key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xC0BA5348
Re: Namespace-aware XPath expression
Posted by Brenda Bell <b3...@theotherbell.com>.
Jesus M. Salvo Jr. wrote:
>
> I have also tried using the XPathNSResolverImpl instead of
> PrefixResolverDefault.
> I still have to specify the prefix in the xpath expression.
>
> Anyone ...help please!
I've been watching this thread from the start and believe that part of
the confusion has to do with namespaces in general -- frankly, it's one
of the most misunderstood XML concepts.
You really have to think about your source document in more concrete
terms. Namespaces are not a simple decoration -- they are a necessary
means of establishing element "ownership" and distinguishing between two
elements that may have the same name but mean entirely different things.
Just because you have a priori knowledge that there are no conflicts in
your source document doesn't mean you get to break the rules. In XPath,
you get to ask certain types of questions... one of them being "give me
element x". Asking for plain element x is asking for the element x that
is not associated with any namespace. If you want an element x that has
been associated with a namespace, you have to include the namespace when
you ask the question... not because there are conflicts in your document
but because the potential for conflicts exists in general.
That said... it would be nice if XPath processors allowed you to ask the
question "give me element x in any namespace". I'm new to Xalan, but
have worked with other parsers -- none of which support a simple syntax
for doing this. AFAIK, the only way to do this is to ask for
"/*[local-name()='x']" which is much less efficient.
Namespaces are there to help you... really!!! Don't get tied up in the
prefixes -- they are a convenience. If you get in the habit of
declaring your own prefixes for namespace URI's that you need to consume
in your program, you'll developer more robust XML applications.
Brenda
http://opensource.theotherbell.com
Re: Namespace-aware XPath expression
Posted by "Jesus M. Salvo Jr." <je...@migasia.com>.
I have also tried using the XPathNSResolverImpl instead of
PrefixResolverDefault.
I still have to specify the prefix in the xpath expression.
Anyone ...help please!
Jesus M. Salvo Jr. wrote:
>
> Hi Simon,
>
> ( Sorry if you got this more than once. Forgot to cc the list )
>
> I relalise I can do that ... but I would like NOT to specify the
> namespace in the XPath expression ( is that possible as per XPath
> specification? ).
>
> The reason is that the incoming SOAP message may have a different
> prefix for the same namespace.
> Furthermore, while PrefixResolver has a method called
> getNamespaceForPrefix(), it does not have a method called
> getPrefixForNamespace().
> If there was a method called getPrefixForNamespace()., then at least I
> could build the XPath expression by adding the prefix.
>
>
> Simon Kitching wrote:
>
>> Hi Jesus,
>>
>>
>>
>>> <mm7:SubmitReq
>>> xmlns:mm7="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2">
>>> <mm7:MM7Version>5.5.0</mm7:MM7Version>
>>> <mm7:SenderIdentification>
>>> <mm7:VASPID>MIG</mm7:VASPID>
>>> <mm7:VASID>Mig-test4</mm7:VASID>
>>> <mm7:SenderAddress>
>>> <mm7:Number>+6140955555</mm7:Number>
>>> </mm7:SenderAddress>
>>> </mm7:SenderIdentification>
>>>
>>>
>>
>>
>> Have you tried
>>
>>
>>> XPath xpath = new XPath(
>>> "//SenderIdentification/SenderAddress/Number", this.locator,
>>> resolver, XPath.SELECT );
>>>
>>
>> XPath xpath = new
>> XPath("//mm7:SenderIdentification/mm7:SenderAddress/mm7:Number", ...); ?
>>
>> Regards,
>>
>> Simon
>>
>>
>>
>>
>>
>
>
--
Jesus M. Salvo Jr.
Mobile Internet Group Pty Ltd
(formerly Softgame International Pty Ltd)
M: +61 409 126699
T: +61 2 94604777
F: +61 2 94603677
PGP Public key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xC0BA5348
Re: Namespace-aware XPath expression
Posted by "Jesus M. Salvo Jr." <je...@migasia.com>.
Hi Simon,
( Sorry if you got this more than once. Forgot to cc the list )
I relalise I can do that ... but I would like NOT to specify the
namespace in the XPath expression ( is that possible as per XPath
specification? ).
The reason is that the incoming SOAP message may have a different prefix
for the same namespace.
Furthermore, while PrefixResolver has a method called
getNamespaceForPrefix(), it does not have a method called
getPrefixForNamespace().
If there was a method called getPrefixForNamespace()., then at least I
could build the XPath expression by adding the prefix.
Simon Kitching wrote:
>Hi Jesus,
>
>
>
>><mm7:SubmitReq xmlns:mm7="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2">
>><mm7:MM7Version>5.5.0</mm7:MM7Version>
>><mm7:SenderIdentification>
>> <mm7:VASPID>MIG</mm7:VASPID>
>> <mm7:VASID>Mig-test4</mm7:VASID>
>> <mm7:SenderAddress>
>> <mm7:Number>+6140955555</mm7:Number>
>> </mm7:SenderAddress>
>></mm7:SenderIdentification>
>>
>>
>>
>
>Have you tried
>
>
>> XPath xpath = new XPath( "//SenderIdentification/SenderAddress/Number", this.locator, resolver, XPath.SELECT );
>>
>>
>XPath xpath = new
>XPath("//mm7:SenderIdentification/mm7:SenderAddress/mm7:Number", ...); ?
>
>Regards,
>
>Simon
>
>
>
>
>
--
Jesus M. Salvo Jr.
Mobile Internet Group Pty Ltd
(formerly Softgame International Pty Ltd)
M: +61 409 126699
T: +61 2 94604777
F: +61 2 94603677
PGP Public key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xC0BA5348
Re: Namespace-aware XPath expression
Posted by Simon Kitching <si...@ecnetwork.co.nz>.
Hi Jesus,
> <mm7:SubmitReq xmlns:mm7="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2">
> <mm7:MM7Version>5.5.0</mm7:MM7Version>
> <mm7:SenderIdentification>
> <mm7:VASPID>MIG</mm7:VASPID>
> <mm7:VASID>Mig-test4</mm7:VASID>
> <mm7:SenderAddress>
> <mm7:Number>+6140955555</mm7:Number>
> </mm7:SenderAddress>
> </mm7:SenderIdentification>
>
Have you tried
> XPath xpath = new XPath( "//SenderIdentification/SenderAddress/Number", this.locator, resolver, XPath.SELECT );
XPath xpath = new
XPath("//mm7:SenderIdentification/mm7:SenderAddress/mm7:Number", ...); ?
Regards,
Simon