2011-06-22 59 views
1

請考慮使用Nokogiri構建的以下SAX解析器。Nokogiri and Encoding

#encoding: UTF-8 

require 'nokogiri' 

class MyParser < Nokogiri::XML::SAX::Document 

    def initialize(&callback) 
    @callback = callback 
    @buffer = "" 
    @parser = Nokogiri::XML::SAX::PushParser.new(self, "UTF-8") 
    @elem = nil 
    @doc ||= Nokogiri::XML::Document.new 
    super() 
    end 

    def push(data) 
    @parser << data 
    end 

    def start_element(name, attributes = []) 
    @elem = Nokogiri::XML::Element.new(name, @doc) 
    attributes.each do |k, v| 
     @elem.set_attribute(k, v) 
    end 
    end 

    def end_element(name) 
    clear_characters_buffer 
    @callback.call(@elem) 
    end 

    def clear_characters_buffer 
    if @buffer && @elem 
     @buffer.strip! 
     @elem.add_child(Nokogiri::XML::Text.new(@buffer, @doc)) unless @buffer.empty? 
     @buffer = nil # empty the buffer 
    end 
    end 

    def characters(string) 
    @buffer ||= "" 
    @buffer << string 
    end 

end 


xml =<<-EOXML 
<entry> 
<title>Appel à témoins pour émission de TV sur les jobs d'été</title> 
<summary type="text">Je laisse la parole à Caroline, journaliste, qui recherche des étudiants pour une émission sur les jobs d'été à la rentrée.</summary> 
<link rel="alternate" type="text/html" href="http://www.jobetudiant.net/blog/index.php?2011/04/29/573-appel-tmoins-pour-mission-de-tv-sur-les-jobs-d-t" title="Appel à témoins pour émission de TV sur les jobs d'été"/> 
EOXML 

p = MyParser.new() do |node| 
    puts node.to_xml(:encoding => "UTF-8") 
end 

p.push(xml) 

## 
# Output : 
## 
# $ ruby encoding-bug.rb 
# <title>Appel à témoins pour émission de TV sur les jobs d'été</title> 
# <summary type="text">Je laisse la parole à Caroline, journaliste, qui recherche des étudiants pour une émission sur les jobs d'été à la rentrée.</summary> 
# <link rel="alternate" type="text/html" href="http://www.jobetudiant.net/blog/index.php?2011/04/29/573-appel-tmoins-pour-mission-de-tv-sur-les-jobs-d-t" title="Appel &#xE0; t&#xE9;moins pour &#xE9;mission de TV sur les jobs d'&#xE9;t&#xE9;"/> 

## 
# Expected : 
## 
# $ ruby encoding-bug.rb 
# <title>Appel à témoins pour émission de TV sur les jobs d'été</title> 
# <summary type="text">Je laisse la parole à Caroline, journaliste, qui recherche des étudiants pour une émission sur les jobs d'été à la rentrée.</summary> 
# <link rel="alternate" type="text/html" href="http://www.jobetudiant.net/blog/index.php?2011/04/29/573-appel-tmoins-pour-mission-de-tv-sur-les-jobs-d-t" title="Appel à témoins pour émission de TV sur les jobs d'été"/> 

正如你所看到的,它是一個UTF8字符串。 SAX解析器在用正確的字符串發射正確的事件方面做得很好,但是當我嘗試再次將它放在文檔中時,出於某種原因,它不會正確地序列化屬性,通過將它們重新編碼爲UTF- 8。任何人都知道發生了什麼?

回答

0

它是HTML轉義屬性值。如果你改變你的例子來

xml =<<-EOXML 
<entry title="jobs d'été"> 
jobs d'été 
</entry> 
EOXML 

它更清晰:

<entry title="jobs d'&#xE9;t&#xE9;">jobs d'été</entry> 

你可以將它們轉換回到這樣

require 'cgi' 
p = MyParser.new() do |node| 
    puts CGI.unescapeHTML(node.to_xml(:encoding => "UTF-8")) 
end 

這給

<entry title="jobs d'été">jobs d'été</entry>