tags:

views:

77

answers:

4

I'm new to using XPath so I've been fooling around with an XPath Evaluator and I'm trying to find out how to return the value of a function.

If I want to return the hrefs of all the links on a page I can use the following XPath:

//a/@href

If I want to return all the links with hrefs longer than 20 chars I can use this:

//a[string-length(@href) > 20]

What I can't figure out is how do I get just the lengths of all hrefs? My naive assumption was that this should do it:

//a/string-length(@href)

But it fails (as do all the variations I could think of).

How can this be done?


After digging in a bit further I saw that the XPath Evaluator I was using hard-coded XPathResult.ORDERED_NODE_SNAPSHOT_TYPE as the result type, when I changed it to ANY_TYPE (0) the following worked for getting the length of one link (which is what I actually need)

string-length((//a)[1]/@href)
+1  A: 

XPath is primarily designed to select nodes not to return a scalar value. The existance of scalar function in XPath assists in the creating of predicate conditions and can be used in XSLT to supply output values. However most DOM implementations that support XPath only support the return of selected node(s).

AnthonyWJones
Especially string-length is easily determinable in the "outside" environment...
Tomalak
A: 

You can't. Functions are there to further specify the nodes you want (i.e. I want all tt-nodes that have more than 3 attributes.) But since xpath queries return node objects in general, you can poll their properties in the language you're using xpath in.

soulmerge
A: 

You'll need to loop through the results of //a[string-length(@href) > 20], how depends entirely on which language you plan on using the query from.

Rowan Lewis
+1  A: 

You are trying to find the length of multiple strings. I can think of two ways that might work:

Try putting the function outside of the query path. Right now I'm guessing it fails because you are saying "go to this node" and part of the node is a function. Try this instead:

 string-length(//a/@href)

But I still don't think you will get what you want, which is the length of each URL. I could be wrong, but just in case, you may want to consider finding all hrefs first, then looping through the results and using the function to get the lengths of each one. Something like

urls = //a/@href

foreach (urls as url) {
   if (string-length(url) > 20) 
        ....blah blah blah....
 }

You are probably trying to avoid looping, but getting all hrefs and then using a conditional may be almost as effective.

Anthony
I tried your first suggestion (as part of the *all the variations I could think of*) and it didn't work.
Motti
Based on the other answers, I figured it wouldn't. Sorry. I wasn't sure if placing the function outside of the query was one of your many variations, so I figured it might be one of those "oh duh" kind of things. Out of curiosity, which language are you using XPath with eventually? PHP should be really easy to implement a looping function using the simplexml extension.
Anthony