XPath Umbound
November 10, 2007 7:07 AM   Subscribe

Coding help on XPath queries in WPF (I wanted to post this in the msdn forums, but they don't seem to be responding right now)

I have a WPF user control bound to an rss feed. The feed, in part, looks like this (irrelevant stuff replaced with "..."):

<rss ...>
<channel>
...
<yweather:units temperature="F" distance="mi" pressure="in" speed="mph" />
<:yweather:wind chill="61" direction="0" speed="0" />
...
</channel>
</rss>

So based on this data, I would say that the wind speed is 0 mph (the @speed attribute of yweather:wind plus the speed attribute of yweather:units);

I have two TextBlock elements, one of which I need to bind to the yweather:wind @speed attribute and the other to the yweather:units @speed attribute.

binding to XPath=//@speed[1] returns the expected value of "mph". Binding to XPath=//@speed[2] returns nothing. Binding to XPath=//@speed[last()] returns "mph". This tells me that the second @speed attribute is not being seen.

Can anyone point me in the right direction on how to bind to that second attribute?
posted by Lokheed to Computers & Internet (7 answers total)
 
Even if what you want to do worked, what would happen if the weather service started tracking waves too?

<yweather:units temperature="F" distance="mi" pressure="in" speed="mph" height="feet"/>
<:yweather:wave height="6" direction="45" speed="3" />
<:yweather:wind chill="61" direction="0" speed="0" />
posted by orthogonality at 7:15 AM on November 10, 2007


Try (untested):

XPath=//yweather:wind[@speed]

Or better and more specifically,

XPath=/rss/channel/yweather:wind[@speed]

That'll get you the node; how you bind to the node's attribute value in WPF is something you'll figure out.
posted by orthogonality at 7:33 AM on November 10, 2007


Best answer: I don't know WPF, but I know XPath, and //@speed[1] should return the sequence of all attribute nodes named "speed". The unabbreviated form is /descendent-or-self::node()/attribute::speed[position() = 1], so it returns all first speed attributes -- and, since attribute names are unique, it will always return all attributes. //@speed[last()] will do the same thing, and //@speed[2] will always return nothing, since you can't have a second attribute with the same name on the same element.

To pick up each individual value, use //yweather:units/@speed and //yweather:wind/@speed. If those aren't working for you, check your namespaces -- the namespace URI for yweather has to match, and the attibute should be in the no namespace.

If you're just debugging, (//@speed)[2] will give you the second "speed" attribute in the entire document, which may or may not be the one you're looking for.
posted by backupjesus at 12:05 PM on November 10, 2007


Response by poster: I knew the problem had to be me misunderstanding the syntax. Following the suggestions above, I have found that:

- binding to //yweather:wind[@speed] returns nothing

- binding to //yweather:wind/@speed returns nothing

- binding to (//@speed)[2] returns the desired value, but will break if the order of the elements ever changes in the feed.

- I also tried binding to //yweather:wind/@speed[1] and it returned nothing as well.

This means that the only one I have found that "works" is the one that is most likely to break in the future. I'll keep watching here for more suggestions, and I will try over at the msdn forum to see if there is some microsoft weirdness when it comes to wpf, xpath and binding.
posted by Lokheed at 1:54 PM on November 10, 2007


Response by poster: Aha! The warning about namespaces from backupjesus was dead on. Although the rss feed declared the yweather namespace, it turns out that in wpf I also had to do a couple of things. Under <userControl.Resources> I had to declare an XmlNamespaceMappingCollection and then within that declare the XmlNamespaceMapping for yweather (and also geo for another part of the feed). Then in the binding of the control itself I had to set the Binding.XmlNamespaceManager to point to that XmlNamespaceMappingCollection. As soon as I did that the values started binding properly.

Thanks everyone!
posted by Lokheed at 2:28 PM on November 10, 2007


Just curious: does //yweather:wind return anything? If it does, it's something funky with the attribute handling, but you should at least be able to look at the returned element node and figured out what's going on. If it returns nothing, it points to a namespace mismatch.
posted by backupjesus at 2:29 PM on November 10, 2007


Ah, I shoulda previewed. Glad to see it worked out.
posted by backupjesus at 2:30 PM on November 10, 2007


« Older Web fun for 3 to 4 year olds   |   My dentist is expenive enough... Newer »
This thread is closed to new comments.