2017-02-25 97 views
1

我試圖解析一個大的XML文件來獲取所有外部XML標籤內容,這樣的事情:如何使用SAX獲取CDATA內容

<string name="key"><![CDATA[Hey I'm a tag with & and other characters]]></string> 

得到這個:

<![CDATA[Hey I'm a tag with & and other characters]]> 

雖然,當我使用引入nokogiri的SAX XML解析器我只得到了文本而不CDATA與轉義字符,像這樣:

Hey I\'m a tag with &amp; and other characters 

這爲m y代碼:

class IDCollector < Nokogiri::XML::SAX::Document 
    def initialize 
    end 

    def characters string 
     puts string # this does not works, CDATA tag is not printed 
    end 

    def cdata_block string 
     puts string 
     puts "<![CDATA[" + string + "]]>" 
    end 
    end 

有沒有什麼辦法可以與Nokogiri SAX做到這一點?

+0

這並不完全清楚你想要做什麼:讀取或生成CDATA塊?你不會得到'<![CDATA [嘿,我是帶有&和其他字符的標籤]]>'因爲它是一個塊,而不是標籤或元素。 '<![CDATA ['實際上就是標籤,但它被處理完了,只有它的內容被返回。 http://stackoverflow.com/q/2784183可能會有所幫助。我無法重複獲取編碼結果。 –

+0

我的最終目標是將一些帶有內部內容的xml標籤移植到其他文件中。雖然,這兩個文件很大,我必須使用SAX或其他我有一個內存異常 – iGoDa

回答

1

目前還不清楚是什麼你想要做的,但這可能有助於解決問題。

A <![CDATA[...]]>條目不是標記,它是一個塊,並且由解析器對其進行不同處理。當遇到該塊時,<![CDATA[]]>被剝離,所以你只能看到裏面的字符串。有關更多信息,請參閱「What does <![CDATA[]]> in XML mean?」。

如果你想創建一個CDATA塊XML它可以很容易地使用來完成:

doc = Nokogiri::XML(%(<string name="key"></string>)) 
doc.at('string') << Nokogiri::XML::CDATA.new(Nokogiri::XML::Document.new, "Hey I'm a tag with & and other characters") 
doc.to_xml # => "<?xml version=\"1.0\"?>\n<string name=\"key\"><![CDATA[Hey I'm a tag with & and other characters]]></string>\n" 

<<只是速記創建一個子節點。

嘗試使用inner_html不會做你想做的,因爲它會創建一個文本節點作爲一個孩子:

doc = Nokogiri::XML(%(<string name="key"></string>)) 
doc.at('string').inner_html = "Hey I'm a tag with & and other characters" 
doc.to_xml # => "<?xml version=\"1.0\"?>\n<string name=\"key\">Hey I'm a tag with &amp; and other characters</string>\n" 
doc.at('string').children.first.text # => "Hey I'm a tag with & and other characters" 
doc.at('string').children.first.class # => Nokogiri::XML::Text 

使用inner_html導致出現的字符串,它是嵌入的另一種方式的HTML編碼可能包含標籤的文字。如果沒有編碼或使用CDATA,XML解析器可能會對什麼是文本與什麼是真正的標籤感到困惑。我已經撰寫了RSS聚合器,並且必須處理Feed中錯誤編碼的嵌入式HTML是一件痛苦的事情。

+0

其實我更喜歡這個(Nokogiri :: XML :: CDATA.new)我回答。另外,感謝所描述的答案,它幫助:) – iGoDa

0

過了一會兒檢查的文件,我認爲這是唯一可能通過建立一個新的CDATA內容與引入nokogiri的幫助下,像這樣:

tmp = Nokogiri::XML::Document.new 
    value = tmp.create_cdata(value) 
    r = doc.at_xpath(PATH_TO_REPLACE) 
    r.inner_html = value