XML и анализаторы на самом деле не имеют понятия номеров строк. Вы говорите о физической структуре файла.
Вы можете играть в игру с анализатором, используя средства доступа, ищущие текстовые узлы, содержащие переводы строк и / или возврат каретки, но которые можно отбросить, поскольку XML допускает вложенные узлы.
require 'nokogiri'
xml =<<EOT_XML
<atag>
<btag>
<ctag
id="another_node">
other text
</ctag>
</btag>
<btag>
<ctag id="another_node2">yet
another
text</ctag>
</btag>
<btag>
<ctag id="this_node">this text</ctag>
</btag>
</atag>
EOT_XML
doc = Nokogiri::XML(xml)
# find a particular node via CSS accessor
doc.at('ctag#this_node').text # => "this text"
# count how many "lines" there are in the document
doc.search('*/text()').select{ |t| t.text[/[\r\n]/] }.size # => 12
# walk the nodes looking for a particular string, counting lines as you go
content_at = []
doc.search('*/text()').each do |n|
content_at << [n.line, n.text] if (n.text['this text'])
end
content_at # => [[14, "this text"]]
Это работает из-за способности синтаксического анализатора выяснить, что такое текстовый узел, и безошибочно возвращать его, не полагаясь на регулярные выражения или совпадения текста.
РЕДАКТИРОВАТЬ: Я просмотрел какой-то старый код, пролистал некоторые из документов Нокогири и внес изменения, которые были отредактированы выше. Он работает правильно, включая работу с некоторыми патологическими случаями. Нокогири FTW!