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