JXPath

メニュー

情報

プロジェクトに関する情報

ダウンロード

我々について

Jakartaプロジェクト

コンポーネント レポジトリ

Sandboxコンポーネント

日本語訳 (Translations)

オリジナル

What's JXPath

JXPathは、XPath構文を使って、JavaBean/DOM/その他の型のオブジェクトを解析し、ツリー構造で表現されるデータの集合を生成するAPIを提供します。

もし、XPath構文を余り知らなければ、XPath Tutorial by W3Schoolsから初めてみてください。
また、XML Path Language (XPath) バージョン1.0 もあります----公式の標準です。

XPathは、XSLTの公式な表現言語です。XSLTでは、XMLドキュメントの様々な要素にアクセスするのに大部分はXpathを使うでしょう。これと同じ事をJXPathでも行う事が出来ます。更に、JavaBeanのプロパティの読み書きが出来、配列型・コレクション型・MAP型・透過的コンテナ・サーブレット内のコンテキストオブジェクト、などといった要素のgetとsetを行う事も出来ます。言い換えれば、JXPathはXPathの概念を、代わりとなるオブジェクトモデルに応用した、という事が出来るでしょう。

必要とあらば、JXPathから新規オブジェクトを生成する事もできます。

JXPathの構成の中で一番重要なクラスは、 JXPathContext クラスです。 この文書で議論される殆どのAPIは、何らかの形でこのJXPathContextクラスと関連しています。


Object Graph Traversal

JXPathは、JavaBeanのプロパティを列挙しアクセスするために、JavaBeanのイントロスペクションを使います。

Javaオブジェクト・グラフのコンテキストに措けるXPath構文の解釈は、全く持って直感的です: XPathの"child"軸がJavaBeanのプロパティにマッピングされます。

JavaBean Property Access

JXPathは、JavaBeanのプロパティにアクセスするのに利用する事も出来ます。

                                                                       
public class Employee {
    public String getFirstName(){
       ...
    }
}

Employee emp = new Employee();
...

JXPathContext context = JXPathContext.newContext(emp);
String fName = (String)context.getValue("firstName");

この例では、emp beanのプロパティにアクセスする為に、JXPathを使っています。 このようなシンプルなケースで、JXPathの呼び出しは、Bean上でのgetFirstName()メソッドの呼び出しと等価になります。


Lenient Mode

与えられたxpathにプロパティが存在していない場合、context.getValue(xpath)メソッドは、例外を投げます。 この制約は、context.setLenient(true)を呼び出す事で、緩やかになります。 "lenient"モードでは、pathがどれにも対応しない場合は単にnullを戻すだけです。


Nested Bean Property Access

JXPathは、オブジェクト・グラフを全探索(トラバース)する事ができます。

                                                                       
 public class Employee {
    public Address getHomeAddress(){
       ...
    }
 }
 public class Address {
    public String getStreetNumber(){
       ...
    }
 }

 Employee emp = new Employee();
 ...

 JXPathContext context = JXPathContext.newContext(emp);
 String sNumber = (String)context.getValue("homeAddress/streetNumber");
 

このケースで、XPathはネストされたBeanのプロパティにアクセスするのに使われています。

XPathによって示されるプロパティは、"leaf"プロパティである必要はありません。 例えば、上記の例のAddress型オブジェクト全体を抽出する事が出来ます:

                                                                       
    Address addr = (Address)context.getValue("homeAddress");
 

Collection Subscripts

JXPathは、配列型やコレクション型から要素を抽出する事が出来ます。

                                                                       
 public class Integers {
    public int[] getNumbers(){
       ...
    }
 }

 Integers ints = new Integers();
 ...

 JXPathContext context = JXPathContext.newContext(ints);
 Integer thirdInt = (Integer)context.getValue("numbers[3]");
 

コレクション型には、任意の配列やjava.util.Collectionのインスタンスがあります。

注意: XPathでは、コレクションの最初の要素番号は、0ではなく1です。


Retrieving Multiple Results

