我正在尝试编写一个Nokogiri脚本,它将为包含ASCII双引号(«“»)的文本节点grep XML。由于我想要类似grep的输出,我需要行号,以及每行的内容但是,我无法看到如何分辨元素起始处的行号。这是我的代码:
require 'rubygems'
require 'nokogiri'
ARGV.each do |filename|
xml_stream = File.open(filename)
reader = Nokogiri::XML::Reader(xml_stream)
titles = []
text = ''
grab_text = false
reader.each do |elem|
if elem.node_type == Nokogiri::XML::Node::TEXT_NODE
data = elem.value
lines = data.split(/\n/, -1);
lines.each_with_index do |line, idx|
if (line =~ /"/) then
STDOUT.printf "%s:%d:%s\n", filename, elem.line()+idx, line
end
end
end
end
end
elem.line()不起作用。
答案 0 :(得分:4)
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"]]
这是有效的,因为解析器能够找出什么是文本节点并干净地返回它,而不依赖于正则表达式或文本匹配。