Саксофон Парсинг странный элемент с нокогири - PullRequest
1 голос
/ 03 апреля 2012

Я хочу выполнить синтаксический анализ в nokogiri, но когда дело доходит до синтаксического анализа элемента xml с длинным и сумасшедшим именем элемента xml или атрибутом ... тогда все сводится с ума.

Например, если мне нравится анализировать этот xml-файл и захватывать все элементы заголовка, как мне это сделать с помощью nokogiri-sax.

<titles>
    <title xml:lang="sv">Arkivvetenskap</title>
    <title xml:lang="en">Archival science</title>
</titles>

1 Ответ

4 голосов
/ 03 апреля 2012

В вашем примере title - это имя элемента.xml:lang="sv" является атрибутом.Этот синтаксический анализатор предполагает, что нет элементов, вложенных в элементы заголовка

require 'rubygems'
require 'nokogiri'

class MyDocument < Nokogiri::XML::SAX::Document
  def start_element(name, attrs)
    @attrs = attrs
    @content = ''
  end
  def end_element(name)
    if name == 'title'
      puts Hash[@attrs]['xml:lang']
      puts @content.inspect
      @content = nil
    end
  end
  def characters(string)
    @content << string if @content
  end
  def cdata_block(string)
    characters(string)
  end
end

parser = Nokogiri::XML::SAX::Parser.new(MyDocument.new)
parser.parse(DATA)

__END__
<titles>
    <title xml:lang="sv">Arkivvetenskap</title>
    <title xml:lang="en">Archival science</title>
</titles>

Это печатает

sv
"Arkivvetenskap"
en
"Archival science"

SAX-анализ обычно слишком сложен.Поэтому я рекомендую стандартный парсер Nokogiri в памяти, или, если вам действительно нужна скорость и эффективность памяти, Парсер Nokogiri's Reader .

Для сравнения, вотстандартный синтаксический анализатор Нокогири для того же документа

require 'rubygems'
require 'nokogiri'

doc = Nokogiri::XML(DATA)
doc.css('title').each do |title|
  puts title['lang']
  puts title.text.to_s.inspect
end

__END__
<titles>
    <title xml:lang="sv">Arkivvetenskap</title>
    <title xml:lang="en">Archival science</title>
</titles>

А вот парсер чтения для того же документа

require 'rubygems'
require 'nokogiri'

reader = Nokogiri::XML::Reader(DATA)
while reader.read
  if reader.name == 'title' && reader.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
    puts reader.attribute('xml:lang')
    puts reader.inner_xml.inspect # TODO xml decode this, if necessary.
  end
end

__END__
<titles>
    <title xml:lang="sv">Arkivvetenskap</title>
    <title xml:lang="en">Archival science</title>
</titles>
...