PHP SimpleXML を使用してローカル DTD を参照するには、絶対パスをファイル タイプ URI に変換する必要があります。たとえば、/home/sitename/www/xml/example.dtd を file:///home/sitename/www/xml/example.dtd に変換します。
与えられた例では、必要なのはパスの前に「ファイル」スキームを追加することだけなので、非常に簡単です。ただし、ディレクトリ名の 1 つに空白があるなどの状況が発生した場合は、これでは不十分です。このメカニズムは Windows または Linux で動作し、ディレクトリ名に非 ASCII 文字を使用できるようにする必要があります。
これまでに考案されたコードは次のとおりです。
$absparts = explode('/', _ALIRO_ABSOLUTE_PATH);
$driveletter = (0 == strncasecmp(PHP_OS, 'win', 3)) ? array_shift($absparts) : '';
$filename = $driveletter.implode('/', array_map('rawurlencode', $absparts)).'/xml/'.$filename.'.dtd';
$href = 'file:///'.$filename;
ここで、定義されたシンボルはシステム ルートへの絶対パス (常にスラッシュ付き) であり、DTD は xml サブディレクトリにあり、$filename の後に拡張子 .dtd が続く名前を持ちます。
これは正しく動作しますか? より良いアプローチはありますか?
もう少し背景を説明します。目的は、SimpleXML を使用して XML ドキュメントを解析することです。これは、LIBXML_DTDVALID オプションを指定した simplexml_load_string() 関数を使用して行われます。XML ドキュメントには、ホーム Web サイトを指す実際の URI が含まれますが、遠く離れた Web サイトに到達するために遅延が発生したり、要求でホーム Web サイトをロードしたりしたくありません。したがって、DTD への参照は、ローカル マシンを参照するように編集されます。ただし、XML ドキュメント内の DOCTYPE 内に URI として埋め込む必要があります。制約は私の選択ではありません。それらは DOCTYPE のルールに暗黙的に含まれており、SimpleXML 関数によって強制されます。ファイルの場所は絶対パスでわかりますが、DOCTYPE にするには、URI に変換する必要があります。