JXPathを使って、オブジェクト・グラフから複数のオブジェクトを取得する事が出来ます。 この場合、getValueメソッドではなく、iterateメソッドを呼び出すことに注意してください。

                                                                       
 public class Author {
    public Book[] getBooks(){
       ...
    }
 }

 Author auth = new Author();
 ...

 JXPathContext context = JXPathContext.newContext(auth);
 Iterator threeBooks = context.iterate("books[position() < 4]");
 

対象となる著者によって書かれた全ての本の配列から、最大3冊の本のリストを返します。


Map Element Access

JXPathはMap型をサポートします。値を得るには、対応するキーを使います。

                                                                       
 public class Employee {
    private Map addressMap = new HashMap();
    {
        addressMap.put("home", new Address(...));
        addressMap.put("office", new Address(...));
    }

    public Map getAddresses(){
       return addressMap;
    }
    ...
 }

 Employee emp = new Employee();
 JXPathContext context = JXPathContext.newContext(emp);
 String homeZipCode =
        (String)context.getValue("addresses/home/zipCode");
 

Map要素へのアクセスの為に、代わりの構文を使う必要がある場合もあるでしょう。

                                                                       
 String homeZipCode = (String)context.
        getValue("addresses[@name='home']/zipCode");
 

XPathでの子要素名とは違い、"name"属性の値は適切な識別子(訳注:Java Identifier)である必要はありません。また、この例では、"key"が式であっても良いのです(例:変数)。

"name"属性は、Map型で使えるだけではなく、JavaBeanでも使えます。 其の場合、この属性の値は、プロパティ名をあらわします。

注意: この場合、keyとしてString型を使っているMapのみをJXPathはサポートします。

注意: JXPathは、Mapの拡張概念をサポートします: クラスがJXPathIntrospector で登録されている、という前提上であれば、動的プロパティを持ついかなるオブジェクトも、JXPathによって扱うことが可能です。


DOM Document Access

JXPathは、DOMノードへのアクセスをサポートします。JXPathContextのコンテキスト・ノード、あるいはプロパティ・コレクション型の要素・変数等の値が、DOMノードになり得ます。 今、"$foo/bar/baz"というPathがあると考えてみます。 例えば、変数"foo"の値がJavaBean(プロパティ"bar"がDOMノードで、その子ノードに"baz"がある場合)であれば、正常に動作します。

DOM構造モデル上でのXPathの解釈は、XPath仕様に基づいて実行されます。例えば、"attribute"軸は、DOMオブジェクトでは適用できますが、JavaBeansでは適用できません。


Containers

Containerは、JXPathを透過的にする、間接的なメカニズムを実装しているオブジェクトです。

例えば、コンテキストノードのプロパティ"foo"が値としてContainerを持っている場合、XPath形式の"foo"は、コンテナそのものではなくContainerの内容を意味する事になります。

有益なコンテナの例は、XMLDocumentContainerです。XMLDocumentContainerを生成する際、XMLファイルの場所のポインタを書くことでしょう(URL形式あるいはjavax.xml.transform.Source型)。XMLDocumentContainerは、XMLファイルをアクセスされた時一度だけ読み込み解析します。XPathを使ってアクセスされる(されなくても)様々なXML文書でXMLDocumentContainerを生成することが出来ます。それら文書があれば、自動的に読み込まれ、解析され、トラバースされるでしょう。もしなければ、全く読み込まれません。

Javaリソースとして格納されている、以下のXMLファイルを仮定しましょう。

                                                                       
    <?xml version="1.0" ?>
    <vendor>
      <location id="store101">
        <address>
          <street>Orchard Road</street>
        </address>
      </location>

      <location id="store102">
        <address>
          <street>Tangerine Drive</street>
        </address>
      </location>
    </vendor>

XMLDocumentContainerを使ったコード例です。

                                                                       
 class Company {
    private Container locations = null;

    public Container getLocations(){
        if (locations == null){
            URL url = getClass().getResource("Vendor.xml");
            locations = new XMLDocumentContainer(url);
        }
        return locations;
    }
 }
 ...
 context = JXPathContext.newContext(new Company());
 ...
 String street = (String)context.getValue(
                "locations/vendor/location[@id = 'store102']//street");

