2013-08-01 23 views
3

我對Ruby非常陌生,嘗試使用REXML解析XML文檔,該文檔之前已經很漂亮(通過REXML)打印,但結果稍微不穩定。爲什麼REXML不能解析CDATA前面有換行符?

某些CDATA節在打開XML標記後但在打開CDATA塊之前有換行符,在這些情況下,REXML會將標記的文本解析爲空。

  • 任何想法,如果我可以得到REXML閱讀這些行?
  • 如果沒有,我可以用正則表達式或其他東西重寫它們嗎?
  • 這是否甚至是有效的XML?

下面是一個示例XML文檔(多刪節):

<?xml version="1.0" encoding="utf-8"?> 
<root-tag> 
    <content type="base64"><![CDATA[V2VsbCBkb25lISBJdCB3b3JrcyA6KQ==]]></content> 
    <content type="base64"> 
     <![CDATA[VGhpcyB3b250IHdvcms=]]></content> 

    <content><![CDATA[This will work]]></content> 
    <content> 
     <![CDATA[This will not appear]]></content> 

    <content> 
     Seems happy</content> 
    <content>Obviously no problem</content> 
</root-tag> 

,這裏是我的Ruby腳本(蒸餾至最小的例子):

require 'rexml/document' 
require 'base64' 
include REXML 

module RexmlSpike 
    file = File.new("ex.xml") 
    doc = Document.new file 
    doc.elements.each("root-tag/content") do |contentElement| 
    if contentElement.attributes["type"] == "base64" 
     puts "decoded: " << Base64.decode64(contentElement.text) 
    else 
     puts "raw: " << contentElement.text 
    end 
    end 
    puts "Finished." 
end 

我得到的輸出是:

>> ruby spike.rb 
    decoded: Well done! It works :) 
    decoded: 
    raw: This will work 
    raw: 

    raw: 
      Seems happy 
    raw: Obviously no problem 
    Finished. 

我在OSX Lion上使用Ruby 1.9.3p392。練習的目的是最終將一些BlogML的註釋解析爲Disqus使用的自定義導入XML。

回答

4

爲什麼

具有<![CDATA[]]>覆蓋無論是在<![CDATA[]]>什麼。從信件到新行(如你發現的)或單個空間。這是有道理的,因爲你的例子是獲取元素的text,並且空白作爲文本計數。在您可以訪問<![CDATA[]]>的示例中,這是因爲文本爲零。


解決方案

如果你看一下documentation for Element,你會看到它有一個名爲cdatas()功能:

獲取中的所有CDATA兒童的數組。不可改變的。

因此,在您的示例中,如果您在contentElement.cdatas()上執行內部循環,則會看到所有缺失標籤的內容。

3

我建議使用Nokogiri,這是Ruby的事實上的XML/HTML解析器。用它來訪問<content>標籤的內容,我得到:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0" encoding="utf-8"?> 
<root-tag> 
    <content type="base64"><![CDATA[V2VsbCBkb25lISBJdCB3b3JrcyA6KQ==]]></content> 
    <content type="base64"> 
     <![CDATA[VGhpcyB3b250IHdvcms=]]></content> 

    <content><![CDATA[This will work]]></content> 
    <content> 
     <![CDATA[This will not appear]]></content> 

    <content> 
     Seems happy</content> 
    <content>Obviously no problem</content> 
</root-tag> 
EOT 

doc.search('content').each do |n| 
    puts n.content 
end 

,輸出:

V2VsbCBkb25lISBJdCB3b3JrcyA6KQ== 

     VGhpcyB3b250IHdvcms= 
This will work 

     This will not appear 

     Seems happy 
Obviously no problem 
+0

謝謝 - 我想我可能會嘗試Nokogiri,它聽起來好像更好,但它並沒有真正回答原來的問題,所以我會留下來看看是否有人知道答案。 –

+0

這並沒有回答這個問題,也沒有正確解釋爲什麼他應該使用nokogiri而不是REXML – fotanus

+0

他應該使用Nokogiri,如果他想解析XML而沒有他使用REXML遇到的麻煩。建議OP使用JSON而不是XML使它們比Nokogiri和REXML更遠。 –

2

您的xml是有效的,但不像您期望的那樣,正如@ lightswitch05指出的那樣。你可以,如果你正在使用XML從野生世界網站使用

,它是利用引入nokogiri,因爲它通常工作作爲一個好主意,你認爲它應該,還不如說真的應該。注意:這正是我爲什麼避免使用XML並使用JSON的原因:XML有一個合適的定義,但似乎沒有人使用它。

+0

Nokogiri和rexml有趣的比較。不幸的是,當在兩個第三方系統之間移植數據時,你不能選擇那些數據看起來像什麼,我們只需要嘗試使用它。 –

+0

@AndrewM是的,很多時候我都無法選擇,這就是我意識到的。快樂的黑客攻擊。 – fotanus