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/