<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns="http://purl.org/rss/1.0/"
 xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:admin="http://webns.net/mvcb/"
>
<channel rdf:about="http://driveool.livedoor.biz/">
<title>mylog</title>
<link>http://driveool.livedoor.biz/</link>
<description>Sabel: Open-Source PHP Framework
</description>
<dc:language>ja</dc:language>
<admin:generatorAgent rdf:resource="http://blog.livedoor.com/?v=2.0" />
<items>
 <rdf:Seq>
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51088118.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51084176.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51079422.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51078345.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51078286.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51077702.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51075147.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51074469.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51069364.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51068519.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51067810.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51067536.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51066504.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51063695.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51062975.html" />
 </rdf:Seq>
</items>
</channel>

<item rdf:about="http://driveool.livedoor.biz/archives/51088118.html">
<title>XML Xpath</title>
<link>http://driveool.livedoor.biz/archives/51088118.html</link>
<description>クエリの頭が&quot;//&quot;の場合は絶対パス、無い場合は相対パスとなる。相対パスを使用する時はevaluate()メソッドの第2引数に基点となるノードを渡す。

全てのfoo要素

$items = $xpath-&amp;gt;evaluate(&quot;//foo&quot;);


$nodeの子要素のfoo要素(孫以下は含まれない)

$items = ...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-08-04T09:39:23+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[クエリの頭が"//"の場合は絶対パス、無い場合は相対パスとなる。相対パスを使用する時はevaluate()メソッドの第2引数に基点となるノードを渡す。<br/>
<br/>
全てのfoo要素
<pre class="box">
$items = $xpath-&gt;evaluate("//foo");
</pre>

$nodeの子要素のfoo要素(孫以下は含まれない)
<pre class="box">
$items = $xpath-&gt;evaluate("foo", $node);
</pre>

<br/>
属性は"@属性名"で指定する。<br/>
<br/>

attr属性を持つfoo要素
<pre class="box">
$items = $xpath-&gt;evaluate("//foo[@attr]");
</pre>

attr属性の値が'test'のfoo要素
<pre class="box">
$items = $xpath-&gt;evaluate("//foo[@attr = 'test']");
</pre>

attr属性の値が'http://'で始まるfoo要素
<pre class="box">
$items = $xpath-&gt;evaluate("//foo[starts-with(@attr, 'http://')]");
</pre>

attr属性の値が'http://'で始まらないfoo要素
<pre class="box">
$items = $xpath-&gt;evaluate("//foo[not(starts-with(@attr, 'http://'))]");
</pre>

attr属性の値が'http://'で始り、attr2属性の値が'hoge'のfoo要素
<pre class="box">
$items = $xpath-&gt;evaluate("//foo[starts-with(@attr, 'http://') and attr2 = 'hoge']");
</pre>

attr属性の値に'://'を含むfoo要素
<pre class="box">
$items = $xpath-&gt;evaluate("//foo[contains(@attr, '://')");
</pre>

<br/>
テキストノード(の内容)はtext()で指定する。<br/>
<br/>

テキストが'test'のfoo要素。
<pre class="box">
$items = $xpath-&gt;evaluate("//foo[text() = 'test']");
</pre>

テキストが'test'でないfoo要素。
<pre class="box">
$items = $xpath-&gt;evaluate("//foo[text() != 'test']");
</pre>

<br/>

users.xml
<pre class="box">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;users&gt;
  &lt;user id="1"&gt;
    &lt;name&gt;satou&lt;/name&gt;
    &lt;age&gt;20&lt;/age&gt;
  &lt;/user&gt;
  &lt;user id="2"&gt;
    &lt;name&gt;tanaka&lt;/name&gt;
    &lt;age&gt;30&lt;/age&gt;
  &lt;/user&gt;
  &lt;user id="3"&gt;
    &lt;name&gt;suzuki&lt;/name&gt;
    &lt;age&gt;40&lt;/age&gt;
  &lt;/user&gt;
&lt;/users&gt;
</pre>

ageの値(テキスト)が30以上のuser要素
<pre class="box">
$items = $xpath-&gt;evaluate("user[age/text() >= 30]", $users);
var_dump($item->length);  // int(2)
</pre>

ageが30以上、かつnameが'suzuki'のuser要素
<pre class="box">
$items = $xpath-&gt;evaluate("user[age/text() >= 30 and name/text() = 'suzuki']", $users);
var_dump($item->length);  // int(1)
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51084176.html">
<title>SWT Browser Widget</title>
<link>http://driveool.livedoor.biz/archives/51084176.html</link>
<description>HTMLをレンダリングするJavaクライアントアプリを作成する。

JDKをインストールする。
http://java.sun.com/javase/downloads/index.jsp

Eclipse(Eclipse IDE for Java EE Developers)をダウンロードする。
http://www.eclipse.org/downloads/

SWTをダウンロード...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-29T00:09:04+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[HTMLをレンダリングするJavaクライアントアプリを作成する。<br/>
<br/>
JDKをインストールする。<br/>
<a href="http://java.sun.com/javase/downloads/index.jsp" target="_blank">http://java.sun.com/javase/downloads/index.jsp</a><br/>
<br/>
Eclipse(Eclipse IDE for Java EE Developers)をダウンロードする。<br/>
<a href="http://www.eclipse.org/downloads/" target="_blank">http://www.eclipse.org/downloads/</a><br/>
<br/>
SWTをダウンロードする。<br/>
<a href="http://www.eclipse.org/swt/" target="_blank">http://www.eclipse.org/swt/</a><br/>
<br/>

SWT(zip)をC:\java\swttestに解凍する。<br/>
<br/>

JAVA_HOME\binを環境変数PATHに追加する。

<pre class="box">
C:\Program Files\Java\jdk1.6.0_07\bin
</pre>

Eclipseに含まれるSWTを展開する。

<pre class="box">
C:\HOME>cd C:\ECLIPSE_HOME\plugins
C:\ECLIPSE_HOME\plugins>jar xvf org.eclipse.swt.win32.win32.x86_x.x.x.vxxxxf.jar
</pre>

展開して出てきた.dllファイルをC:\java\swttestに移動する。<br/>
<br/>

BrowsetTestクラスを作成する。

<pre class="box">
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.browser.*;

public class BrowserTest
{
  public static void main(String args[])
  {
    Display display = new Display();
    Shell shell = new Shell(display);
    shell.setSize(800, 600);
    shell.open();
    
    Browser browser = new Browser(shell, SWT.NONE);
    browser.setBounds(shell.getClientArea());
    browser.setUrl("http://www.google.com/");
    
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
        display.sleep();
      }
    }
    
    display.dispose();
  }
}
</pre>

コンパイル &amp; 実行

<pre class="box">
C:\java\swttest>javac -classpath swt.jar;. BrowserTest.java
C:\java\swttest>java -classpath swt.jar;. BrowserTest
</pre>

]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51079422.html">
<title>PHP - XML(3)</title>
<link>http://driveool.livedoor.biz/archives/51079422.html</link>
<description>XMLにおける、複数のネームスペースと複数のスキーマによるバリデーションの考察。

