- 更新日: 2015年6月19日
- Rails
Ruby/RailsでXML中の不正な制御文字を削除する
Rails で ActiveRecord と ActionView::Helpers::AtomFeedHelper を使って、データベースの中身からデータを引っ張って Atom フィードを出力するコードを書いていたら問題発生。DBから引っ張ってきたデータ中に制御文字が含まれていて、出力された Atom フィードの CDATA セクションにその制御文字が入り込み、XML 書式が不正なものとなってしまいました。
— 環境 —
Rails 4.1
XML1.0 で不正になる制御文字
ということでまずは、XML 中で invalid となる文字について XML の仕様書(RFC)に当たって調べました。
The characters to be escaped are the control characters #x0 to #x1F and #x7F (most of which cannot appear in XML), space #x20, the delimiters ‘<' #x3C, '>‘ #x3E and ‘”‘ #x22, the unwise characters ‘{‘ #x7B, ‘}’ #x7D, ‘|’ #x7C, ‘\’ #x5C, ‘^’ #x5E and ‘`’ #x60, as well as all characters above #x7F.
上記 W3C のページは、「Note: On 7 February 2013, this specification was modified in place to replace broken links to RFC4646 and RFC4647.」とあるので、リンクが壊れた RFC4646, 4647 の内容の代わりに設置された XML1.0 の仕様だろうと思われます。
引用した部分に XML 中でエスケープすべき制御文字コードがずらずらっと書いてある。
以下のエントリーなども参考になりました。
XML1.0にvalidな文字列の出力 – memo.mzt
PHPでのXMLパースエラー出力は必須だね – 今からお前んちこいよ
PHP で simplexml_load_string() を使って RSS フィードをパースすると、RSS フィードに制御文字が入っていた場合エラーになるらしい。困ったもんだ…
text.gsub(/[[:cntrl:]]/, ”) で対応
stackoverflow の以下ページ等を参考にして対処しました。
Ruby regex remove ^C character from string – Stack Overflow
Invalid Characters in XML – Stack Overflow
少々乱暴なやり方っぽくも感じるけど、出力の際に Ruby の String#gsub メソッドを使って、正規表現指定で制御文字を全部空文字に置換する方法をとりあえず試してみた。
views/users/posts.atom.builder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
atom_feed do |feed| feed.title("User's posts") feed.updated((@posts.first.created_at)) @posts.each do |post| feed.entry( post, url: post_path(post.id) ) do |entry| entry.title do entry.cdata!( post.title.gsub(/[[:cntrl:]]/, '') ) end entry.content( type: "html", "xml:lang" => "ja" ) do entry.cdata!( post.content.gsub(/[[:cntrl:]]/, '') ) end end end end |
これで一応出力される Atom フィードの XML が valid なものとなり、上手く動作しました。このやり方で問題が出たら、また対処しようと思います。最後に Rails で RSS/Atom フィードを作成する方法については以下参考。
RailsでAtomフィードを生成 | EasyRamble
RailsでRSSフィードを生成 | EasyRamble
- Rails の関連記事
- RailsでMySQLパーティショニングのマイグレーション
- Rails ActiveRecordでdatetime型カラムのGROUP BY集計にタイムゾーンを考慮する
- RailsプラグインGemの作成方法、RSpecテストまで含めたrails pluginの作り方
- RailsでAMPに対応するgemをリリースしました
- Railsでrequest.urlとrequest.original_urlの違い
- Railsでwheneverによるcronバッチ処理
- Google AnalyticsのRails Turbolinks対応
- Railsアプリにソーシャル・シェアボタンを簡単設置
- Rails監視ツール用にErrbitをHerokuで運用
- Facebook APIバージョンのアップグレード手順(Rails OmniAuth)
Leave Your Message!