On Thu, Nov 24, 2011 at 1:49 PM, Robert Klemme
<shortcutter / googlemail.com> wrote:
> 2011/11/24 Jes Gabriel y Gal <jgabrielygalan / gmail.com>:
>> On Thu, Nov 24, 2011 at 12:30 PM, Ruby Mania <prateek123 / gmail.com> wrote:
>>> Thanks a lot for help. But it matched CDEF and all nodes after that even
>>> if key != english
>>
>> I'm not sure why is this. I'm still trying to come up with a good
>> XPath that will return just that node,
>
> Well, there could be many matches and from the original posting I
> cannot see that only the first is needed.
>
>> but in the meantime you can do this:
>>
>> doc.xpath("//key[. = 'English']/following-sibling::topic/data")[0]
>
> Or better
>
> doc.at_xpath("//key[. = 'English']/following-sibling::topic[1]/data")
>
> I would probably do
>
> doc.xpath('//topic[preceding-sibling::key[text()="English"]]//data')
>
> or, for one hit only
>
> doc.at_xpath('//topic[preceding-sibling::key[text()="English"]][1]//data')
>
> Not sure about efficiency but I prefer it visually to have the path to
> the selected node as basis and use criteria in [] for filtering.
>
> If we want to be even more robust we could do
>
> doc.xpath('//topic[preceding-sibling::key[last() and text()="English"]]//data')
>
> This will avoid matching the topic in
>
> <key>English</key>
> ...
> <key>Foo</key>
> <topic>...
>
> or
>
> <key>English</key>
> <another>...</another>
> <topic>
>
> Kind regards
>
> robert
>
>
> PS: My favorite XPath help
> http://www.w3schools.com/xpath/default.asp
> http://www.zvon.org/xxl/XPathTutorial/General/examples.html

PPS: You can append /text() to directly get the text:

//topic[preceding-sibling::key[last() and text()="English"]]//data/text()

e.g.

doc.xpath('//topic[preceding-sibling::key[last() and
text()="English"]]//data/text()').map {|x| x.text.strip}

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/