前に記述したように、このコードは暗示的にXMLファイルを開き、パースを行います。そして、XPathに対応した値を見つけ出します。


Functions id() and key()

id()関数とkey()関数は、JXPath内で使う事が出来ます。しかし、殆どの場合、新たなコーディングが必要になります。

新たなコーディングを必要としない唯一の場合は、id()関数を使いたいと考え、更にDOMノードをJXPathContextとして持っている場合のみです。この場合、DOMの標準規則をJXPathは使います。

id()関数を評価するために、JXPathは、JXPathContextの中で実装されるべき委譲クラスオブジェクト(delegate object)を呼び出します。この委譲オブジェクトは、IdentityManagerインターフェースを実装している必要があります。

似たように、key()関数は、KeyManagerインターフェースを実装するカスタムクラスを頼ります。


注意: JXPathは、DOMではないオブジェクト用のDOM attributeをサポートしていません。例え、XPathが"para[@type='warning']"形式の正しいものであっても、emptyの結果を常に出します。JavaBeanでの唯一の"attribute"のサポートは、"name""xml:lang"のみです。


Modifying Object Graphs

JXPathは、オブジェクト・グラフの一部を修正変更する際にも使われます:プロパティ値・Mapでの"key"に対応する値、等です。オブジェクト・グラフでの中間ノードを作る事もあります。

Setting Properties

プロパティ値の修正・変更を行う際にJXPathを使う事が出来ます。

                                                                       
 public class Employee {
    public Address getAddress() {
       ...
    }

    public void setAddress(Address address) {
       ...
    }
 }

 Employee emp = new Employee();
 Address addr = new Address();
 ...

 JXPathContext context = JXPathContext.newContext(emp);
 context.setValue("address", addr);
 context.setValue("address/zipCode", "90190");
 

Creating Objects