user要素は以下のようなprofile要素(型)を持つとする。


&amp;lt;profile&amp;gt;
  &amp;lt;age&amp;gt;18&amp;lt;/age&amp;gt;
  &amp;lt;prefecture&amp;gt;Tokyo&amp;lt;/prefecture&amp;gt;
&amp;lt;/profile&amp;gt;


こ...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-21T17:24:35+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[XMLにおける、複数のネームスペースと複数のスキーマによるバリデーションの考察。<br/>
<br/>
user要素は以下のようなprofile要素(型)を持つとする。

<pre class="box">
&lt;profile&gt;
  &lt;age&gt;18&lt;/age&gt;
  &lt;prefecture&gt;Tokyo&lt;/prefecture&gt;
&lt;/profile&gt;
</pre>

このprofile型は他でも使えるかもしれない、という場合、profile型を定義するスキーマ"profile.xsd"を作成する。この時、このprofile型はネームスペース"prf"に属することとする。<br/>
<br/>
profile.xsdにはprofile型(複合型)、age型(単純型)、prefecture型(単純型)が含まれるため、それらを宣言する。

<pre class="box">
&lt;element name="profile" type="prf:PROFILE_CTYPE" /&gt;
&lt;element name="age" type="prf:PROFILE_AGE_STYPE" /&gt;
&lt;element name="prefecture" type="prf:PROFILE_PREFECTURE_STYPE" /&gt;
</pre>

単純型の定義を行う。

<pre class="box">
&lt;simpleType name="PROFILE_AGE_STYPE"&gt;
  &lt;restriction base="integer"&gt;
    &lt;minInclusive value="18" /&gt;
    &lt;maxInclusive value="120" /&gt;
  &lt;/restriction&gt;
&lt;/simpleType&gt;

&lt;simpleType name="PROFILE_PREFECTURE_STYPE"&gt;
  &lt;restriction base="string" /&gt;
&lt;/simpleType&gt;
</pre>

定義した単純型を参照し、profile型を定義する。

<pre class="box">
&lt;complexType name="PROFILE_CTYPE"&gt;
  &lt;sequence&gt;
    &lt;element ref="prf:age" /&gt;
    &lt;element ref="prf:prefecture" /&gt;
  &lt;/sequence&gt;
&lt;/complexType&gt;
</pre>

出来上がったprofile.xsdの全体。

<pre class="box">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;schema targetNamespace="http://mydomain/profns"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:prf="http://mydomain/profns"&gt;
  
  &lt;element name="profile" type="prf:PROFILE_CTYPE" /&gt;
  &lt;element name="age" type="prf:PROFILE_AGE_STYPE" /&gt;
  &lt;element name="prefecture" type="prf:PROFILE_PREFECTURE_STYPE" /&gt;
  
  &lt;simpleType name="PROFILE_AGE_STYPE"&gt;
    &lt;restriction base="integer"&gt;
      &lt;minInclusive value="18" /&gt;
      &lt;maxInclusive value="120" /&gt;
    &lt;/restriction&gt;
  &lt;/simpleType&gt;
  
  &lt;simpleType name="PROFILE_PREFECTURE_STYPE"&gt;
    &lt;restriction base="string" /&gt;
  &lt;/simpleType&gt;
  
  &lt;complexType name="PROFILE_CTYPE"&gt;
    &lt;sequence&gt;
      &lt;element ref="prf:age" /&gt;
      &lt;element ref="prf:prefecture" /&gt;
    &lt;/sequence&gt;
  &lt;/complexType&gt;
&lt;/schema&gt;
</pre>

XMLでuserは以下のように記述される(プロフィールは除外してある)。

<pre class="box">
&lt;user&gt;
  &lt;id&gt;1&lt;/id&gt;
  &lt;registeredDate&gt;2008-01-01T10:00:00&lt;/registeredDate&gt;
&lt;/user&gt;
</pre>

userはネームスペース"usr"に属することとした場合、XMLは次のように変更される。

<pre class="box">
&lt;usr:user&gt;
  &lt;usr:id&gt;1&lt;/usr:id&gt;
  &lt;usr:registeredDate&gt;2008-01-01T10:00:00&lt;/usr:registeredDate&gt;
&lt;/usr:user&gt;
</pre>

ネームスペース"usr"のスキーマ定義を行う。

<pre class="box">
&lt;element name="users" type="usr:USERS_CTYPE" /&gt;
&lt;element name="user" type="usr:USER_CTYPE" /&gt;
&lt;element name="id" type="usr:USER_ID_STYPE" /&gt;
&lt;element name="registeredDate" type="usr:USER_REGISTERED_DATE_STYPE" /&gt;

&lt;complexType name="USERS_CTYPE"&gt;
  &lt;sequence&gt;
    &lt;element ref="usr:user" minOccurs="1" maxOccurs="unbounded" /&gt;
  &lt;/sequence&gt;
&lt;/complexType&gt;

&lt;simpleType name="USER_ID_STYPE"&gt;
  &lt;restriction base="integer" /&gt;
&lt;/simpleType&gt;

&lt;simpleType name="USER_REGISTERED_DATE_STYPE"&gt;
  &lt;restriction base="dateTime" /&gt;
&lt;/simpleType&gt;

&lt;complexType name="USER_CTYPE"&gt;
  &lt;sequence&gt;
    &lt;element ref="usr:id" /&gt;
    &lt;element ref="usr:registeredDate" /&gt;
  &lt;/sequence&gt;
&lt;/complexType&gt;
</pre>

次に、userはprofileを持つという定義の実装を行う。profile型は外部(profile.xsd)で定義されているため、それをインポートする。

<pre class="box">
&lt;import namespace="http://mydomain/profns"
        schemaLocation="http://mydomain/xmlSchema/profile.xsd" /&gt;
</pre>

インポートするとprofile型が参照できるようになる。<br/>
userにprofile要素を追加する。

<pre class="box">
&lt;complexType name="USER_CTYPE"&gt;
  &lt;sequence&gt;
    ...
    &lt;element ref="prf:profile" /&gt;
  &lt;/sequence&gt;
&lt;/complexType&gt;
</pre>

出来上がったuser.xsdの全体。

<pre class="box">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;schema targetNamespace="http://mydomain/userns"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:usr="http://mydomain/userns"
        xmlns:prf="http://mydomain/profns"&gt;
  
  &lt;import namespace="http://mydomain/profns"
          schemaLocation="http://mydomain/xmlSchema/profile.xsd" /&gt;
  
  &lt;element name="users" type="usr:USERS_CTYPE" /&gt;
  &lt;element name="user" type="usr:USER_CTYPE" /&gt;
  &lt;element name="id" type="usr:USER_ID_STYPE" /&gt;
  &lt;element name="registeredDate" type="usr:USER_REGISTERED_DATE_STYPE" /&gt;
  
  &lt;complexType name="USERS_CTYPE"&gt;
    &lt;sequence&gt;
      &lt;element ref="usr:user" minOccurs="1" maxOccurs="unbounded" /&gt;
    &lt;/sequence&gt;
  &lt;/complexType&gt;
  
  &lt;simpleType name="USER_ID_STYPE"&gt;
    &lt;restriction base="integer" /&gt;
  &lt;/simpleType&gt;
  
  &lt;simpleType name="USER_REGISTERED_DATE_STYPE"&gt;
    &lt;restriction base="dateTime" /&gt;
  &lt;/simpleType&gt;
  
  &lt;complexType name="USER_CTYPE"&gt;
    &lt;sequence&gt;
      &lt;element ref="usr:id" /&gt;
      &lt;element ref="usr:registeredDate" /&gt;
      &lt;element ref="prf:profile" /&gt;
    &lt;/sequence&gt;
  &lt;/complexType&gt;
&lt;/schema&gt;
</pre>

これらのスキーマ定義に沿うXMLの例。

<pre class="box">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;usr:users xmlns:usr="http://mydomain/userns"
           xmlns:prf="http://mydomain/profns"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://mydomain/xmlSchema/user.xsd"&gt;
  &lt;usr:user&gt;
    &lt;usr:id&gt;1&lt;/usr:id&gt;
    &lt;usr:registeredDate&gt;2008-01-01T10:00:00&lt;/usr:registeredDate&gt;
    &lt;prf:profile&gt;
      &lt;prf:age&gt;20&lt;/prf:age&gt;
      &lt;prf:prefecture&gt;Tokyo&lt;/prf:prefecture&gt;
    &lt;/prf:profile&gt;
  &lt;/usr:user&gt;
  &lt;usr:user&gt;
    &lt;usr:id&gt;2&lt;/usr:id&gt;
    &lt;usr:registeredDate&gt;2008-02-02T15:00:00&lt;/usr:registeredDate&gt;
    &lt;prf:profile&gt;
      &lt;prf:age&gt;30&lt;/prf:age&gt;
      &lt;prf:prefecture&gt;Aichi&lt;/prf:prefecture&gt;
    &lt;/prf:profile&gt;
  &lt;/usr:user&gt;
&lt;/usr:users&gt;
</pre>

バリデーションのコード例。

<pre class="box">
$doc = new DOMDocument();
$doc-&gt;loadXML(file_get_contents("/path/to/users.xml"));

$xpath = new DOMXPath($doc);
$res = $xpath-&gt;evaluate("//@xsi:schemaLocation");
$doc-&gt;schemaValidate($res-&gt;item(0)-&gt;nodeValue);
</pre>

試しに年齢を200にするとWarningが発生する。スキーマ定義やprofile.xsdのインポートなど、機能していることがわかる。

<pre class="box">
Warning: DOMDocument::schemaValidate() [function.DOMDocument-schemaValidate]:
  Element '{http://mydomain/profns}age': [facet 'maxInclusive'] The value '200' is greater than the maximum value allowed ('120').
  in /usr/local/www/data/sabel/app/index/controllers/Index.php on line 17
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51078345.html">
<title>PHP - XML(2)</title>
<link>http://driveool.livedoor.biz/archives/51078345.html</link>
<description>XMLにおけるスキーマ定義の基本的な検証。


以下のようなXMLの有効性を検証するスキーマ定義を作成する。


&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;
&amp;lt;users xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
       xsi:schemaLocation=&quot;http://my...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-20T00:14:21+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[XMLにおけるスキーマ定義の基本的な検証。<br/>
<br/>

以下のようなXMLの有効性を検証するスキーマ定義を作成する。

<pre class="box">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;users xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://mydomain/xmlSchema/user.xsd"&gt;
  &lt;user&gt;
    &lt;id&gt;1&lt;/id&gt;
    &lt;registeredDate&gt;2008-01-01T10:00:00&lt;/registeredDate&gt;
  &lt;/user&gt;
  &lt;user&gt;
    &lt;id&gt;2&lt;/id&gt;
    &lt;registeredDate&gt;2008-02-02T15:00:00&lt;/registeredDate&gt;
  &lt;/user&gt;
  &lt;user&gt;
    &lt;id&gt;3&lt;/id&gt;
    &lt;registeredDate&gt;2008-03-03T20:00:00&lt;/registeredDate&gt;
  &lt;/user&gt;
&lt;/users&gt;
</pre>

まず、複合型となる、ドキュメント要素のusersと子要素のuserを定義する。

<pre class="box">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  &lt;xsd:element name="users" type="DEF_USERS" /&gt;
  &lt;xsd:element name="user" type="DEF_USER" /&gt;
  
  &lt;xsd:complexType name="DEF_USERS"&gt;
  &lt;/xsd:complexType&gt;
  
  &lt;xsd:complexType name="DEF_USER"&gt;
  &lt;/xsd:complexType&gt;
&lt;/xsd:schema&gt;
</pre>

次に、usersにuserが1つ以上含まれることを定義する。x以上はminOccursで、x以下はmaxOccursで指定する。最大値がいくらでも良い場合はunboundedとする。

<pre class="box">
  ...
  
  &lt;xsd:complexType name="DEF_USERS"&gt;
    &lt;xsd:sequence&gt;
      &lt;xsd:element ref="user" minOccurs="1" maxOccurs="unbounded" /&gt;
    &lt;/xsd:sequence&gt;
  &lt;/xsd:complexType&gt;
  
  ...
</pre>

次に、userが持つ単純型の要素(idやregisteredDate)の定義を行う。typeで、idは数値型、registeredDateは日付時刻型であることを示す。データ型はstring, boolean, floatなど色々ある。<a href="http://www.w3.org/TR/xmlschema-2/" target="_blank">こちら</a>を参照。

<pre class="box">
  ...
  
  &lt;xsd:complexType name="DEF_USER"&gt;
    &lt;xsd:sequence&gt;
      &lt;xsd:element name="id" type="xsd:int" /&gt;
      &lt;xsd:element name="registeredDate" type="xsd:dateTime" /&gt;
    &lt;/xsd:sequence&gt;
  &lt;/xsd:complexType&gt;
  
  ...
</pre>

できあがったスキーマ定義でバリデーションを行う。

<pre class="box">
$doc = new DOMDocument();
$doc-&gt;loadXML(file_get_contents("/path/to/users.xml"));

$xpath = new DOMXPath($doc);
$res = $xpath-&gt;evaluate("//@xsi:schemaLocation");
$doc-&gt;schemaValidate($res-&gt;item(0)-&gt;nodeValue);
</pre>

userのidの値を"abc"に変更するとWarningが発生する。バリデーションが正常に機能していることが分かる。

<pre class="box">
Warning: DOMDocument::schemaValidate() [function.DOMDocument-schemaValidate]:
  Element 'id': 'abc' is not a valid value of the atomic type 'xs:int'.
  in /usr/local/www/data/sabel/app/index/controllers/Index.php on line 16
</pre>

userを0個にした時のエラー。

<pre class="box">
Warning: DOMDocument::schemaValidate() [function.DOMDocument-schemaValidate]:
  Element 'users': Missing child element(s). Expected is ( user ).
  in /usr/local/www/data/sabel/app/index/controllers/Index.php on line 16
</pre>

userがageを持つように変更。しかし、ageはなくても良いものとする。また、値は整数で18～120とする(18や120という閾値を含まない場合、minExclusiveやmaxExclusiveにする)。この場合、データ型にintegerを指定するだけでは十分なルールでないため、年齢型を作成する。

<pre class="box">
  ...
  
  &lt;xsd:simpleType name="DEF_AGE"&gt;
    &lt;xsd:restriction base="xsd:integer"&gt;
      &lt;xsd:minInclusive value="18" /&gt;
      &lt;xsd:maxInclusive value="120" /&gt;
    &lt;/xsd:restriction&gt;
  &lt;/xsd:simpleType&gt;
  
  ...
</pre>

userにageの定義を追加する。データ型には作成したDEF_AGEを指定し、必須要素ではないためminOccursで0を指定する。

<pre class="box">
  ...
  
  &lt;xsd:complexType name="DEF_USER"&gt;
    &lt;xsd:sequence&gt;
      ...
      &lt;xsd:element name="age" type="DEF_AGE" minOccurs="0" /&gt;
    &lt;/xsd:sequence&gt;
  &lt;/xsd:complexType&gt;
  
  ...
</pre>

これでuserにageを持たせられるようになった。不正な値、例えば121とすると以下のようなエラーになる。

<pre class="box">
Warning: DOMDocument::schemaValidate() [function.DOMDocument-schemaValidate]:
  Element 'age': [facet 'maxInclusive'] The value '121' is greater than the maximum value allowed ('120').
  in /usr/local/www/data/sabel/app/index/controllers/Index.php on line 16
</pre>

今回作成したスキーマ定義の全体(user.xsd)

<pre class="box">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  &lt;xsd:element name="users" type="DEF_USERS" /&gt;
  &lt;xsd:element name="user" type="DEF_USER" /&gt;
  
  &lt;xsd:complexType name="DEF_USERS"&gt;
    &lt;xsd:sequence&gt;
      &lt;xsd:element ref="user" minOccurs="1" maxOccurs="unbounded" /&gt;
    &lt;/xsd:sequence&gt;
  &lt;/xsd:complexType&gt;
  
  &lt;xsd:simpleType name="DEF_AGE"&gt;
    &lt;xsd:restriction base="xsd:integer"&gt;
      &lt;xsd:minExclusive value="18"/&gt;
      &lt;xsd:maxInclusive value="120"/&gt;
    &lt;/xsd:restriction&gt;
  &lt;/xsd:simpleType&gt;
  
  &lt;xsd:complexType name="DEF_USER"&gt;
    &lt;xsd:sequence&gt;
      &lt;xsd:element name="id" type="xsd:int" /&gt;
      &lt;xsd:element name="registeredDate" type="xsd:dateTime" /&gt;
      &lt;xsd:element name="age" type="DEF_AGE" minOccurs="0" /&gt;
    &lt;/xsd:sequence&gt;
  &lt;/xsd:complexType&gt;
&lt;/xsd:schema&gt;
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51078286.html">
<title>PHP - XML</title>
<link>http://driveool.livedoor.biz/archives/51078286.html</link>
<description>XMLにおけるネームスペースの基本的な検証。

以下のようなXMLがある。


&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;
&amp;lt;books&amp;gt;
  &amp;lt;book&amp;gt;
    &amp;lt;title&amp;gt;book title1&amp;lt;/title&amp;gt;
    &amp;lt;author&amp;gt;author name1&amp;lt;/author&amp;gt;
  &amp;lt;/book&amp;g...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-19T14:56:44+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[XMLにおけるネームスペースの基本的な検証。<br/>
<br/>
以下のようなXMLがある。

<pre class="box">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;books&gt;
  &lt;book&gt;
    &lt;title&gt;book title1&lt;/title&gt;
    &lt;author&gt;author name1&lt;/author&gt;
  &lt;/book&gt;
  &lt;book&gt;
    &lt;title&gt;book title2&lt;/title&gt;
    &lt;author&gt;author name2&lt;/author&gt;
  &lt;/book&gt;
&lt;/books&gt;
</pre>

タグ名による要素の取得。

<pre class="box">
$doc = new DOMDocument();
$doc-&gt;loadXML(file_get_contents("/path/to/test.xml"));
$books = $doc-&gt;documentElement;
$titles = $books-&gt;getElementsByTagName("title");
var_dump($titles-&gt;length);  // int(2)
</pre>

bookの1つ目と2つ目に、それぞれネームスペースを与える。ネームスペースのURIは単なる名前で、存在するリソースを示さなくても良い。

<pre class="box">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;books&gt;
  &lt;book1:book xmlns:book1="http://www.example.com/ns1"&gt;
    &lt;book1:title&gt;book title1&lt;/book1:title&gt;
    &lt;book1:author&gt;author name1&lt;/book1:author&gt;
  &lt;/book1:book&gt;
  &lt;book2:book xmlns:book2="http://www.example.com/ns2"&gt;
    &lt;book2:title&gt;book title2&lt;/book2:title&gt;
    &lt;book2:author&gt;author name2&lt;/book2:author&gt;
  &lt;/book2:book&gt;
&lt;/books&gt;
</pre>

ネームスペース名(URI)を指定した、タグ名による要素の取得をする。

<pre class="box">
$doc = new DOMDocument();
$doc-&gt;loadXML(file_get_contents("/path/to/test.xml"));
$books = $doc-&gt;documentElement;

$titles = $books-&gt;getElementsByTagName("title");
var_dump($titles-&gt;length);  // int(2)

$titles = $books-&gt;getElementsByTagNameNS("http://www.example.com/ns1", "title");
var_dump($titles-&gt;length);  // int(1)

$titles = $books-&gt;getElementsByTagNameNS("http://www.example.com/ns2", "title");
var_dump($titles-&gt;length);  // int(1)
</pre>

親要素にネームスペースが与えられ、子要素のネームスペースが省略されている場合は、子要素は親要素のネームスペースに属することになる。この時、プレフィックスは省略できる。これは先程のXML文書と同等のものとなる。

<pre class="box">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;books&gt;
  &lt;book xmlns="http://www.example.com/ns1"&gt;
    &lt;title&gt;book title1&lt;/title&gt;
    &lt;author&gt;author name1&lt;/author&gt;
  &lt;/book&gt;
  &lt;book xmlns="http://www.example.com/ns2"&gt;
    &lt;title&gt;book title2&lt;/title&gt;
    &lt;author&gt;author name2&lt;/author&gt;
  &lt;/book&gt;
&lt;/books&gt;
</pre>

子要素がさらに別のネームスペースに属する場合、親要素のネームスペースはそれ以上下位に適用されない。

<pre class="box">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;books&gt;
  &lt;book xmlns="http://www.example.com/ns1"&gt;
    &lt;title&gt;book title1&lt;/title&gt;
    &lt;author&gt;author name1&lt;/author&gt;
    &lt;foo xmlns="http://www.example.com/foo"&gt;
      &lt;title&gt;foo&lt;/title&gt;
    &lt;/foo&gt;
  &lt;/book&gt;
&lt;/books&gt;
</pre>

<pre class="box">
$doc = new DOMDocument();
$doc-&gt;loadXML(file_get_contents("/path/to/test.xml"));
$books = $doc-&gt;documentElement;

$titles = $books-&gt;getElementsByTagName("title");
var_dump($titles-&gt;length);  // int(2)

$titles = $books-&gt;getElementsByTagNameNS("http://www.example.com/ns1", "title");
var_dump($titles-&gt;length);  // int(1)
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51077702.html">
<title>Sabel Release Announcement</title>
<link>http://driveool.livedoor.biz/archives/51077702.html</link>
<description>Sabel-1.1.1がリリースされました。
Sabel 1.1.0で発見されたいくつかのバグが修正されています。

(Http-Request)リクエスト後にGET値やPOST値を破棄するように変更, POST値が0個の場合にファイルアップロードできない問題の修正
(Task-Fixture)Windowsにおける絶対パス...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-18T15:25:24+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[Sabel-1.1.1がリリースされました。<br/>
Sabel 1.1.0で発見されたいくつかのバグが修正されています。<br/>
<br/>
(Http-Request)リクエスト後にGET値やPOST値を破棄するように変更, POST値が0個の場合にファイルアップロードできない問題の修正<br/>
(Task-Fixture)Windowsにおける絶対パス判定の正規表現の不具合を修正<br/>
(Util-String)エンコーディングにUTF-8を使用している際のtrim()メソッドの正規表現の不具合を修正<br/>
(JS)Stringクラス使用時の返り値の不具合修正<br/>
(JS)String.capitalizeメソッドのバグ修正<br/>
<br/>
ダウンロードは<a href="http://www.sabel.jp/downloads#11stable">こちら</a>から。
]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51075147.html">
<title>Sabel AjaxUploader Sample</title>
<link>http://driveool.livedoor.biz/archives/51075147.html</link>
<description>Sabel AjaxUploaderのサンプルを用意しました。

こちらで動作の様子を確認できます(100Mまで)。

コードは以下のような感じです。ジェネレータで生成することもできますが、コード量が少ないのでコピペでも楽かと思います。

コントローラ例


&amp;lt;?php

class I...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-14T09:21:14+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[Sabel AjaxUploaderのサンプルを用意しました。<br/>
<br/>
<a href="http://www.sabel.jp/smpl/upload/upload" target="_blank">こちら</a>で動作の様子を確認できます(100Mまで)。<br/>
<br/>
コードは以下のような感じです。ジェネレータで生成することもできますが、コード量が少ないのでコピペでも楽かと思います。<br/>
<br/>
コントローラ例

<pre class="box">
&lt;?php

class Index_Controllers_Upload extends Sabel_Controller_Page
{
  public function upload()
  {
    $this-&gt;uploadId = md5hash();
  }
  
  public function fetchStatus()
  {
    $status = apc_fetch("upload_" . $this-&gt;request-&gt;fetchGetValue("uploadId"));
    
    echo json_encode($status);
    exit;
  }
  
  public function uploaded()
  {
    echo "uploaded";
    exit;
  }
}
</pre>

uploadアクションのテンプレート例(Sabelレンダラ使用)

<pre class="box">
&lt;script type="text/javascript" src="&lt;?= linkto("js/Sabel.js") ?&gt;"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="&lt;?= linkto("js/helpers/AjaxUploader.js") ?&gt;"&gt;&lt;/script&gt;
&lt;style type="text/css"&gt;
@import url("&lt;?= linkto("js/helpers/css/Sabel.css") ?&gt;");
&lt;/style&gt;

&lt;div id="progressBar"&gt;&lt;/div&gt;

&lt;form id="upload_form" enctype="multipart/form-data" action="&lt;?= uri("a: uploaded") ?&gt;" method="post"&gt;
  &lt;p&gt;
    &lt;input type="hidden" name="APC_UPLOAD_PROGRESS" value="&lt;?= $uploadId ?&gt;" /&gt;
    &lt;input type="file"   name="upfile" /&gt;&lt;br /&gt;
    &lt;input type="submit" value="upload" /&gt;
  &lt;/p&gt;
&lt;/form&gt;

&lt;script type="text/javascript"&gt;
new Sabel.PHP.AjaxUploader("upload_form", "&lt;?= uri("a: fetchStatus") ?&gt;?uploadId=&lt;?= $uploadId ?&gt;", "progressBar");
&lt;/script&gt;
</pre>

<br/>

&nbsp;&nbsp;<a href="http://www.sabel.jp/"><img src="http://image.blog.livedoor.jp/driveool/imgs/3/a/3af945b1.gif" border="0" alt="Powered by Sabel" title="Powered by Sabel" class="pict" /></a>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51074469.html">
<title>ssh-agent</title>
<link>http://driveool.livedoor.biz/archives/51074469.html</link>
<description>ssh-agentの起動、パスフレーズ入力の自動化。


vi ~/.bashrc

echo -n &quot;ssh-agent: &quot;
if [ ! -f ~/.ssh-agent-info ]; then
  ssh-agent &amp;gt; ~/.ssh-agent-info
fi

source ~/.ssh-agent-info
ssh-add -l &amp;gt;&amp;/dev/null

if [ $? == 1 ]; then
  ssh-add ~...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-13T06:45:55+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[ssh-agentの起動、パスフレーズ入力の自動化。

<pre class="box">
vi ~/.bashrc

echo -n "ssh-agent: "
if [ ! -f ~/.ssh-agent-info ]; then
  ssh-agent &gt; ~/.ssh-agent-info
fi

source ~/.ssh-agent-info
ssh-add -l &gt;&/dev/null

if [ $? == 1 ]; then
  ssh-add ~/.ssh/priv_key
fi
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51069364.html">
<title>Sabel JS - DatePicker(Sabel.Widget.Calendar)</title>
<link>http://driveool.livedoor.biz/archives/51069364.html</link>
<description>Sabel 1.1で追加されるSabel.Widget.Calendarのサンプル。

カレンダーで日付を選択し、その選択された日付をインプットに適用するDatePicker.jsを書いてみた。


DatePicker.js

function datepicker(inputs) {
  Sabel.Array.each(inputs, function(input) {
    ...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-05T00:32:25+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[Sabel 1.1で追加されるSabel.Widget.Calendarのサンプル。<br/>
<br/>
カレンダーで日付を選択し、その選択された日付をインプットに適用するDatePicker.jsを書いてみた。

<pre class="box">
DatePicker.js

function datepicker(inputs) {
  Sabel.Array.each(inputs, function(input) {
    var div = document.createElement("div");
    div.style.position = "absolute";
    div.style.zIndex = 100;
    document.body.appendChild(div);
    
    var self = {
      element: Sabel.get(input),
      calendar: new Sabel.Widget.Calendar(div, {
        callback: function(date) {
          self.element.value = date.join("-");
        }
      }),
      render: function() {
        self.calendar.render();
      }
    };
    
    div.style.top  = Sabel.Element.getCumulativeTop(self.element)  + "px";
    div.style.left = Sabel.Element.getCumulativeLeft(self.element) + "px";
    
    self.calendar.WeekDays = ["日", "月", "火", "水", "木", "金", "土"];
    self.element.observe("mousedown", self.render);
  });
}
</pre>

インプットのidをdatepicker()関数に渡すだけで使用できる（簡単に使えるようにしているため、任意のタイミングでカレンダーを消すなどの処理はできない）。インプットをクリックすると、そのインプットの位置にカレンダーが表示され、日付をクリックするとインプットに年-月-日が入る。

<pre class="box">
&lt;script type="text/javascript" src="Sabel.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="DatePicker.js"&gt;&lt;/script&gt;

&lt;script type="text/javascript"&gt;
  new Sabel.Event(window, "load", function() {
    datepicker(["inputid1", "inputid2", ...]);
  });
&lt;/script&gt;
</pre>

動作の様子は<a href="http://driveool.livedoor.biz/smpl/datepicker.html" target="_blank">こちら</a>。<br/>
* 実際にサンプルのように表示するにはSabelに含まれるcssや画像が必要<br/>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51068519.html">
<title>Internet Explorerではこのページは表示できません</title>
<link>http://driveool.livedoor.biz/archives/51068519.html</link>
<description>JavaScriptを使用していて「Internet Explorerではこのページは表示できません」と出ることがある。IEがDOMの構築を終える前にDOM操作などを行おうとする場合にこうなったりならなかったり。

とりあえず、window.onloadイベントのリスナーで処理すれば安全な様子。


n...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-04T00:37:43+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[JavaScriptを使用していて「Internet Explorerではこのページは表示できません」と出ることがある。IEがDOMの構築を終える前にDOM操作などを行おうとする場合にこうなったりならなかったり。<br/>
<br/>
とりあえず、window.onloadイベントのリスナーで処理すれば安全な様子。

<pre class="box">
new Sabel.Event(window, "load", function(){
  // process
});
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51067810.html">
<title>grep | sed</title>
<link>http://driveool.livedoor.biz/archives/51067810.html</link>
<description>以下のような実行ログから失敗したid(\[\d+\]の部分)を抽出する。


20080701 15:20:01 SUCCESS: username [10502]
20080701 18:14:41 FAILURE: username [3821]
20080702 08:39:22 SUCCESS: username [9134]
20080702 14:43:52 FAILURE: username [6810]
20080702 21...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-03T00:56:26+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[以下のような実行ログから失敗したid(\[\d+\]の部分)を抽出する。

<pre class="box">
20080701 15:20:01 SUCCESS: username [10502]
20080701 18:14:41 FAILURE: username [3821]
20080702 08:39:22 SUCCESS: username [9134]
20080702 14:43:52 FAILURE: username [6810]
20080702 21:11:05 SUCCESS: username [8819]
20080703 08:31:34 SUCCESS: username [13266]
...
</pre>

grepで失敗の行を取り出してsedに渡す。<br/>
結果をfailures.phpに出力。

<pre class="box">
grep FAILURE some.log | sed -e 's/^.*\[\([0-9]*\)\]/\1 => 1,/' > failures.php
</pre>

こんな感じになる。

<pre class="box">
3821 => 1,
6810 => 1,
...
</pre>

ちょっと付け足してphpの配列にする。<br/>
使用する側のプログラムではissetでチェックしたいのでこの形式に。<br/>
in_array()だと遅い。

<pre class="box">
&lt;?php

$failures = array(
3821 => 1,
6810 => 1,
...
);

...

if (!isset($failures[$targetId])) {
  // process
}
</pre>

キャプチャに使う括弧をバックスラッシュでエスケープする必要がある。<br/>
これに少しはまった。
]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51067536.html">
<title>Sabel 1.1 Release Announcement</title>
<link>http://driveool.livedoor.biz/archives/51067536.html</link>
<description>Sabel-1.1のリリースが7/7(月)に決定しました。
概要は以下の通りです。

(Core)Sabel::using()でクラスファイルを読み込めたかどうかに応じてbool値を返すように変更
(Function)get_temp_dir()関数追加
(Function)md5hash()関数追加
(Function)remove_nullbyte()関数...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-02T01:07:50+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[Sabel-1.1のリリースが7/7(月)に決定しました。<br/>
概要は以下の通りです。

<ul><li>(Core)Sabel::using()でクラスファイルを読み込めたかどうかに応じてbool値を返すように変更
</li><li>(Function)get_temp_dir()関数追加
</li><li>(Function)md5hash()関数追加
</li><li>(Function)remove_nullbyte()関数追加
</li><li>(DI)DIコンテナ追加
</li><li>(Aspect)Aspect追加(AOPアライアンス準準拠)
</li><li>(Mail)メール(送信/Mimeデコード)追加
</li><li>(Http)HTTPクライアント追加
</li><li>(Annotation)バックスラッシュによるクオートのエスケープに対応
</li><li>(Response)設計の改善・ステータスオブジェクト追加
</li><li>(Request-Validator)一つの入力に対し複数のバリデーションメソッドを登録できるように改善
</li><li>(Controller-Redirector)外部サイトにリダイレクトする際などに使用するurl()メソッドが正常に動作しない問題の修正
</li><li>(View-Pager)実装の改善(3割程度の高速化)
</li><li>(View-PageViewer)実装のスリム化(setPriorityPrevious(), setPriorityNext(), setIgnoreEmpty()メソッド削除)
</li><li>(Session-Memcache)createメソッドでポート番号を指定できるように改善, addServer()メソッド追加
</li><li>(Storage-Memcache)addServer()メソッド追加
</li><li>(Cache-Memcache)addServer()メソッド追加
</li><li>(Util-FileSystem)Sabel_Util_FileSystemによりディレクトリやファイルを作成する際のデフォルトのパーミッションを744から755に変更
</li><li>(DB)バイナリデータ(画像・ファイル)の保存・取得に対応
</li><li>(DB)行のバージョニング(楽観的ロック)に対応
</li><li>(DB)sabel.db.mssql(Microsoft SQL Server)パッケージの追加
</li><li>(DB)Sabel_DB_Modelの各メソッドに対するコールバックの対応が変更
</li><li>(DB)Joinオブジェクト使用時のカラムの指定を可能に改善
</li><li>(DB-Model)selectWithChildrenメソッドを削除
</li><li>(DB-Model)save()メソッドによりモデルの状態をデータベースに反映する際、プライマリキーの値が変更されている場合に例外を投げるように変更
</li><li>(Test)Sabel_Test_Fixtureクラス追加
</li><li>(Processor-Action)リクエストバリデーションがURIクエリに対応
</li><li>(Processor-Session)session.use_trans_sidがOnかつクライアントがCOOKIEを無効にしている時にセッションIDが2重に付加される問題の修正, セッションが開始されていない際にリンクやリダイレクト先URIにセッション名が付加される問題の修正
</li><li>(JS)Sabel.Environment追加
</li><li>(JS)Sabel.Class追加
</li><li>(JS)Sabel.KeyEvent追加
</li><li>(JS)Sabel.Number追加
</li><li>(JS)Ajaxアップローダ追加(apc必須)
</li><li>(JS)Dateピッカー(カレンダー)追加
</li><li>(JS)ElementにgetRegion(), replaceClass()メソッド追加
</li><li>(JS)Sabel.Util.UriをSabel.Uriに変更
</li><li>(JS)Element.getDimentionsメソッドのバグ修正
</li><li>(JS)Effectのバグ修正
</li><li>(JS)要素の絶対位置取得メソッドのバグ修正
</li><li>(JS)現在のスクロール量取得メソッド追加
</li><li>(JS)Stringクラスの大幅な改善(sprintf, htmlspecialchars, chr, repeat追加など)
</li><li>(JS)Ajaxのオプションにtimeout, scope追加
</li><li>(JS)Eventにscope追加
</li><li>(JS)widget.Overlayの改善(Widget.Overlayにリネーム)
</li><li>(Task)各種ジェネレータ追加
</li><li>(Task)バッチ実行ファイル(sabel.php)で正常なアプリケーションルートパスが定義されない問題の修正
</li><li>(Addon-Form)Formオブジェクトが保持するHTMLを書き出すオブジェクトの初期化に不具合があったのを修正, モデルにバージョンカラムがある場合にclose()メソッドで&lt;/form&gt;タグとともにバージョン値をhiddenで書き出すように対応
</li><li>(Addon-Renderer)ショートタグ形式の場合にHTMLエスケープするようにSabelレンダラを改善, SabelレンダラのHTMLタグを抜き出す正規表現を最小マッチに変更
</li><li>(Lib-Paginate)setOrderColumn()メソッドをsetOrderColumns()に変更, setDefaultOrder()メソッド追加, uriの指定を省略可能に改善
</li><li>rewriteモジュールがロードされていない場合にInternal Server Errorになる問題の修正
</li><li>Scaffold(sabelコマンド)にlangオプション(ja)追加
</li><li>$_SERVER["HTTP_HOST"]を参照している箇所を$_SERVER["SERVER_NAME"]を参照するように変更
</li></ul>

<br/>

&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.sabel.jp/"><img src="http://image.blog.livedoor.jp/driveool/imgs/3/a/3af945b1.gif" border="0" alt="Powered by Sabel" title="Powered by Sabel" class="pict" /></a>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51066504.html">
<title>Apache - Basic Authentication</title>
<link>http://driveool.livedoor.biz/archives/51066504.html</link>
<description>簡単に済ませたいとき、たまに使うBasic認証。「たまに」なのでいつも忘れる。

パスワードファイル作成。

$ htpasswd -c /usr/local/www/data/myapp/config/.htpasswd username
New password: [enter password]
Re-type new password: [enter password]
Adding pass...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-30T19:50:25+09:00</dc:date>
<dc:subject>Server</dc:subject>
<content:encoded><![CDATA[簡単に済ませたいとき、たまに使うBasic認証。「たまに」なのでいつも忘れる。<br/>
<br/>
パスワードファイル作成。
<pre class="box">
$ htpasswd -c /usr/local/www/data/myapp/config/.htpasswd username
New password: [enter password]
Re-type new password: [enter password]
Adding password for user username
</pre>

http.confに設定を追加する。

<pre class="box">
&lt;Directory "/usr/local/www/data/myapp/"&gt;
    AuthType Basic
    AuthName "Private Area"
    AuthUserFile /usr/local/www/data/myapp/config/.htpasswd
    Require valid-user
&lt;/Directory&gt;
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51063695.html">
<title>Quoted-Printable Encode/Decode</title>
<link>http://driveool.livedoor.biz/archives/51063695.html</link>
<description>phpにquoted_printable_decode()関数はあるけど、quoted_printable_encode()関数はないので、エンコードは次のように行う(mb拡張があればmb_encode_mimeheader()でQエンコーディング使えば良い)。


$fp = fopen(&quot;php://temp&quot;, &quot;r+&quot;);

stream_filter_appand($fp, &quot;conv...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-26T23:21:08+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[phpにquoted_printable_decode()関数はあるけど、quoted_printable_encode()関数はないので、エンコードは次のように行う(mb拡張があればmb_encode_mimeheader()でQエンコーディング使えば良い)。<br/>

<pre class="box">
$fp = fopen("php://temp", "r+");

stream_filter_appand($fp, "convert.quoted-printable-encode",
                     STREAM_FILTER_READ,
                     array("line-length" => 74,
                           "line-break-chars" => "\r\n")
                    );

fputs($fp, $str);
rewind($fp);
$encoded = stream_get_contents($fp);
fclose($fp);
</pre>

多くのMUAがヘッダに含まれるアンダースコアをスペースに変換する(ボディのアンダースコアはそのまま)。変換するMUAは、確認したところで、Outlook Express6, Thunderbird, Mail, Becky, Sylpheed, Eudora, Entourage。変換しないMUAはShuriken。<br/>
<br/>
変換したりしなかったりなので、ヘッダでもボディでも、とにかくアンダースコアは=5Fに変換しておけば良い。

<pre class="box">
$encoded = str_replace("_", "=5F", $encoded);
</pre>

デコード時は、先程挙げた多くのMUAと同様、ヘッダの場合にのみアンダースコアをスペースに変換する。=5Fはquoted_printable_decode()関数がアンダースコアに変換するので、気にしなくて良い。

<pre class="box">
if ($isHeader) {
  $str = str_replace("_", " ", $str);
}

$decoded = quoted_printable_decode($str);
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51062975.html">
<title>response headers in the download script</title>
<link>http://driveool.livedoor.biz/archives/51062975.html</link>
<description>日本語ファイル名のファイルをダウンロードさせる場合、少しブラウザ(ユーザエージェント)を気にする必要がある。

Safariはサーバ側でどうにもできないため、ダウンロードリンクの最後(ファイル名として扱われる)をファイル名をURLデコードしたものにする。


&amp;lt;a hr...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-25T23:33:25+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[日本語ファイル名のファイルをダウンロードさせる場合、少しブラウザ(ユーザエージェント)を気にする必要がある。<br/>
<br/>
Safariはサーバ側でどうにもできないため、ダウンロードリンクの最後(ファイル名として扱われる)をファイル名をURLデコードしたものにする。

<pre class="box">
&lt;a href="/dlscript/&lt;?php echo urlencode($filename) ?&gt;"&gt;
  &lt;?php echo htmlentities($filename, ENT_QUOTES) ?&gt;
&lt;/a&gt;
</pre>

サーバ側では、IEの場合にヘッダに付加するファイル名をShift-JISに変換する。Safariの場合はヘッダにファイル名を付加しない(付加すると文字化けする)。

<pre class="box">
$filename = urldecode($filename);
$path = "/path/to/" . $filename;

header("Content-Type: application/octet-stream");
header("Content-Length: " . filesize($path));

$ua = (isset($_SERVER["HTTP_USER_AGENT"])) ? $_SERVER["HTTP_USER_AGENT"] : "unknown";
if (strpos($ua, "MSIE") !== false) {
  $filename = mb_convert_encoding($filename, "SJIS", "UTF-8");
}
      
if (strpos($ua, "Safari") === false) {
  header("Content-Disposition: attachment; filename="' . $filename . '"');
} else {
  header("Content-Disposition: attachment");
}
      
echo file_get_contents($path);
</pre>

以下のブラウザで文字化けすることなくダウンロードできることを確認。

<ul>
  <li>Windows: IE6, IE7, Firefox2, Opera9.?, Safari3</li>
  <li>Linux: Firefox2, Opera9.?</li>
  <li>Mac: Firefox3, Opera9.?, Safari3</li>
</ul>
]]>
</content:encoded>
</item>

</rdf:RDF>