情報エクストラクタは、構造化されていないドキュメントから意味のある情報を検索して抽出します。この抽出された情報に基づいてドキュメントを検索する機能は、全文検索エンジンでサポートされるキーワード・ベースの検索より大幅に優れています。
ドキュメントのセマンティク索引付けによって、情報エクストラクタおよびアノテータを使用して、リレーショナル表に格納されているドキュメントにセマンティクに索引付けできる索引タイプが導入されます。セマンティクに索引付けされたドキュメントは、標準のSQL問合せ内でSEM_CONTAINS演算子を使用して検索できます。これらのドキュメントの検索条件は、次の例に示すとおり、ドキュメントから抽出された情報に基づいて機能するSPARQL問合せパターンを使用して表現されます。
SELECT docId FROM Newsfeed WHERE SEM_CONTAINS (article, ' { ?org rdf:type typ:Organization . ?org pred:hasCategory cat:BusinessFinance } ', ..) = 1
Oracle Databaseのドキュメントのセマンティク索引付けを容易にする主要コンポーネントは、次のとおりです。
拡張可能な情報エクストラクタ・フレームワーク: サードパーティの情報エクストラクタをデータベースにプラグインできます。
SEM_CONTAINS演算子: 標準のSQL問合せを使用して、抽出された情報に基づいて目的のドキュメントを識別します。
SEM_CONTAINS_SELECT補助演算子: SEM_CONTAINS演算子を使用して識別されたドキュメントの関連情報を戻します。
SemContext索引タイプ: 情報エクストラクタと対話して索引構造のドキュメント・セットから抽出された情報を管理し、ドキュメントに対するセマンティクに意味のある検索を容易にします。
ドキュメントに対して作成されたエクストラクタ・ポリシーおよびセマンティク索引を管理するためのアプリケーション・プログラミング・インタフェース(API)は、SEM_RDFCTX PL/SQLパッケージで提供されます。第12章に、SEM_RDFCTXパッケージのサブプログラムに関するリファレンス情報があります。
この章には次の項が含まれます。
情報エクストラクタは、通常、オントロジで支援された自然言語処理エンジンを使用して、構造化されていないドキュメントを処理し、そこから意味のある情報を抽出します。ドキュメントから抽出される情報の品質と完全性は、エクストラクタごとに異なります。一部のエクストラクタは単にエンティティを識別するのみですが(ドキュメントに基づく人、組織および地理的場所の名前など)、他のエクストラクタは識別したエンティティ間の関係やそれらのエンティティの追加記述の識別を試みます。ドキュメントから抽出された情報がセマンティク索引として管理されている場合、大規模なセットから特定のドキュメントを検索できます。
情報エクストラクタを使用して、リレーショナル表の列に格納されたドキュメントに対してセマンティク索引を作成できます。拡張可能なフレームワークによって、データベースからアクセス可能なサードパーティの情報エクストラクタをデータベースにプラグインできます。エクストラクタ用に作成されたオブジェクト型は、抽出ロジックをカプセル化し、エクストラクタを構成してRDF/XML形式の特定のドキュメントから抽出された情報を受信するメソッドを持ちます。
抽象タイプMDSYS.RDFCTX_EXTRACTORは、すべての情報エクストラクタに共通のインタフェースを定義します。この抽象タイプの実装は、特定の情報エクストラクタと対話して特定のドキュメントのRDF/XMLを生成します。このタイプの実装は、データベース・アプリケーションとして使用できるか、ネットワークにインストールされている(Webサービス・コールアウトを使用してアクセスされる)サードパーティの情報エクストラクタにアクセスできます。例4-1に、RDFCTX_EXTRACTOR抽象タイプの定義を示します。
例4-1 RDFCTX_EXTRACTOR抽象タイプの定義
create or replace type rdfctx_extractor authid current_user as object ( extr_type VARCHAR2(32), member function getDescription return VARCHAR2, member function rdfReturnType return VARCHAR2, member function getContext(attribute VARCHAR2) return VARCHAR2, member procedure startDriver, member function extractRDF(document CLOB, docId VARCHAR2) return CLOB, member function extractRdf(document CLOB, docId VARCHAR2, params VARCHAR2, options VARCHAR2 default NULL) return CLOB member function batchExtractRdf(docCursor SYS_REFCURSOR, extracted_info_table VARCHAR2, params VARCHAR2, partition_name VARCHAR2 default NULL, docId VARCHAR2 default NULL, preferences SYS.XMLType default NULL, options VARCHAR2 default NULL) return CLOB, member procedure closeDriver ) not instantiable not final /
RDFCTX_EXTRACTORタイプの特定の実装は、extr_type
属性にエクストラクタ・タイプの識別子を設定し、getDescription
メソッドを使用してエクストラクタ・タイプの短い説明を戻します。この抽象タイプのすべての実装で、抽出された情報がRDFトリプルとして戻されます。現在のリリースでは、RDFトリプルはRDF/XML形式を使用してシリアライズされることが予定されているため、rdfReturnType
メソッドは、'RDF/XML
'を戻す必要があります。
エクストラクタ・タイプの実装は、通常、独自のインタフェースを使用して外部情報エクストラクタを起動することで抽出ロジックをカプセル化するextractRDF
メソッドを使用し、抽出された情報をRDF/XML形式で戻します。抽出された情報を取得するためにサードパーティのエクストラクタが独自のXMLスキーマを使用する場合、XMLスタイル・シートを使用して同等のRDF/XMLを生成できます。startDriver
メソッドとcloseDriver
メソッドは、情報エクストラクタに関連するハウスキーピング操作を実行できます。オプションのparams
パラメータによって、エクストラクタは、必要な抽出のタイプに関する追加情報を取得できます(たとえば、要求される抽出品質など)。
エクストラクタ・タイプの実装では、オプションで、batchExtractRdf
メンバー・ファンクションの実装を提供することでバッチ・インタフェースをサポートできます。このファンクションは、入力パラメータdocCursor
を通じてカーソルを受け入れ、通常はそのカーソルを使用して各ドキュメントを取得し、ドキュメントから情報を抽出した後で、抽出した情報をextracted_info_table
表のpartition_name
パーティションによって識別される指定されたパーティションに挿入します。preferences
パラメータは、ポリシーに関連付けられたプリファレンス値を取得するために使用されます(4.8項およびSEM_RDFCTX.CREATE_POLICYのリファレンスの項を参照)。
getContext
メンバー・ファンクションは、属性名を受け入れ、その属性の値を戻します。現在、このファンクションは、バッチ・インタフェースをサポートするエクストラクタにのみ使用できます。属性名とそれに対応する可能な戻り値は次のとおりです。
BATCH_SUPPORT
属性に対する戻り値は、エクストラクタがバッチ・インタフェースをサポートするかどうかに応じて'YES
'または'NO
'です。
DBUSER
属性に対する戻り値は、(docCursor
パラメータによって識別される)カーソルから行を取得するためにデータベースに接続し、表extracted_info_table
に書込みを行うデータベース・ユーザーの名前です。
この情報は、索引付けされる表および表extracted_info_table
に適切な権限を付与するために使用されます。
startDriver
メソッドとcloseDriver
メソッドは、情報エクストラクタに関連するハウスキーピング操作を実行できます。
General Architecture for Text Engineering (GATE)エンジンのエクストラクタ・タイプは、RDFCTX_EXTRACTORタイプのサブタイプとして定義されます。このエクストラクタ・タイプの実装は、TCP接続を介してGATEエンジンにドキュメントを送信し、エンジンによって抽出された注釈をXML形式で受信して、その独自のXMLドキュメントをRDF/XMLドキュメントに変換します。GATEエンジンを構成してOracle Databaseと連携させる方法の詳細は、4.10項を参照してください。新しい情報エクストラクタを作成する例は、4.11項を参照してください。
Webサービスとしてデプロイされた情報エクストラクタは、RDFCTX_EXTRACTORタイプのサブタイプであるRDFCTX_WS_EXTRACTORタイプを拡張することで、データベースから起動できます。RDFCTX_WS_EXTRACTORタイプは、extractRDF
メソッドのWebサービス・コールアウトをカプセル化します(ネットワーク・ベース・エクストラクタの特定の実装によって、タイプ・コンストラクタに適切な属性値を設定することでその実装を再利用できます)。
Thomson Reuters Calaisは、Webサービス・コールアウトを使用してアクセスできるネットワーク・ベースの情報エクストラクタの一例です。RDFCTX_WS_EXTRACTORタイプのサブタイプであるCALAIS_EXTRACTORタイプは、Calais抽出ロジックをカプセル化し、それを使用してドキュメントにセマンティクに索引付けできます。CALAIS_EXTRACTORタイプは、それを使用してセマンティク索引を作成する前に、データベース・インスタンスに対して構成しておく必要があります(4.9項を参照)。
エクストラクタ・ポリシーは、ポリシーを使用して作成されたセマンティク索引の特性を決定する名前付きのディクショナリ・エンティティです。各エクストラクタ・ポリシーは、直接的または間接的にエクストラクタ・タイプのインスタンスを参照します。エクストラクタ・タイプのインスタンスを直接参照するエクストラクタ・ポリシーは、オントロジの追加のRDFモデルを含む他のエクストラクタ・ポリシーを構成するために使用できます。
次の例では、GATEエクストラクタ・タイプを使用して作成される基本エクストラクタ・ポリシーを作成しています。
begin sem_rdfctx.create_policy (policy_name => 'SEM_EXTR', extractor => mdsys.gatenlp_extractor()); end; /
次の例では、前述の例のポリシーによって抽出されたメタデータと、geo_ontology
というユーザー定義のRDFモデルを組み合せる依存エクストラクタ・ポリシーを作成しています。
begin sem_rdfctx.create_policy (policy_name => 'SEM_EXTR_PLUS_GEOONT', base_policy => 'SEM_EXTR', user_models => SEM_MODELS ('geo_ontology')); end; /
エクストラクタ・ポリシーを使用して、構造化されていないドキュメントを格納する列に1つ以上のセマンティク索引を作成できます(4.3項を参照)。
リレーショナル表のCLOBまたはVARCHAR2列に格納されたテキスト・ドキュメントは、セマンティクに意味のある検索を容易にするため、MDSYS.SEMCONTEXT索引タイプを使用して索引付けできます。索引の作成時に指定されたエクストラクタ・ポリシーによって、ドキュメントのセマンティク索引付けに使用される情報エクストラクタが決定されます。ドキュメントごとにRDFトリプルのセットとして取得された抽出情報は、セマンティク・データ・ストアで管理されます。セマンティク索引の各インスタンスは、対応するドキュメントから抽出されたRDFトリプルを保持するシステム生成のRDFモデルに関連付けられます。
次の例では、SEM_EXTR
というエクストラクタ・ポリシーを使用して、NEWSFEED表のARTICLE列のテキスト・ドキュメントにArticleIndex
というセマンティク索引を作成しています。
CREATE INDEX ArticleIndex on Newsfeed (article) INDEXTYPE IS mdsys.SemContext PARAMETERS ('SEM_EXTR');
索引に対して作成されたRDFモデルは、内部的に管理され、アプリケーション表には関連付けられません。このようなモデルに格納されているトリプルは、表の列に格納されたドキュメントを変更(更新、挿入、削除など)するために自動的に管理されます。1つのRDFモデルを使用して、表の列に格納されたすべてのドキュメントが索引付けされますが、モデルに格納されたトリプルは、抽出元のドキュメントに対する参照を管理するため、特定のドキュメントから抽出されたすべてのトリプルによって、RDFモデル内の個々のグラフが構成されます。セマンティクに索引付けされたドキュメントは、ドキュメントから抽出されたトリプルを処理するSPARQL問合せパターンを使用して検索できます。
ドキュメントのセマンティク索引を作成する場合、1つ以上のユーザー定義のRDFモデルを含むことが可能な基本エクストラクタ・ポリシーまたは依存ポリシーを使用できます。依存エクストラクタ・ポリシーで索引を作成する場合、SPARQLを使用して指定されたドキュメント検索パターンは、ドキュメントから抽出されたトリプルとユーザー定義モデルで定義されたトリプルを対象とすることができます。
複数のエクストラクタ・ポリシーを使用して索引を作成できますが、その場合、対応するエクストラクタによって抽出されたトリプルは、別々のRDFモデルで個別に管理されます。このような索引を使用するドキュメント検索問合せでは、問合せへの応答に使用される特定のポリシーを選択できます。たとえば、CITY_EXTR
というエクストラクタ・ポリシーを作成して特定のドキュメントから都市の名前を抽出できます(次の例のようにこのエクストラクタ・ポリシーをSEM_EXTRポリシーと組み合せて使用すると、セマンティク索引を作成できます)。
CREATE INDEX ArticleIndex on Newsfeed (article)
INDEXTYPE IS mdsys.SemContext PARAMETERS ('SEM_EXTR CITY_EXTR');
PARAMETERSリストの最初のエクストラクタ・ポリシーは、問合せが特定のポリシーを参照していない場合、デフォルト・ポリシーとみなされますが、次の例のようにSEM_RDFCTX.SET_DEFAULT_POLICYプロシージャを使用することでセマンティク索引のデフォルトのエクストラクタ・ポリシーを変更できます。
begin sem_rdfctx.set_default_policy (index_name => 'ArticleIndex', policy_name => 'CITY_EXTR'); end; /
標準のSQL文でSEM_CONTAINS演算子を使用して、リレーショナル表に格納されているドキュメントまたはドキュメント参照を検索できます。この演算子の構文は次のとおりです。
SEM_CONTAINS( column VARCHAR2 / CLOB, sparql VARCHAR2, policy VARCHAR2, aliases SEM_ALIASES, index_status NUMBER, ancoper NUMBER ) RETURN NUMBER;
column
およびsparql
属性は必須です。その他の属性はオプションです(それぞれNULL値を指定できます)。
column
属性では、セマンティクに索引付けされているドキュメントまたはドキュメントへの参照を格納しているリレーショナル表のVARCHAR2またはCLOB列を指定します。SEM_CONTAINS演算子によって使用するには、タイプMDSYS.SEMCONTEXTの索引をこの列に定義する必要があります。
sparql
属性は、SPARQL形式で表現されるドキュメント検索条件を定義する文字列リテラルです。
オプションのpolicy
属性では、通常はデフォルト・ポリシーをオーバーライドするため、エクストラクタ・ポリシーの名前を指定します。セマンティク・ドキュメント索引は、索引の作成時に指定された1つ以上のエクストラクタ・ポリシーを持つことが可能で、これらのポリシーの1つが、SEM_CONTAINSのコールでpolicy
属性がNULLの場合に使用されるデフォルトになります。
オプションのaliases
属性では、問合せパターンの修飾名の拡張に使用する、デフォルトの名前空間を含む1つ以上の名前空間を指定します。そのデータ型は、TABLE OF SEM_ALIAS
という定義を持つSEM_ALIASESです。各SEM_ALIAS要素により、名前空間IDと名前空間値が識別されます。SEM_ALIASデータ型は、(namespace_id VARCHAR2(30), namespace_val VARCHAR2(4000))
という定義を持ちます。
オプションのindex_status
属性は、1つ以上の伴意を含む依存ポリシーがSEM_CONTAINSの起動で使用される場合にのみ関連します。index_status
の値で、伴意の最小限必要な有効性ステータスを指定します。可能な値は、0
(VALIDの場合で、デフォルト)、1
(INCOMPLETEの場合)および2
(INVALIDの場合)です。
オプションのancoper
属性では、問合せでSEM_CONTAINS_SELECT補助演算子をこの演算子とともに使用する場合に使用されるバインディングとしての数値を指定します。ancoper
属性に指定する数値は、SEM_CONTAINS_SELECT補助演算子のoperbind
属性に指定された数値と同じである必要があります。
SEM_CONTAINS演算子は、指定した検索条件に一致するドキュメント・インスタンスごとに1を戻し、他のすべての場合は0を戻します。
SEM_CONTAINS演算子の使用方法の詳細とその例は、4.5項を参照してください。
SEM_CONTAINS_SELECT補助演算子を使用すると、いくつかの検索条件に一致する各ドキュメントの追加情報を戻すことができます。この補助演算子には、バインディングに同じ値を使用してSEM_CONTAINS_SELECT補助演算子のインスタンスとSEM_CONTAINS演算子を関連付ける単一の数値属性(operbind
)が含まれます。この補助演算子は、一致ドキュメントから追加情報を含むCLOB型のオブジェクトをSPARQL Query Results XML形式で書式設定した状態で戻します。
SEM_CONTAINS_SELECT補助演算子の構文は次のとおりです。
SEM_CONTAINS_SELECT( operbind NUMBER ) RETURN CLOB;
SEM_CONTAINS_SELECT補助演算子の使用方法の詳細とその例は、4.6項を参照してください。
SEM_CONTAINS演算子の起動にSEM_CONTAINS_COUNT補助演算子を使用できます。一致したドキュメントごとに、SEM_CONTAINSの起動で指定されたSPARQLグラフ・パターンの一致サブグラフの数が戻されます。
SEM_CONTAINS_COUNT補助演算子の構文は次のとおりです。
SEM_CONTAINS_COUNT( operbind NUMBER ) RETURN NUMBER;
次の抜粋例は、SEM_CONTAINS_COUNT補助演算子を使用して、一致したドキュメントごとに一致サブグラフの数を戻す方法を示しています。
SELECT docId, SEM_CONTAINS_COUNT(1) as matching_subgraph_count FROM Newsfeed WHERE SEM_CONTAINS (article, '{ ?org rdf:type class:Organization . ?org pred:hasCategory cat:BusinessFinance }', .., 1)= 1;
セマンティクに索引付けされたドキュメント(mdsys.SemContext索引タイプを使用して索引付けされたドキュメント)は、標準のSQL問合せ内でSEM_CONTAINS演算子を使用して検索できます。問合せで、SEM_CONTAINS演算子は2つ以上のパラメータを持つ必要があります(次の例のように、最初のパラメータはドキュメントが格納される列を指定するもので、2番目のパラメータはSPARQL問合せパターンとして表現されるドキュメント検索条件を指定するものです)。
SELECT docId FROM Newsfeed WHERE SEM_CONTAINS (article, '{ ?org rdf:type <http://www.example.com/classes/Organization> . ?org <http://example.com/pred/hasCategory> <http://www.example.com/category/BusinessFinance> }' )= 1;
SEM_CONTAINS演算子で指定されたSPARQL問合せパターンは、各ドキュメントに対応する個々のグラフに対して照合され、ドキュメントは、対応するグラフのトリプルが問合せパターンを満足させる場合に検索条件に一致するものとみなされます。前述の例で、SPARQL問合せパターンは、BusinessFinance
カテゴリに属するOrganization
を参照する個々のグラフ(ドキュメント)を識別します。SQL問合せによって、一致ドキュメントに対応する行が結果セットで戻されます。前述の例では、問合せで使用されるURIが基礎となるエクストラクタによって生成され、ドキュメントを検索するユーザーが使用中のエクストラクタによって生成されたプロパティと用語を認識していることが前提です。
1つ以上のユーザー定義のRDFモデルを含む依存エクストラクタ・ポリシーを使用して索引を作成する場合、ユーザー・モデルで表明されたトリプルは、すべてのドキュメントに共通とみなされます。このようなポリシーを含むドキュメント検索では、ユーザー・モデルのトリプルに結合された、ドキュメントに対応する個々のグラフのトリプルに対して検索条件がテストされます。たとえば、次の問合せでは、都市を州にマップする地理オントロジ(前述の例のgeo_ontology
RDFモデル)を使用して、ニューハンプシャー州の組織に言及しているすべての記事が識別されます。
SELECT docId FROM Newsfeed WHERE SEM_CONTAINS (article, '{ ?org rdf:type class:Organization . ?org pred:hasLocation ?city . ?city geo:hasState state:NewHampshire }', 'SEM_EXTR_PLUS_GEOONT', sem_aliases( sem_alias('class', 'http://www.myorg.com/classes/'), sem_alias('pred', 'http://www.myorg.com/pred/'), sem_alias('geo', 'http://geoont.org/rel/'), sem_alias('state', 'http://geoont.org/state/'))) = 1;
前述の問合せは、(4.2項の例で作成された)エクストラクタ・ポリシーのSEM_EXTR_PLUS_GEOONTに対する参照を使用して、索引付きドキュメントから抽出されたトリプルと、ユーザー・モデルのトリプルを結合して一致ドキュメントを検索します。この例で、エクストラクタ・ポリシーの名前は、対応する索引がこのポリシーで作成されている場合、またはこれが索引のデフォルトのエクストラクタ・ポリシーの場合はオプションです。問合せパターンで修飾名を使用する場合、SEM_CONTAINS演算子のオプション・パラメータでは、修飾名を拡張するために使用する名前空間を指定できます。
SPARQLベースのドキュメント検索では、SEM_MATCH問合せを通じてサポートされるSPARQL構文を使用できます。
SEM_CONTAINS_SELECT補助演算子を使用すると、SEM_CONTAINS演算子を使用して照合された各ドキュメントの追加情報を戻すことができます。具体的には、この演算子を使用して、SPARQLベースのドキュメント検索条件で使用される変数のバインディングを戻すことができます。この演算子は、SEM_CONTAINS演算子を補助するもので、次の例のように、この演算子の引数としてリテラル数値が使用され、SEM_CONTAINS演算子の特定のインスタンスに関連付けられます。
SELECT docId, SEM_CONTAINS_SELECT(1) as result FROM Newsfeed WHERE SEM_CONTAINS (article, '{ ?org rdf:type class:Organization . ?org pred:hasCategory cat:BusinessFinance }', .., 1)= 1;
SEM_CONTAINS_SELECT補助演算子によって、CLOBデータとしてSPARQL Query Results XML形式で変数のバインディングが戻されます。変数は、単一のドキュメントから複数のデータ・インスタンスにバインドされることがあり、その場合は変数のすべてのバインディングが戻されます。次の例は、前述の問合せの出力からの抜粋です(指定した検索条件に一致するドキュメントに対してSEM_CONTAINS_SELECT補助演算子によって戻された値)。
<results> <result> <binding name="ORG"> <uri>http://newscorp.com/Org/AcmeCorp</uri> </binding> </result> <result> <binding name="ORG"> <uri>http://newscorp.com/Org/ABCCorp</uri> </binding> </result> </results>
SEM_CONTAINS_SELECT補助演算子によって戻されるCLOB値に対してXMLTypeのインスタンスを作成し、属性値に基づいて結果をソートするXPath式を適用することで、検索結果をランク付けできます。
デフォルトでは、SEM_CONTAINS_SELECT補助演算子によって、SPARQLベースのドキュメント検索条件で使用されているすべての変数のバインディングが戻されます。ただし、変数のサブセットのみの値が検索に適切な場合、次の例のように、値を戻す必要のある変数の空白区切りのリストを持つSELECT句をSPARQLパターンに含めることができます。
SELECT docId, SEM_CONTAINS_SELECT(1) as result FROM Newsfeed WHERE SEM_CONTAINS (article, 'SELECT ?org ?city WHERE { ?org rdf:type class:Organization . ?org pred:hasLocation ?city . ?city geo:hasState state:NewHampshire }', .., 1) = 1;
ドキュメント検索操作の品質は、ドキュメントの索引付けに使用されるエクストラクタによって生成される情報の品質に応じて変化します。抽出される情報が不完全の場合、ドキュメントに注釈を追加できます。次の例に示すとおり、検索の品質を向上するため、SEM_RDFCTX.MAINTAIN_TRIPLESプロシージャを使用してRDFトリプルの形式で特定のドキュメントに注釈を追加できます。
begin sem_rdfctx.maintain_triples( index_name => 'ArticleIndex', where_clause => 'docid in (1,15,20)', rdfxml_content => sys.xmltype( '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:pred="http://example.com/pred/"> <rdf:Description rdf:about=" http://newscorp.com/Org/ExampleCorp"> <pred:hasShortName rdf:datatype="http://www.w3.org/2001/XMLSchema#string"> Example </pred:hasShortName> </rdf:Description> </rdf:RDF>')); end; /
前述の例に指定されている索引名とWHERE句によって、注釈が指定されたドキュメントの特定のインスタンスが識別され、渡されたRDF/XMLコンテンツが使用されて、それらのドキュメントに対応する個々のグラフに他のトリプルが追加されます。これによって、ドメイン・エキスパートとユーザー・コミュニティは、関連するトリプルを追加して一部のドキュメントに注釈を指定することで、検索の品質を向上できます。
ファイル・システムまたはネットワークに格納されているドキュメントに対してセマンティク索引付けを使用できます。この場合、表の列に外部ドキュメントへの参照を格納し、適切なエクストラクタ・ポリシーを使用してその列にセマンティク索引を作成します。
外部ドキュメントに索引を付けるには、次の例のように、SEM_RDFCTX.CREATE_POLICYプロシージャのpreferences
パラメータに割り当てられたXMLドキュメントを使用して、適切なプリファレンスによってエクストラクタ・ポリシーを定義します。
begin sem_rdfctx.create_policy ( policy_name => 'SEM_EXTR_FROM_FILE', extractor => mdsys.gatenlp_extractor()), preferences => sys.xmltype('<RDFCTXPreferences> <Datastore type="FILE"> <Path>EXTFILES_DIR</Path> </Datastore> </RDFCTXPreferences>')); end; /
プリファンレス・ドキュメントの<Datastore>
要素によって、索引付けするドキュメントで使用するリポジトリのタイプを指定します。type
属性の値がFILE
に設定されている場合、<Path>
要素によって、(SQL文のCREATE DIRECTORYを使用して作成された)データベースのディレクトリ・オブジェクトが識別されます。指定したエクストラクタ・ポリシーを使用して索引付けされた表の列は、次の例に示すとおり、ディレクトリ・オブジェクト内の個々のファイルに対する相対パスを含むことになります。
CREATE TABLE newsfeed (docid number, articleLoc VARCHAR2(100)); INSERT INTO into newsfeed (docid, articleLoc) values (1, 'article1.txt'); INSERT INTO newsfeed (docid, articleLoc) values (2, 'folder/article2.txt'); CREATE INDEX ArticleIndex on newsfeed (articleLoc) INDEXTYPE IS mdsys.SemContext PARAMETERS ('SEM_EXTR_FROM_FILE');
HTTPプロトコルを使用してアクセスされるドキュメントに索引を付けるには、次の抜粋に示すとおり、<Datastore>
要素のtype
属性にURL
を設定し、<Path>
要素に1つ以上のホストをリストしたプリファレンスを含むエクストラクタ・ポリシーを作成します。
<RDFCTXPreferences> <Datastore type="URL"> <Path>http://cnn.com</Path> <Path>http://abc.com</Path> </Datastore> </RDFCTXPreferences>
外部ドキュメントのセマンティク索引が作成されるスキーマは、次の例に示すとおり、外部オブジェクトへのアクセスに必要な権限(ファイアウォール外部のドキュメントにアクセスするために使用されるプロキシ・サーバーへのアクセス権限など)を持っている必要があります。
-- Grant read access to the directory object for FILE data store -- grant read on directory EXTFILES_DIR to SEMUSR; -- Grant connect access to set of hosts for URL data store -- begin dbms_network_acl_admin.create_acl ( acl => 'network_docs.xml', description => 'Normal Access', principal => 'SEMUSR', is_grant => TRUE, privilege => 'connect'); end; / begin dbms_network_acl_admin.assign_acl ( acl => 'network_docs.xml', host => 'cnn.com', lower_port => 1, upper_port => 10000); end; /
データベースでセマンティクに索引付けされた外部ドキュメントは、Microsoft Word、RTF、PDFなどの一般的な形式のいずれかである場合があります。この場合、Oracle Text機能を利用して、書式設定されたドキュメントからフィルタを通じてプレーン・テキスト・バージョンを抽出します(『Oracle Textリファレンス』でCTX_DOC.POLICY_FILTERプロシージャを参照してください)。書式設定されたドキュメントにセマンティクに索引を付けるには、次の抜粋に示すとおり、エクストラクタ・プリファレンスにCTXポリシーの名前を指定する必要があります。
<RDFCTXPreferences>
<Datastore type="FILE" filter="CTX_FILTER_POLICY">
<Path>EXTFILES_DIR</Path>
</Datastore>
</RDFCTXPreferences>
前述の例で、CTX_DDL.CREATE_POLICYプロシージャを使用して作成されたCTX_FILTER_POLICY
ポリシーは、スキーマ内に存在する必要があります。このプリファレンス・ドキュメントを使用してセマンティクに索引付けされた表の列には、指定したCTXポリシーを使用してプレーン・テキストが抽出される、書式設定されたドキュメントへのパスを格納できます。エクストラクタ・ポリシーに関連付けられた情報エクストラクタは、その後、RDF/XML形式でセマンティクを抽出するためにプレーン・テキストをさらに処理します。
RDFCTX_WS_EXTRACTORタイプのサブタイプであるCALAIS_EXTRACTORタイプによって、ネットワーク上の任意の場所にあるWebサービス・エンド・ポイントにアクセスできます(パブリックにアクセス可能な場所(OpenCalais.com
)を含む)。これを行うには、SYSDBA権限で接続し、次の例に示すとおり、対応するパラメータを設定してWebサービス・エンド・ポイント、SOAPアクションおよびライセンス・キーでCalaisエクストラクタ・タイプを構成する必要があります。
begin sem_rdfctx.set_extractor_param ( param_key => 'CALAIS_WS_ENDPOINT', param_value => 'http://api1.opencalais.com/enlighten/calais.asmx', param_desc => 'Calais web service end-point'); sem_rdfctx.set_extractor_param ( param_key => 'CALAIS_KEY', param_value => '<Calais license key goes here>', param_desc => 'Calais extractor license key'); sem_rdfctx.set_extractor_param ( param_key => 'CALAIS_WS_SOAPACTION', param_value => 'http://clearforest.com/Enlighten', param_desc => 'Calais web service SOAP Action'); end;
ファイアウォール外部のWebサービスへのアクセスを可能にするには、次の例のようにプロキシ・ホストのパラメータも設定する必要があります。
begin sem_rdfctx.set_extractor_param ( param_key => 'HTTP_PROXY', param_value => 'www-proxy.acme.com', param_desc => 'Proxy server'); end;
General Architecture for Text Engineering (GATE)は、オープン・ソースの自然言語プロセッサおよび情報エクストラクタです(http://gate.ac.uk
を参照)。GATEを使用して、データベースに格納されているドキュメントのセマンティク索引付けを実行できます。エクストラクタ・タイプmdsys.gatenlp_extractor
は、RDFCTX_EXTRACTORタイプのサブタイプとして定義されます。このエクストラクタ・タイプの実装によって、構造化されていないドキュメントをTCP接続を通じてGATEエンジンに送信し、対応する注釈を受信して、それらをユーザー指定のXMLスタイル・シートに従ってRDFに変換します。
情報抽出のリクエストは、GATEコンポーネントをインスタンス化し、事前決定済のポートで抽出リクエストをリスニングするサーバー・ソケット実装によって処理されます。GATEリスナーのホストとポートは、次の例に示すとおり、使用するmdsys.gatenlp_extractor
タイプのすべてのインスタンスに対してデータベースに記録されます。
begin sem_rdfctx.set_extractor_param ( param_key => 'GATE_NLP_HOST', param_value => 'gateserver.acme.com', param_desc => 'Host for GATE NLP Listener '); sem_rdfctx.set_extractor_param ( param_key => 'GATE_NLP_PORT', param_value => '7687', param_desc => 'Port for Gate NLP Listener'); end;
サーバー・ソケット・アプリケーションは、構造化されていないドキュメントを受信し、目的のタイプの注釈を含む注釈セットを構成します。セット内の各注釈は、入力ドキュメントからの関連フレーズやドメイン固有の機能などの追加機能を含むようにカスタマイズできます。結果となる注釈セットは、(gate.corpora.DocumentXmlUtils
JavaパッケージのannotationSetToXml
メソッドを使用して) XMLにシリアライズされ、ソケット・クライアントに戻されます。
GATEリスナーのサンプルのJava実装は、OTNのコード・サンプルおよび使用例のページからダウンロードできます(このページの詳細は、1.11項「セマンティク・データの例(PL/SQLとJava)」を参照してください)。
データベースのmdsys.gatenlp_extractor
実装は、XMLでエンコードされた注釈セットを受信し、それをXMLスタイル・シートを使用してRDF/XMLに変換します。mdsys.gatenlp_extractor
実装で使用されるデフォルト・スタイル・シート(4.17項を参照)は、タイプをインスタンス化する際にカスタム・スタイル・シートに置換できます。
次の例では、カスタム・スタイル・シートを使用するエクストラクタ・ポリシーを作成して、GATEエクストラクタによって生成された注釈セットからRDFを生成しています。
begin sem_rdfctx.create_policy (policy_name => 'GATE_EXTR', extractor => mdsys.gatenlp_extractor( sys.XMLType('<?xml version="1.0"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > .. </xsl:stylesheet>'))); end; /
RDFCTX_EXTRACTORまたはRDFCTX_WS_EXTRACTORエクストラクタ・タイプを拡張して新しいエクストラクタ・タイプを作成できます。拡張されるエクストラクタ・タイプには、Webサービス・コールを使用してアクセスできる必要があります。新しいエクストラクタ・タイプが作成されるスキーマには、サブタイプを作成できるように追加の権限を付与する必要があります。たとえば、新しいエクストラクタ・タイプがスキーマRDFCTXUに作成される場合、次のコマンドを入力してそのスキーマにUNDERおよびRDFCTX_ADMIN権限を付与する必要があります。
GRANT under ON mdsys.rdfctx_extractor TO rdfctxu; GRANT rdfctx_admin TO rdfctxu;
たとえば、情報エクストラクタで受信ドキュメントを処理し、抽出された情報を含むXMLドキュメントを戻すことができると仮定します。PL/SQLラッパーを使用して情報エクストラクタを起動できるようにするには、次の例のように、対応するエクストラクタ・タイプの実装を作成します。
create or replace type rdfctxu.info_extractor under rdfctx_extractor ( xsl_trans sys.XMLtype, constructor function info_extractor ( xsl_trans sys.XMLType ) return self as result, overriding member function getDescription return VARCHAR2, overriding member function rdfReturnType return VARCHAR2, overriding member function extractRDF(document CLOB, docId VARCHAR2) return CLOB ) / create or replace type body rdfctxu.info_extractor as constructor function info_extractor ( xsl_trans sys.XMLType ) return self as result is begin self.extr_type := 'Info Extractor Inc.'; -- XML style sheet to generate RDF/XML from proprietary XML documents self.xsl_trans := xsl_trans; return; end info_extractor; overriding member function getDescription return VARCHAR2 is begin return 'Extactor by Info Extractor Inc.'; end getDescription; overriding member function rdfReturnType return VARCHAR2 is begin return 'RDF/XML'; end rdfReturnType; overriding member function extractRDF(document CLOB, docId VARCHAR2) return CLOB is ce_xmlt sys.xmltype; begin EXECUTE IMMEDIATE 'begin :1 = info_extract_xml(doc => :2); end;' USING IN OUT ce_xmlt, IN document; -- Now pass the ce_xmlt through RDF/XML transformation -- return ce_xmlt.transform(self.xsl_trans).getClobVal(); end extractRdf; end;
前述の例の説明:
作成されたinfo_extractor
エクストラクタ・タイプの実装は、基礎となる情報エクストラクタで使用される独自のXMLスキーマからRDF/XMLを生成するため、コンストラクタに設定されたXMLスタイル・シートに依存します。
extractRDF
ファンクションでは、info_extract_xml
ファンクションが目的の情報エクストラクタと通信し、渡されたドキュメントから抽出された情報を含むXMLドキュメントが戻されることが前提となります。
XMLスタイル・シートがXMLドキュメントに適用され、同等のRDF/XMLが生成されます(これはextractRDF
ファンクションから戻されます)。
次の構文を使用して、レンジ・パーティション表のVARCHAR2またはCLOB列にローカル索引を作成できます。
CREATE INDEX <index-name> … LOCAL;
次の例では、レンジ・パーティション表とその表に対するローカル・セマンティク索引を作成しています。
CREATE TABLE part_newsfeed ( docid number, article CLOB, cdate DATE) partition by range (cdate) (partition p1 values less than (to_date('01-Jan-2001')), partition p2 values less than (to_date('01-Jan-2004')), partition p3 values less than (to_date('01-Jan-2008')), partition p4 values less than (to_date('01-Jan-2012')) ); CREATE INDEX ArticleLocalIndex on part_newsfeed (article) INDEXTYPE IS mdsys.SemContext PARAMETERS ('SEM_EXTR') LOCAL;
ローカル・セマンティク索引のすべてのパーティションに、同じポリシー・セットに対して生成された内容が含まれることに注意してください。ローカル索引にALTER INDEX文を使用して、セマンティク索引パーティションに関連付けられたポリシーを追加または削除する場合、各パーティションに関連付けられた同じポリシー・セットを維持する必要があります。この結果を得るには、パーティションのセットを反復するループでALTER INDEX文を使用します。(セマンティク索引の変更の詳細は、4.13項を参照してください。)
この項では、セマンティク索引でのALTER INDEX文の使用について説明します。ローカル・セマンティク索引では、ALTER INDEX文は指定したパーティションに適用されます。セマンティク索引のALTER INDEXコマンドの一般的な構文は、次のとおりです。
ALTER INDEX <index-name> REBUILD [PARTITION <index-partition-name>] [PARAMETERS ('-<action_for_policy> <policy-name>')];
PARAMETERS句がALTER INDEX文に含まれない場合、セマンティク索引(または索引パーティション)の内容は、索引に現在関連付けられているすべてのポリシーに対して再構築されます。次に2つの例を示します。
ALTER INDEX ArticleIndex REBUILD; ALTER INDEX ArticleLocalIndex REBUILD PARTITION p1;
<action_for_policy>でadd_policy
を使用して、セマンティク索引(または索引パーティション)に新しいベース・ポリシーまたは依存ポリシーの内容を追加できます。依存ポリシーが追加される場合や、そのベース・ポリシーがすでに索引の一部ではない場合、ベース・ポリシーの内容も(ベース・ポリシー定義の一部として指定されたエクストラクタを起動することで)暗黙的に追加されます。次に例を示します。
ALTER INDEX ArticleIndex REBUILD PARAMETERS ('-add_policy MY_POLICY');
<action_for_policy>でrebuild_policy
を使用して、索引に現在関連付けられている既存ポリシーのセマンティク索引(または索引パーティション)の内容を再構築できます。次に例を示します。
ALTER INDEX ArticleIndex REBUILD PARAMETERS ('-rebuild_policy MY_POLICY');
<action_for_policy>でdrop_policy
を使用して、セマンティク索引(または索引パーティション)から既存のベース・ポリシーまたは依存ポリシーに対応する内容を削除できます。ベース・ポリシーの内容の削除は、それが索引(または索引パーティション)の唯一のポリシーである場合、またはそれが索引(または索引パーティション)に関連付けられた依存ポリシーによって使用されている場合、失敗することに注意してください。
次の例では、索引からポリシーの内容を削除しています。
ALTER INDEX ArticleIndex REBUILD PARAMETERS ('-drop_policy MY_POLICY');
CREATE INDEX文とALTER INDEX文では、エクストラクタに必要なパラメータの受渡しが可能です。これらのパラメータは、extractRdf
メソッドとbatchExtractRdf
メソッドのparams
パラメータを使用してエクストラクタに渡されます。次の2つの例にその使用方法を示します。
CREATE INDEX ArticleIndex on Newsfeed (article) INDEXTYPE IS mdsys.SemContext PARAMETERS ('SEM_EXTR=(NE_ONLY)'); ALTER INDEX ArticleIndex REBUILD PARAMETERS ('-add_policy MY_POLICY=(NE_ONLY)');
ドキュメント中心の推論とは、各ドキュメントから個別に推論する機能です。異なる2つのドキュメントから抽出されたトリプルは、まとめて推論用に使用できません。これとは対照的に、より一般的なコーパス中心の推論では、複数のドキュメントから抽出されたトリプルの組合せから新しいトリプルを推論できます。
検索結果にドキュメントが含まれることは、そのドキュメントのみを対象に抽出または推論された(あるいはその両方が行われた)トリプルに基づくため(コーパスの他のドキュメントから抽出または推論された(あるいはその両方が行われた)トリプルは、そのドキュメントの選択に何の役割も果たさないため)、ドキュメント中心の推論はドキュメント検索アプリケーションに適しています。(たとえば、データの信頼性またはドキュメント作成者のバイアスに違いがあるためにドキュメント間に一貫性がない場合、ドキュメント中心の推論が推奨されることがあります。)
ドキュメント中心の推論を実行するには、SEM_APIS.CREATE_ENTAILMENTプロシージャのコールでoptions => 'LOCAL_NG_INF=T'
を指定して、名前付きグラフ・ベースのローカル推論(2.2.11.2項を参照)を使用します。
ドキュメント中心の推論を通じて作成された伴意をセマンティク索引の内容として含めるには、例4-2に示すとおり、依存ポリシーを作成してそのポリシーをセマンティク索引に追加します。
例4-2 ドキュメント中心の推論の使用
-- Create entailment 'extr_data_inf' using document-centric inference -- assuming: -- model_name for semantic index based on base policy: 'RDFCTX_MOD_1' -- (model name is available from the RDFCTX_INDEX_POLICIES view; -- see Section 4.16.2, "RDFCTX_INDEX_POLICIES View") -- ontology: dataOntology -- rulebase: OWL2RL -- options: 'LOCAL_NG_INF=T' (for document-centric inference) BEGIN sem_apis.create_entailment('extr_data_inf', models_in => sem_models('RDFCTX_MOD_1', 'dataOntology'), rulebases_in => sem_rulebases('OWL2RL'), options => 'LOCAL_NG_INF=T'); END; / -- Create a dependent policy to augment data extracted using base policy -- with content of entailment extr_data_inf (computed in previous statement) BEGIN sem_rdfctx.create_policy ( policy_name => 'SEM_EXTR_PLUS_DATA_INF', base_policy => 'SEM_EXTR', user_models => NULL, user_entailments => sem_models('extr_data_inf')); END; / -- Add the dependent policy to the ARTICLEINDEX index. EXECUTE sem_rdfctx.add_dependent_policy('ARTICLEINDEX','SEM_EXTR_PLUS_DATA_INF');
この項では、セマンティク索引付けのメタデータを含むビューについて説明します。
現在のスキーマに定義されたエクストラクタ・ポリシーに関する情報は、MDSYS.RDFCTX_POLICIESビューに保持されます(表4-1に、このビューの列を示します(1つの行が1つのエクストラクタ・ポリシーに対応します))。
表4-1 MDSYS.RDFCTX_POLICIESビューの列
列名 | データ型 | 説明 |
---|---|---|
POLICY_OWNER |
VARCHAR2(32) |
エクストラクタ・ポリシーの所有者 |
POLICY_NAME |
VARCHAR2(32) |
エクストラクタ・ポリシーの名前 |
EXTRACTOR |
MDSYS.RDFCTX_EXTRACTOR |
エクストラクタ・タイプのインスタンス |
IS_DEPENDENT |
VARCHAR2(3) |
エクストラクタ・ポリシーがベース・ポリシーに依存する場合は |
BASE_POLICY |
VARCHAR2(32) |
依存ポリシーの場合、ベース・ポリシーの名前 |
USER_MODELS |
MDSYS.RDF_MODELS |
依存ポリシーの場合、そのポリシーに含まれるRDFモデルのリスト |
現在のスキーマに定義されたセマンティク索引と、その索引の作成に使用されるエクストラクタ・ポリシーに関する情報は、MDSYS.RDFCTX_POLICIESビューに保持されます(表4-2に、このビューの列を示します(1つの行がセマンティク索引とエクストラクタ・ポリシーの1つの組合せに対応します))。
表4-2 MDSYS.RDFCTX_INDEX_POLICIESビューの列
列名 | データ型 | 説明 |
---|---|---|
INDEX_OWNER |
VARCHAR2(32) |
セマンティク索引の所有者 |
INDEX_NAME |
VARCHAR2(32) |
セマンティク索引の名前 |
INDEX_PARTITION |
VARCHAR2(32) |
索引パーティションの名前(LOCAL索引のみ) |
POLICY_NAME |
VARCHAR2(32) |
エクストラクタ・ポリシーの名前 |
EXTR_PARAMETERS |
VARCHAR2(100) |
エクストラクタに指定されたパラメータ |
IS_DEFAULT |
VARCHAR2(3) |
POLICY_NAMEが索引のデフォルトのエクストラクタ・ポリシーである場合は |
STATUS |
VARCHAR2(10) |
|
RDF_MODEL |
VARCHAR2(32) |
索引データを保持するRDFモデルの名前 |
現在のスキーマでセマンティク索引を作成または保持する際に発生した例外に関する情報は、MDSYS.RDFCTX_INDEX_EXCEPTIONSビューに保持されます(表4-3に、このビューの列を示します(1つの行が1つの例外に対応します))。
表4-3 MDSYS.RDFCTX_INDEX_EXCEPTIONSビューの列
列名 | データ型 | 説明 |
---|---|---|
INDEX_OWNER |
VARCHAR2(32) |
例外に関連付けられたセマンティク索引の所有者 |
INDEX_NAME |
VARCHAR2(32) |
例外に関連付けられたセマンティク索引の名前 |
POLICY_NAME |
VARCHAR2(32) |
例外に関連付けられたエクストラクタ・ポリシーの名前 |
DOC_IDENTIFIER |
VARCHAR2(38) |
例外に関連付けられたドキュメントの行識別子(ROWID) |
EXCEPTION_TYPE |
VARCHAR2(13) |
例外のタイプ |
EXCEPTION_CODE |
NUMBER |
例外に関連付けられたエラー・コード |
EXCEPTION_TEXT |
CLOB |
例外に関連付けられたテキスト |
EXTRACTED_AT |
TIMESTAMP |
例外が発生した時刻 |
この項では、XMLでエンコードされた注釈セットをRDF/XMLに変換するためにmdsys.gatenlp_extractor
実装で使用されるデフォルトのXMLスタイル・シートをリストします。(このエクストラクタの詳細は、4.10項を参照してください。)
<?xml version="1.0"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:output encoding="utf-8" indent="yes"/> <xsl:param name="docbase">http://xmlns.oracle.com/rdfctx/</xsl:param> <xsl:param name="docident">0</xsl:param> <xsl:param name="classpfx"> <xsl:value-of select="$docbase"/> <xsl:text>class/</xsl:text> </xsl:param> <xsl:template match="/"> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:prop="http://xmlns.oracle.com/rdfctx/property/"> <xsl:for-each select="AnnotationSet/Annotation"> <rdf:Description> <xsl:attribute name="rdf:about"> <xsl:value-of select="$docbase"/> <xsl:text>docref/</xsl:text> <xsl:value-of select="$docident"/> <xsl:text>/</xsl:text> <xsl:value-of select="@Id"/> </xsl:attribute> <xsl:for-each select="./Feature"> <xsl:choose> <xsl:when test="./Name[text()='majorType']"> <rdf:type> <xsl:attribute name="rdf:resource"> <xsl:value-of select="$classpfx"/> <xsl:text>major/</xsl:text> <xsl:value-of select="translate(./Value/text(), ' ', '#')"/> </xsl:attribute> </rdf:type> </xsl:when> <xsl:when test="./Name[text()='minorType']"> <xsl:element name="prop:hasMinorType"> <xsl:attribute name="rdf:resource"> <xsl:value-of select="$docbase"/> <xsl:text>minorType/</xsl:text> <xsl:value-of select="translate(./Value/text(), ' ', '#')"/> </xsl:attribute> </xsl:element> </xsl:when> <xsl:when test="./Name[text()='kind']"> <xsl:element name="prop:hasKind"> <xsl:attribute name="rdf:resource"> <xsl:value-of select="$docbase"/> <xsl:text>kind/</xsl:text> <xsl:value-of select="translate(./Value/text(), ' ', '#')"/> </xsl:attribute> </xsl:element> </xsl:when> <xsl:when test="./Name[text()='locType']"> <xsl:element name="prop:hasLocType"> <xsl:attribute name="rdf:resource"> <xsl:value-of select="$docbase"/> <xsl:text>locType/</xsl:text> <xsl:value-of select="translate(./Value/text(), ' ', '#')"/> </xsl:attribute> </xsl:element> </xsl:when> <xsl:when test="./Name[text()='entityValue']"> <xsl:element name="prop:hasEntityValue"> <xsl:attribute name="rdf:datatype"> <xsl:text> http://www.w3.org/2001/XMLSchema#string </xsl:text> </xsl:attribute> <xsl:value-of select="./Value/text()"/> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:element name="prop:has{translate( substring(./Name/text(),1,1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')}{ substring(./Name/text(),2)}"> <xsl:attribute name="rdf:datatype"> <xsl:text> http://www.w3.org/2001/XMLSchema#string </xsl:text> </xsl:attribute> <xsl:value-of select="./Value/text()"/> </xsl:element> </xsl:otherwise> </xsl:choose> </xsl:for-each> </rdf:Description> </xsl:for-each> </rdf:RDF> </xsl:template> </xsl:stylesheet>