如何在Ruby中呈现XML字符实体引用?

时间:2011-03-10 16:00:00

标签: ruby xml

我正在使用Ruby从XML Web服务中读取一些数据,如下所示:

<phrases>
  <phrase language="en_US">&iexcl;I&#39;m highly&nbsp;annoyed with character references!</phrase>
</phrases>

我正在解析XML并抓取一系列短语。如您所见,短语text包含一些XML character entity references。我想用引用的实际字符替换它们。这对于数字引用来说很简单,但对于XML和HTML却很讨厌。我想避免在我的代码中有一个大哈希,它包含每个XML或HTML字符引用的字符,即http://www.java2s.com/Code/Java/XML/Resolvesanentityreferenceorcharacterreferencetoitsvalue.htm

肯定有一个图书馆,对吧​​?

更新

是的,那里有一个图书馆,名为HTMLEntities

: jmglov@laurana; sudo gem install htmlentities
Successfully installed htmlentities-4.2.4
: jmglov@laurana;  irb
irb(main):001:0> require 'htmlentities'
=> []
irb(main):002:0> HTMLEntities.new.decode "&iexcl;I&#39;m highly&nbsp;annoyed with character references!"
=> "¡I'm highly annoyed with character references!"

2 个答案:

答案 0 :(得分:2)

REXML可以做到,但它不会处理“&amp; iexcl;”或“&amp; nbsp;”。预定义的XML实体列表(除了Unicode数字实体)实际上非常小。见http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references

鉴于此输入XML:

<phrases>
  <phrase language="en_US">&quot;I&#39;m highly annoyed with character references!&#x00a9;</phrase>
</phrases>

你可以像这样解析XML和嵌入式实体(例如):

require 'rexml/document'

doc = REXML::Document.new(File.open('/tmp/foo.xml').readlines.join(''))
phrase = REXML::XPath.first(doc, '//phrases/phrase')
text = phrase.first # Type is REXML::Text
puts(text.value)

显然,该示例假定XML位于文件/tmp/foo.xml中。您可以轻松传递一串XML。在我的Mac和Ubuntu系统上,运行它会产生:

$ ruby /tmp/foo.rb
"I'm highly annoyed with character references!©

答案 1 :(得分:1)

这不是尝试提供解决方案,而是涉及我自己处理XML的一些经验。我最初使用Perl,然后使用Ruby,如果你获得足够的XML或RDF / RSS / Atom提要,你可以轻松地遇到这些经验。

我经常看到XML CDATA包含HTML,包括编码和未编码的HTML。编码的HTML可能是某人以正确的方式做事的结果,通过一些API或库来生成XML。未编码的HTML可能是使用脚本用标签包装HTML的人,导致XML无效,但无论如何我都必须处理它。

我还看到包含多次编码的HTML的XML CDATA,要求我对所有内容进行解码,即使在XML引擎完成之后也是如此。有时在中间传递过程中,我会突然在字符串中包含非UTF8字符以及编码字符,因为有人会添加注释或将多个HTML流连接在一起,这些HTML流来自不同的字符集。无论出于何种原因,它都非常难看,导致XML解析中断或发出大量警告。我必须遍历内容,解码和检查以查看前一个传递是否与当前解码传递相同,并且如果没有任何更改则退出。虽然不能保证我当时在一个有效的字符集中有一个字符串,所以我必须告诉iconv将它转换为UTF8并丢弃不能完全转换的字符。

Nokogiri可以通过创造性地使用to_xmlto_html方法,以各种方式解码节点的内容。您还可以查看HTMLEntities gem,Loofah和其他人来查看CDATA内容。丝瓜络很好,因为它的设计可能会遇到白名单/黑名单标签。

XML规范应该保护我们免受这些恶作剧的影响,但是,正如我的一位同事曾经告诉我的那样,“我们可以让它变得万无一失,但不能傻瓜式”。人们是如此富有创造力,对于那些懒得阅读或不关心的人来说,这些规格毫无意义。