ラベル rfc の投稿を表示しています。 すべての投稿を表示
ラベル rfc の投稿を表示しています。 すべての投稿を表示

2009年7月28日火曜日

PHPの URLエンコード (urlencode, rawurlencode, http_build_query)

(2013/5/19 変更:rawurlencode()はRFC3986なのにRFC1738と書いてたので訂正。)


まずはurlencode()rawurlencode()を比較。

  • urlencode()
    • 半角チルダ(~)を%7Eに変換する
    • 半角スペースをプラス(+)に変換する
  • rawurlencode()
    • 半角チルダ(~)の変換についてはPHPのバージョンによって違う
      • PHP 5.2.xまでは、%7Eに変換する
      • PHP 5.3.0からは、%7Eに変換しない(チルダのまま)
    • 半角スペースを%20に変換する

rawurlencode()はRFC1738 RFC3986に沿った変換とされているので、基本的にはurlencode()よりrawurlencode()の方が無難。
ただし、RFC1738 3986ではチルダを%7Eに変換しない。


ちなみに、RFC1738はその後、RFC3986によって更新されているが、RFC3986はパッと見た感じではURLエンコードについては(JavaScriptのencodeURIComponent()で使われるRFC2396の方ではなく、)RFC1738を踏襲しているようだ。(2013/5/19 追記:一部変更されてる。)

Amazonの新しいAPIでも、RFC3986によるURLエンコードを使っている。(参考:Amazon Product Advertising API への対応(PHP版) - もやし日記



次に、http_build_query()の話。
http_build_query()は便利だが、URLエンコードの内容はurlencode()と同じなのが残念。
RFC1738/3986に沿った形にするには、もう1つ変換を咬ませなければならない。
//例
function encodeAlongRFC1738($str) {
return strtr($str, array('%7E' => '~', '+' => '%20'));
}

echo encodeAlongRFC1738(http_build_query($arr));
上記の変換は、PHP5.2までのrawurlencode()にも使える。



あとは実験結果。上記のencodeAlongRFC1738()も交えて。
元の文字
 "~_ _+"

urlencode()の場合
変換結果
 "%7E_+_%2B"
urldecode()すると
 "~_ _+"
rawurldecode()すると(正しくデコードできない)
 "~_+_+"

rawurlencode()の場合(PHP 5.2)
変換結果
 "%7E_%20_%2B"
urldecode()すると
 "~_ _+"
rawurldecode()すると
 "~_ _+"

rawurlencode()の場合(PHP 5.3)
変換結果
 "~_%20_%2B"
urldecode()すると
 "~_ _+"
rawurldecode()すると
 "~_ _+"


urlencode() + encodeAlongRFC1738()の場合
変換結果
 "~_%20_%2B"
urldecode()すると
 "~_ _+"
rawurldecode()すると
 "~_ _+"


元の配列
 array("test[0]" => "~_ _+")

http_build_query()の場合
変換結果
 "test%5B0%5D=%7E_+_%2B"
urldecode()すると
 "test[0]=~_ _+"
rawurldecode()すると(正しくデコードできない)
 "test[0]=~_+_+"

http_build_query() + encodeAlongRFC1738()の場合
変換結果

 "test%5B0%5D=~_%20_%2B"
urldecode()すると
 "test[0]=~_ _+"
rawurldecode()すると
 "test[0]=~_ _+"

urldecode()はurlencode()に対してもrawurlencode()に対しても使える。



参考:URIに使ってよい文字の話 - RFC2396 と RFC3986 - Text::Easyhacking

2007年12月16日日曜日

RSS/AtomフィードのXMLの作り方メモ

とりあえず、必要最小限の要素だけを作る方法のメモ。


RSS1.0
シンプルなRSSの全体に、Dublin Coreモジュールのdateを加える。
各itemのdescriptionにはエスケープしたhtmlを入れられる。

<?xml version="1.0" encoding="utf-8" ?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/"
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xml:lang="ja">

 <channel rdf:about="http://example.com/rss1.rdf">
  <title>RSS1.0 Test</title>
  <link>http://example.com</link>
  <description>RSS1.0のテスト</description>
  <items>
   <rdf:Seq>
    <rdf:li rdf:resource="http://example.com/page1"/>
    <rdf:li rdf:resource="http://example.com/page2"/>
   </rdf:Seq>
  </items>
 </channel>

 <item rdf:about="http://example.com/page1">
  <title>ページ1</title>
  <link>http://example.com/page1</link>
  <description>1つ目のページ</description>
  <dc:date>2007-01-01T00:00:00+09:00</dc:date>
 </item>

 <item rdf:about="http://example.com/page2">
  <title>ページ2</title>
  <link>http://example.com/page2</link>
  <description>2つ目のページ</description>
  <dc:date>2007-01-02T03:04:05+09:00</dc:date>
 </item>
</rdf:RDF>


RSS2.0
▽PHP4でRSS配信プログラム xmlファイルの作成からlastBuildDateを削除し、各itemにdescriptionを追加する。
(lastBuildDateはあったほうがよい?)
docs要素はなくてもいいが、せっかくなので付けておく?
他のフィードと違い、日付はRFC2822形式(例:Sun, 05 Nov 2006 16:53:33 +0900)。
フィード自体のURLを示す箇所が無い。
各itemのdescriptionにはエスケープしたhtmlを入れられる。
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0">
 <channel>

  <title>RSS2.0 Test</title>
  <link>http://example.com</link>
  <description>RSS2.0のテスト</description>
  <language>ja</language>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>

  <item>
   <title>ページ1</title>
   <link>http://example.com/page1</link>
   <description>1つ目のページ</description>
   <pubDate>Mon, 01 Jan 2007 00:00:00 +0900</pubDate>
  </item>

  <item>
   <title>ページ2</title>
   <link>http://example.com/page2</link>
   <description>2つ目のページ</description>
   <pubDate>Tue, 02 Jan 2007 03:04:05 +0900</pubDate>
  </item>

 </channel>
</rss>


Atom0.3
2章 Atomフォーマット - The Atom Syndication Formatの"Atomフォーマットの構成"からフィード全体の日時(modefied)を削除し、各entryにsummaryを追加する。
xml:lang属性もfeed要素あたりに付けておく。
Atom1.0とは違い、フィード全体のidは必須ではない。
フィード自体のURLを示す箇所が無い。
各entryの2つの日時(issued、modefied)は必須。
各entryのidについてはAtom1.0と同様。
ベタなテキストでなくhtmlを入れたいなら、summaryの代わりにcontent要素を使う。
<?xml version="1.0" encoding="utf-8" ?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xml:lang="ja">

 <title>Atom feed 0.3 Test</title>
 <link rel="alternate" type="text/html" href="http://example.com"/>
 <author>
  <name>ぼく</name>
 </author>

 <entry>
  <title>ページ1</title>
  <link rel="alternate" type="text/html" href="http://example.com/page1"/>
  <id>http://example.com/page1</id>
  <modified>2007-01-02T00:00:00+09:00</modified>
  <issued>2007-01-01T00:00:00+09:00</issued>
  <summary>1つ目のページ</summary>
 </entry>

 <entry>
  <title>ページ2</title>
  <link rel="alternate" type="text/html" href="http://example.com/page2"/>
  <id>http://example.com/page2</id>
  <modified>2007-01-02T03:04:05+09:00</modified>
  <issued>2007-01-02T03:04:05+09:00</issued>
  <summary>2つ目のページ</summary>
 </entry>

</feed>



Atom1.0
簡単なAtomフィード文書を元にする。
xml:lang属性もfeed要素あたりに付けておく。
feedおよび各entryのid要素は"永久的で完全に一意的な識別子"なので、手軽に済ますならfeedやentryを一意に示すURLでよいと思う。
パーマリンクは一意と言えないという意見もある。それが理由かは分からないがAtomの基本的なフィードの例ではurlのtagスキームを、簡単なAtomフィード文書のサンプルではurnを使っている。)
feed全体のupdated日時が必須。
linkでrel属性を指定しないとrel="alternate"とみなされる。
summaryとcontentについてはAtom0.3と同様。
フィードリーダーによってはAtom1.0は対応していないので注意が必要。(他のフィードと併用するなど。)
<?xml version="1.0" encoding="utf-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">

 <title>Atom feed 1.0 Test</title>
 <link href="http://example.com"/>
 <link rel="self" href="http://example.com/atom1.xml"/>
 <author>
  <name>ぼく</name>
 </author>
 <updated>2007-12-12T14:20:37+09:00</updated>
 <id>http://example.com/atom1.xml</id>

 <entry>
  <title>ページ1</title>
  <link href="http://example.com/page1"/>
  <summary>1つ目のページ</summary>
  <updated>2007-01-01T00:00:00+09:00</updated>
  <id>http://example.com/page1</id>
 </entry>

 <entry>
  <title>ページ2</title>
  <link href="http://example.com/page2"/>
  <summary>2つ目のページ</summary>
  <updated>2007-01-02T03:04:05+09:00</updated>
  <id>http://example.com/page2</id>
 </entry>