JXPathを使って、新規のオブジェクトを生成する事が出来ます。初めに、AbstractFactoryのサブクラスを作り、JXPathXontextをその中に実装します。次に、jxPathContext.createPath(xpath)を呼び出します。JXPathContextは、パスの中間ノードがnullである場合に、AbstractFactoryをinvoke(訳注:メソッドの動的な起動)します。存在するノードを上書きしません。

                                                                       
 public class AddressFactory extends AbstractFactory {
    public boolean createObject(JXPathContext context, Pointer pointer,
                                Object parent, String name, int index){
     if ((parent instanceof Employee) && name.equals("address"){
       ((Employee)parent).setAddress(new Address());
       return true;
     }
     return false;
   }
 }

 JXPathContext context = JXPathContext.newContext(emp);
 context.setFactory(new AddressFactory());
 context.createPath("address");

パスの生成と同時にリーフノードの値を設定する事もできます:其の場合は、createPathAndSetValue(path, value)メソッドを使います。

                                                                       
 context.createPathAndSetValue("address/zipCode", "90190");

ノードの自動生成は、とてもシンプルなパスである時だけ意味をなすということを押さえておいてください。実際、JXPathは、以下のルールに従わないパスの中間ノードを生成しようとしません:

  • "child::"軸だけが使われる---例:"foo/bar/baz"(訳注:"foo/child::bar/child::bazと等価")
  • コンテキスト非依存のインデックス番号、"[@name = expr]"構成の、2つのタイプの述語のみが使われる---例:"map[@name='key1'][4/2]"
  • 変数が使われる際は、それがパスのルートになっている---例:"$object/child"



Variables

JXPathは、変数の概念をサポートします。変数にアクセスする為のXPath構文は、"$varName"です。

                                                                       
 public class Author {
    public Book[] getBooks(){
       ...
    }
 }

 Author auth = new Author();
 ...

 JXPathContext context = JXPathContext.newContext(auth);
 context.getVariables().declareVariable("index", new Integer(2));

 Book secondBook = (Book)context.getValue("books[$index]");
 

JXPathを使って、変数をセットする事も出来ます:

                                                                       
 context.setValue("$index", new Integer(3));
 

注意: 一般的に、このやり方では、既に存在する変数の値を変更する事だけが可能で、 新たな変数を定義する事は出来ません。もし、動的に新たな変数を定義したいと考えるならば、defineVariable()メソッドを独自のAbstractFactoryに実装し、setValue()メソッドより寧ろcreatePathAndSetValue()メソッドを呼び出してください。"Creating Objects"セクションで述べた制約は、ここでも適用されます。

変数がJavaBeanやcollectionを表している場合、Beanやcollectionをトラバースする事も出来ます:

                                                                       
 ...
 context.getVariables().declareVariable("book", myBook);
 String title = (String)context.getValue("$book/title);

 Book array[] = new Book[]{...};

 context.getVariables().declareVariable("books", array);

 String title = (String)context.getValue("$books[2]/title);
 

Custom Variable Pools

デフォルトでは、JXPathContextは変数のHashMapを生成します。しかし、JXPathを代わりとなる変数で機能させるため、Valiablesインターフェース(訳注:org.apache.commons.jxpath.Valiables)を独自に実装したものに置き換えても構いません。例えば、サーブレットコンテキストやHTTPリクエストあるいは同様の構造のものをカバーするValiablesインターフェースの実装を定義する事が出来ます。

例を見るには、org.apache.commons.jxpath.servletパッケージをご覧下さい。(訳注:org.apache.commons.jxpath.servlet.JXPathServletContextsが良いと思います)



Servlet Contexts

org.apache.commons.jxpath.servletパッケージは、様々なサーブレットコンテキスト(JSP用の"page", "request", "session", "application")の値に、XPathを使ってアクセスするのを容易にするクラス群を含んでいます。

このクラスの静的メソッドであるJXPathServletContextsをご覧下さい。これは、サーブレットに関連した様々なJXPathContextを割り当てます。

JSP Page Context

getPageContext(PageContext pageContext)メソッドによって返されるJXPathContextは、PageContext.findAttribute()メソッドを通じて全てのスコープへのアクセスが可能になっています。従って、"foo"という表現を使うと、"page", "request", "session", "application"コンテキストの順番に属性名"foo"を探していきます。

属性名の検索対象に制限を加える場合、定義済みの変数("page","request","session","application")を使います。例えば、"$session/foo"という表現だと、"session"属性名が"foo"であるものの値を抽出します。


Servlet Request Context

getRequestContext(ServletRequest request, ServletContext servletContext)メソッドは、"request",(セッションがあれば)"session","application"コンテキストの順にチェックして、コンテキストを返します。


HttpSession Context

getSessionContext(HttpSession session, ServletContext servletContext)メソッドは、"session","application"コンテキストの順にチェックして、コンテキストを返します。


ServletContext Context

最後に。getApplicationContext(ServletContext servletContext)メソッドは、"application"コンテキストをチェックして、コンテキストを返します。


これらのメソッドは、全て、JXPathContextをキャッシュし、対応するスコープの中でコンテキストを生成します。その後のメソッドの呼び出しでは、其の前に生成されたJXPathContextを使います。


Pointers

JXPathは、所謂「ポインタ(Pointer)」をサポートします。ポインタは、オブジェクト・グラフ内でのノードの場所を表します。例えば、このような事が出来ます:

                                                                       
Pointer ptr = context.getPointer("employees[$i]/addresses[$j]")

変数iの値は1、変数jの値は3であると仮定しましょう。ptr.asPath()メソッドを呼び出せば、完全な場所を記述するXPath表記が戻ります:"/employees[1]/addresses[3]"

オブジェクト・グラフ内で多くのノードがマッチするXPath記述の場合、JXPathに、該当するノード全てのポインタのコレクションを作らせる事が出来ます。

                                                                       
List homeAddresses = context.getPointer("//employee/address[@name='home']");

リスト内の各々のポインタは、オブジェクト・グラフ内の"home address"オブジェクト にマップします。

オブジェクト・グラフ内の同一ノードに繰り返しアクセスしようとする場合にポインタを 使うのも非常に良い考えです。

また、XPathが異なったコンテキスト(例えば、異なる変数値)で繰り返し評価される場合、 それらの評価の結果を残しておく必要があるかもしれません。 pointer.asPath()から生成されるポインタは、XPathと同様、コンテキスト非依存です。 従って、関連する変数や式が変わったとしても、ポインタは変わりません。

JXPathは、他の多くのXPathに比して非常に早く、ポインタから生成されるXPathを解釈するよう最適化されています。


Extension Functions

JXPathは、XPathの関数を何の変更もなしに(out of the box)無条件でサポートします。また、"標準の"拡張関数もサポートします。拡張関数は、完全にカスタムな拡張関数も含め、基本的にはJavaとのブリッジです。

Standard Extension Functions

標準拡張関数を使うと、オブジェクトのメソッドやクラス内の静的なメソッドの呼び出し、 コンストラクタを使用したオブジェクトの生成を行う事が出来るようになります。 全てのクラス名は、完全修辞されている必要があります。

どのように新規オブジェクトを生成するかご紹介します:

                                                                       
 Book book = (Book)context.
   getValue("com.myco.books.Book.new('John Updike')");

どのように静的メソッドを呼び出すかをご紹介します:

                                                                       
 Book book = (Book)context.
   getValue("com.myco.books.Book.getBestBook('John Updike')");

どのように通常のメソッドを呼び出すかをご紹介します:

                                                                       
 String firstName = (String)context.
   getValue("getAuthorsFirstName($book)");
 

見て分かるとおり、メソッドのターゲットは、関数内の第一番目のパラメタで指定されます。


Custom Extension Functions

カスタム拡張関数のコレクションは、 Collections of custom extension functions can be implemented as Functionsオブジェクトの実装、 あるいは、メソッドが拡張関数となるようなJavaクラスの実装となりえます。

以下のクラスが様々な書式設定処理を実装すると仮定しましょう:

                                                                       
 public class Formats {
    public static String date(Date d, String pattern){
        return new SimpleDateFormat(pattern).format(d);
    }
    ...
 }

JXPathContextにこのクラスを登録できます:

                                                                       
 context.setFunctions(new ClassFunctions(Formats.class, "format"));
 ...

 context.getVariables().declareVariable("today", new Date());
 String today =
     (String)context.getValue("format:date($today, 'MM/dd/yyyy')");

PackageFunctionsを使用してJavaクラスの全てのパッケージを登録する事も出来ます。

また、FunctionLibraryを ご覧下さい。これは、同じJXPathContextに複数の拡張関数のセットを登録可能とするクラスです。


Expression Context

カスタム関数は、評価しているコンテキスト内でアクセスされることが可能です。 ClassFunctionsおよびPackageFunctionsは、 ExpressionContext オブジェクトを最初の引数とするメソッドやコンストラクタを特別にサポートします。 このような拡張関数がinvokeされれば、ExpressionContextインターフェースを実装したオブジェクトが戻ります。 そこで、この関数は、現在評価されているコンテキスト内で"現在の"オブジェクトへのアクセスを得る事が出来ます。

                                                                       
public class MyExtenstionFunctions {
   public static boolean isDate(ExpressionContext context){
      Pointer pointer = context.getContextNodePointer();
      if (pointer == null){
        return false;
      }
      return pointer.getValue() instanceof Date;
   }
   ...
}

それから、この拡張関数をClassFunctionsを使って登録し、以下のように呼び出します:

                                                                       
  "//.[myext:isDate()]"

この表現を使って、オブジェクト・グラフ内の日付型の全てのノードを見つける事が出来ます。

デフォルトで、カレントコンテキスト(訳注:現在評価されているコンテキスト)が拡張関数に渡されます。 他のコンテキストを渡すには、ExpressionContextオブジェクトの引数を明示します。 注意:最初の引数がExpressionContextであれば、常にカレントコンテキストが渡されます。 故に、2種類のExpressionContextを宣言する必要がある場合もあります(一つがカレントコンテキストでもう一つがパラメタコンテキスト)。 例えば、

                                                                       
public class MyExtenstionFunctions {
   ...
   public static boolean contains(ExpressionContext current,
                            ExpressionContext context, Object value){
      Iterator iter = context.getContextNodeList().iterator();
      while (iter.hasNext()) {
          Pointer item = (Pointer)iter.next();
          if (item.getValue().equals(value)){
            return true;
          }
      }
      return false;
   }
}

この関数を呼び出す事で、ある特定の電話番号を持つ全ての人を検索する事が出来ます:

                                                                       
  "/addressBook/contact[myext:contains(phoneNumbers, '555-5555']"


Type Conversions

JXPathは、自動的に以下の型変換を行います:

変換前の型 変換後の型 演算
null primitive false, zero
any String toString()の呼び出し
Boolean any Number True = 1, false = 0
any Number any other Number 必要ならば切り詰め
String any primitive type String型のパース
array of length 1 any 配列の要素一つを受け取り、
(再帰的に)対応する型への変換を実施
collection of size 1 any コレクション型の要素一つを受け取り、
(再帰的に)対応する型への変換を実施
array array 同一サイズの新規配列を作成し、各要素に変換を行う
array Collection コレクション型を作成し、それに配列の全ての要素を追加する。 Note that it will only know how to create the collection if the type is a concrete class, List or Set
Collection array コレクション型と同一サイズの新規配列を作成し、コレクション型の全ての要素を配列へと変換・コピーを行う
Collection Collection コレクション型を作成し、それにコレクションの全てののソースをコピーする。Note that it will only know how to create the collection if the type is a concrete class, List or Set
ExpressionContext Collection, List, Vector, Set Creates a collection of type ArrayList,
ArrayList, Vector, HashSet respectively and
populates it with all current context node pointers
ExpressionContext any 現在のコンテキストのノードのポインタの値を受け取り、
(再帰的に)対応する型への変換を実施


Internationalization

DOMドキュメント用に、JXPathContextは、国際化XPath形式をサポートします。 以下のように、ロケール(locale)をXML要素で宣言することが出来ます:

                                                                       
     <book xml:lang="fr">Les Miserables</book>

特定の言語のノードを検索するために、XPathのlang関数を使う事が出来ます:

                                                                       
     "//book[lang('fr')]

"lang"関数(boolean型)は、DOMオブジェクト以外でも同様にサポートされています。 この関数は、JXPathContextでのLocaleセットを調べます(あるいは、セットされていなければ戻り値はデフォルトロケールです)。 JXPathContext.setLocale() をご覧下さい。

また、DOMドキュメントであろうがなかろうが、xml:lang属性(この属性の値はロケールの名前)を利用する事が出来ます。


Nested Contexts

異なるBeanでXPath解釈をする際に同じ変数セットを使う必要がある場合、別のコンテキストに変数を格納し、JavaBeanに新規JXPathContextを割り当てる度に親コンテキストとしてそのコンテキストを明記する、という手法を取るのは、道理に適った事です。こうすれば、全てのコンテキストを全て設定するといった無駄な時間をカットできます。

同じロジックが、共有拡張される関数、抽象型factory及びロケールにも適用されます。

                                                                       
 JXPathContext sharedContext = JXPathContext.newContext(null);
 sharedContext.getVariables().declareVariable("title", "Java");
 sharedContext.setFunctions(new MyExtensionFunctions());
 sharedContext.setLocale(Locale.CANADA);
 sharedContext.setFactory(new MyFactory());

 ...

 JXPathContext context = JXPathContext.newContext(sharedContext, auth);

 Iterator javaBooks =
      context.iterate("books[preprocessTitle(title) = $title]");
 


Compiled Expressions

JXPathが最初にある「表現」(訳注:xpathの事)を評価する際、コンパイルを行い、コンパイルされた表現をキャッシュします。 このメカニズムによって、コンパイルで生じるオーバーヘッドを軽減する事が出来ます。 ただ、いくつかのケースでは、JXPathのキャッシングが十分ではない事があります--- JXPathキャッシュにはサイズの制限があり、時々キャッシュがクリアされます。

XPath表現をプリコンパイルする方法の例です:

                                                                       
     CompiledExpression expr = context.compile(xpath);
     ...
     Object value = expr.getValue(context);

コンパイルされる表現は、以下の要件に従わなければなりません:

  • XPath表現の数が比較的少なく、それらのXPathが数回にわたって評価される必要がある
  • いくつかのXPathが初期化段階でプリコンパイルされる必要がある Some XPaths need to be precompiled at initialization time
  • いくつかのXPathの文法が、最初に使用される前にチェックされる必要がある


Customizing JXPath

JXPathは、色々なレベルでカスタマイズする事が出来ます。

  • JXPathが取得可能なJavaBeansのプロパティのリストをカスタマイズする独自のJXPathBeanInfoオブジェクトを作り出す事が出来ます
  • Map型に似たオブジェクト型のサポートを容易に加える事が出来ます。すべき事は、DynamicPropertyHandlerインターフェースを実装し、それをJXPathIntrospectorに登録する事です。
  • JXPathがデフォルトでサポートしていない任意のオブジェクトモデルの型のサポートを加える事が出来ます。このようなモデルの例は、代わりとなるXMLツリー(例:JDOMなど)の実装でしょう。これらのカスタムオブジェクトのプロパティをJXPathがトラバースできるよう、APIを1つか2つ実装する必要があります。
  • JXPathContextFactoryのレベルでのJXPathのカスタマイズが最も劇的でしょう--- 透過的にトップレベルAPIの全ての代替の実装を行う事が出来ます。
Custom JXPathBeanInfo

JXPathは、JavaBeansのプロパティを見つけるためにJavaBeansのイントロスペクション機能を使います。 JXPathBeanInfoを実装するカスタムクラスを使う事で、 代わりとなるプロパティリストを出す事が可能です(JXPathBeanInfoをご覧下さい)。


Custom DynamicPropertyHandler

Map型に似たオブジェクトのプロパティにアクセスする為に、DynamicPropertyHandlerインターフェース の様々な実装をJXPathは使います。

org.apache.commons.jxpath.servletパッケージには、DynamicPropertyHandlersのカスタムクラスの例がいくつかあります。


Custom Pointers and Iterators

設計上、複数モデルサポートは、 NodePointer 及びNodeIterator の概念によって可能となっています。 これらは、異なる種類のオブジェクト・グラフをトラバースするには異なるやり方で拡張される、シンプルな抽象クラスです。NodePointer/NodeIterator APIは、JavaBeansのようなモデルがあるようにデザインされました。これらは、インデックス化されるコレクションを直接サポートします。結果として、"foo[10]"といったXPathは、コレクションの型に対応し、"getFoo(9)"あるいは"getFoo()[9]"あるいは"getFoo().get(9)"で処理する事が出来ます。このような柔軟性は、抽象クラスのAPIによって十分よく隠蔽されているため、コレクションと同じ概念ではないオブジェクトモデル(DOMなど)のトラバースの自然な利用が可能になっています。

新規オブジェクトモデルへのサポートを加えるには、NodePointerFactory 同様、NodePointer及びNodeIteratorを独自に実装してください。 次に、新規factoryをJXPathContextReferenceImpl に登録してください。

この実例であるNodePointerFactories(の実装)をご覧下さい:

  • BeanPointerFactory works with JavaBeans
  • DynamicPointerFactory works with Dynamic beans like Map, HttpRequest and such
  • ContainerPointerFactory works with Container objects like XMLDocumentContainer
  • DOMPointerFactory works with DOM Nodes


Alternative JXPath Implementation

JXPathContextは、代わりとなるJXPathの実装を認めています。 JXPathContextを直接的に割り当てる代わりに、静的なnewContextメソッドを 呼び出す必要があるのは、そういう理由です。 このメソッドは、JXPathのふさわしい実装を特定する為にJXPathContextFactory APIを使います。 JXPathには、リファレンス実装(訳注:reference implementationの訳であるが、 「参考的実装」などといった形で一般的に普及させたい)と呼ばれるデフォルトの実装がバンドルされています。




Copyright © 1999-2007, Apache Software Foundation
Translated into Japanese by Tetsuya Kitahata , powered by Terra-International, Inc.
Original English Page would be found from HERE     --    ApacheNews    ASF プロジェクト一覧
Terra-International, Inc. -- テラ・インターナショナル
Special Thanks -- 【お問い合わせ/テキスト広告】