2017-02-25 53 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