レベル: 初級 Brett McLaughlin (brett@newinstance.com), Enhydra strategist, Lutris Technologies
2001年 6月 15日 Brett McLaughlinが、外部エンティティー参照を使用して外部コンテンツをXML文書に組み込む方法と、SAX EntityResolverインターフェースを使用する方法を説明します。コード・サンプルによりインターフェースを例示し、その使用法を説明し、エンティティー・リゾルバーをパーサーに登録する方法を提示します。
ほとんどのXML開発者やHTML開発者は、エンティティー参照については良くご存知のことと思います。エンティティー参照とは、「アンパーサンド (&) で始まり、セミコロン (;) で終わる」というよく見かける変わった小さなXML構成体です。おそらく、エンティティー参照の最も一般的な使い方は、XMLには含めることのできない文字を、XMLのコンテンツの一部として表示させることです。たとえば、XMLまたはHTMLエレメントを開始するオープン不等号括弧 (<、より小記号とも呼ばれる) を表す<です。
開発者によっては、別のエンティティー参照の仕方で他のソース (多くの場合は、複数のXML文書にまたがって共用するコンテンツであり、場合によっては、XMLに変換不可能なFlashアニメーション・シーケンスのような項目) から取得した材料をXML文書に組み込む人もいます。この種のエンティティー参照は外部エンティティー参照 と呼ばれ、コンテンツを何度もコピーしたり貼り付けたりする時間を省くことができます。たとえば、XML文書でエンティティー参照 (©right; など) を使用して、ほかのだれかが最新状態に保持している別の文書の常用文セクションを参照することができます。(しかし、DTDまたはXMLスキーマがなければ外部エンティティー参照は機能しないので、その場合は参照しないでください。)
エンティティー参照の構文解析および関連する問題
XMLの構文解析を実行すると、パーサーは、DTDまたはXMLスキーマに指定されているロケーションを使用して、XML文書の外部エンティティー参照を解決 します (現在、実動アプリケーションにおけるDTDの使用が一般的になっていることから、この記事ではDTDを重点的に説明します)。解決時には、パーサーは参照するコンテンツを突き止め、それをXMLに挿入します。つまり、構文解析した文書 (Java、C、Perl、PHP、Python、または他の任意の言語を使用して) を操作する場合は、参照したコンテンツは他の任意のコンテンツと同様に表示されます。すべてが正しく機能している限り、各参照コンテンツの個々の処理を気にする必要はありません。ただし、複雑な状態になると、単純なプロセスが失敗することがあります。
たとえば、解決を正しく機能させるためにライブ・ネットワーク接続が必要になることがあります。それは、非常に多くの参照エンティティーがいずれかのリモートURL (たとえば、リスト3のコード例に示されているhttp://www.ibm.com/developerWorks/copyright.xml) を参照するからです。解決 (接続のオープン、コンテンツのプルダウン、接続のクローズ、など) も構文解析プロセスを遅くする可能性があります。皆さんは、参照したコンテンツをキャッシュに入れたローカル・コピーを提供する方法や、エンティティー解決プロセスを迂回する方法はないのかと、不思議に思われるかもしれません。実は、それがあるのです。
外部エンティティー参照を解決するための簡単な方法
Simple API for XML (SAX) を使用しているのであれば、ラッキーです。また、DOMとJDOMはどちらも背後でSAXを使用するので、この単純なソリューションは3つのすべてのAPIに有効に働きます (この3つのすべてのAPIに関する背景情報については、参考文献を参照してください)。SAXは、ユーザーが望む機能だけを提供するインターフェースorg.xml.sax.EntityResolver を定義します。このインターフェースは、リスト1に示されているとおり、1つのメソッドのみを定義します。
リスト1. SAX EntityResolverインターフェース
package org.xml.sax;
public interface EntityResolver {
public InputSource resolveEntity(String publicID, String systemID)
throws SAXException;
}
|
このインターフェースにおける唯一のメソッドresolveEntity() は、エンティティー解決プロセスへ進む手段を提供します。各外部エンティティー参照は、コンテンツを解決する方法を指定するDTDにパブリックIDまたはシステムID (あるいはその両方) を備えているので、ユーザーはこのメソッドでこれらを一致させ、独自の振る舞いをインプリメントすることができます。たとえば、リスト2では、copyright 外部エンティティー参照を定義する、以下のようなDTDフラグメントを考えてみます。
リスト2. DTDに定義されたcopyright外部エンティティー参照
<!ENTITY copyright SYSTEM "http://www.ibm.com/developerWorks/copyright.xml">
|
ここにはパブリックIDは存在せず、システムIDはhttp://www.ibm.com/developerWorks/copyright.xml です。したがって、リスト3に示されているようなCopyrightEntityResolver というクラスを作成することができます。
リスト3. EntityResolverのインプリメンテーション
package com.ibm.developerWorks;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class CopyrightResolver implements EntityResolver {
public InputSource resolveEntity(String publicID, String systemID)
throws SAXException {
if (systemID.equals("http://www.ibm.com/developerWorks/copyright.xml")) {
// Return local copy of the copyright.xml file
return new InputSource("/usr/local/content/localCopyright.xml");
}
// If no match, returning null makes process continue normally
return null;
}
|
この単純なインプリメンテーションでは、エンティティーが解決されるたびにresolveEntity() メソッドが起動されます。エンティティーのシステムIDがそのメソッドのURLと一致した場合は、ローカルXML文書 (localCopyright.xml) が戻されます。これは、提供されたシステムIDで見つかるすべてのリソースに代わって 行われます。こうして、このプロセスを "短絡" し、指定のパブリックIDまたはシステムIDに対して独自のデータを提供することができます。一致が起きなかった場合は、常に、null を戻すようにすることができるため、特殊な場合以外は、エンティティー解決が通常どおり行われます。
これで大体終わりです。リスト4に示されているように、エンティティー・リゾルバーをパーサーに登録することができます。
リスト4. EntityResolverのインプリメンテーション
// Get an XML Reader - this code not detailed here
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setEntityResolver(new CopyrightResolver());
reader.parse(new InputSource("article.xml"));
|
これでおわかりでしょう。エンティティー参照コンテンツのローカル・コピーを取得できた場合、または自分のコンテンツをエンティティー参照の代わりにする必要がある場合は、SAXEntityResolver インターフェースを使用してください。こうすれば、アプリケーションの高速化や、XML文書の柔軟性の拡張に役立つはずです。がんばってください!
参考文献
著者について  | 
|  | Brett McLaughlin (brett@newInstance.com) は、Lutris TechnologiesでEnhydraストラテジストを務めており、分散システム・アーキテクチャーを専門としています。また、Java and XML (O'Reilly社) の著者でもあります。Javaサーブレット、Enterprise JavaBeansテクノロジー、XMLおよびビジネス・ツー・ビジネス・アプリケーションなどの技術にかかわっています。氏は、Jason Hunter氏と一緒に、JDOMプロジェクトを設立しました。このプロジェクトは、JavaアプリケーションからXMLを扱う、簡潔なAPIを提供しています。また、Apache CocoonプロジェクトとEJBoss EJBサーバーの開発に積極的に取り組んでおり、Apache Turbineアクティブの共同設立者でもあります。 |
記事の評価
|