</feed>



補足:日付のタイムゾーンについて
フィードリーダーによっては、タイムゾーンが正しく読めない? UTC (例:2005-11-16T02:27Z)で配信する?


関連記事: RSS/Atomフィードを生成したりSitemapを作成するPHPライブラリ


参考:
RSS1.0
 RSS(RDF Site Summary)によるサイト情報の要約と公開 (RSS1.0についての解説)
 RDF Site Summary (RSS) 1.0 (RSS1.0仕様書の和訳)
RSS2.0
 RSS 2.0 Notes (RSS2.0仕様書を元にした解説)
 RSS 2.0 Specification 日本語訳 - futomi's CGI Cafe (RSS2.0仕様書の和訳)
 ホームページ作成 / Yaskey Diary (RSS2.0のシンプルな例)
Atom0.3
 2章 Atomフォーマット - The Atom Syndication Format (Atom0.3仕様書の和訳)
Atom1.0
 Atom - RSS改訂の試み (Atom1.0についての解説)
 RFC 4287 The Atom Syndication Format 日本語訳 - futomi's CGI Cafe (Atom1.0仕様書の和訳)
 An overview of the Atom 1.0 Syndication Format (Atom1.0の解説)
その他
 Web標準の日時の形式 | Web::Blogoscope (日付形式について)
 RSS1.0とRSS2.0 - fox.tech - by fox_b (RSS仕様の分裂について)

ブログ アーカイブ

tags