3 Oracle Multimedia PL/SQLフォト・アルバム・サンプル・アプリケーション

Oracle Multimedia PL/SQL Web Toolkitフォト・アルバム・サンプル・アプリケーションは、Oracle Multimediaオブジェクト型を使用したメディアのアップロードおよび取得Webアプリケーションです。このアプリケーションは、PL/SQL GatewayおよびPL/SQL Web Toolkitを使用します。

このアプリケーションでは、次のことを想定しています。

  • PL/SQL GatewayおよびPL/SQL Web Toolkitを使用するPL/SQLアプリケーションの開発に精通している。

  • Oracle Multimedia PL/SQL Web Toolkitフォト・アルバム・サンプル・アプリケーションをすでにインストールおよび構成している。

Oracle Multimedia PL/SQL Web Toolkitフォト・アルバム・サンプル・アプリケーションは、Oracle Technology Network (OTN)からダウンロード可能なOracle Database Examplesのメディアからインストールできます。Oracle Database Examplesメディアをインストールした後、サンプル・アプリケーション・ファイルとREADME.txtファイルは次の場所にあります。

<ORACLE_HOME>/ord/http/demo/plsqlwtk (LinuxおよびUNIXの場合)

<ORACLE_HOME>\ord\http\demo\plsqlwtk (Windowsの場合)

この章では、PL/SQL Web Toolkitフォト・アルバム・サンプル・アプリケーションの実行方法を説明します。このサンプル・アプリケーションをインストールおよび構成する場合の追加要件および手順については、このサンプル・アプリケーションのREADME.txtファイルを参照してください。

この章では、次の内容を説明します。

関連項目:

PL/SQL Gatewayのメディア・アップロードおよび取得プロシージャを作成するサンプル・アプリケーションは、「PL/SQL Gateway用のOracle Multimedia Code Wizardサンプル・アプリケーション」を参照してください

3.1 PL/SQLフォト・アルバム・サンプル・アプリケーションの概要

このトピックでは、Oracle Multimedia PL/SQL Web Toolkitフォト・アルバム・サンプル・アプリケーションの設定プロセスについて説明します。

Oracle Multimedia PL/SQL Web Toolkitフォト・アルバム・サンプル・アプリケーションは、次の操作の実行方法を示します。

  • Oracle Multimedia Imageオブジェクト型を使用して、Oracle Databaseに格納されているメディア・データをアップロード、取得および処理する。

  • Oracle Multimediaのイメージ・メタデータ・メソッドとOracle XML DBのXML文書管理機能、フルテキスト検索およびOracle Textの検索機能を組み合せ、バイナリ・イメージ・ファイルに埋め込まれているメタデータを抽出、格納および検索できるソリューションを作成する。

  • ユーザーから新規メタデータを収集し、そのメタデータをXML文書にフォーマットし、Oracle Multimediaイメージ・オブジェクト型を使用してその文書をバイナリ・イメージで格納します。

インストール時に、このフォト・アルバム・アプリケーションは次の説明に重要な複数のスキーマ・オブジェクトを作成します。これらのオブジェクトには、次のCREATE TABLE文で定義されるphotos表が含まれます。

CREATE TABLE photos( id           NUMBER PRIMARY KEY,
                     description  VARCHAR2(40) NOT NULL,
                     metaORDImage XMLTYPE,
                     metaEXIF     XMLTYPE,
                     metaIPTC     XMLTYPE,
                     metaXMP      XMLTYPE,
                     image        ORDSYS.ORDIMAGE,
                     thumb        ORDSYS.ORDIMAGE )
--
-- store full-size and thumbnail images as SecureFiles LOBS
--
LOB(image.source.localdata)  STORE AS SECUREFILE
LOB(thumb.source.localdata)  STORE AS SECUREFILE
--
-- and bind the XMLType columns to the Oracle Multimedia metadata schemas
XMLType COLUMN metaORDImage
  STORE AS SecureFile CLOB
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/ordimage"
  ELEMENT "ordImageAttributes"
XMLType COLUMN metaEXIF
  STORE AS SecureFile CLOB
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/exif"
  ELEMENT "exifMetadata"
XMLType COLUMN metaIPTC
  STORE AS SecureFile CLOB
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/iptc"
  ELEMENT "iptcMetadata"
XMLType COLUMN metaXMP
  STORE AS SecureFile CLOB
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/xmp"
  ELEMENT "xmpMetadata";

image列およびthumb列のデータ型は、Oracle Multimediaイメージ・オブジェクト型として定義されます。これらの列は、それぞれフルサイズ・イメージおよび生成される縮小イメージの格納に使用されます。LOB記憶域句は、データベースにフルサイズおよび縮小イメージをSecureFiles LOBに格納するよう指示します。このLOBは、バイナリ・データに対して最もパフォーマンスが高い記憶域オプションです。

また、この表では、4種類の異なるイメージ・データを含むXML文書を格納するために、XMLType型の4つの列を定義します。各列は、特定のOracle Multimediaメタデータ・スキーマにバインドされます。各メタデータ・スキーマでは、メタデータ・ドキュメントのデータ・モデルを正確に定義します。これらのスキーマは、データベース作成時に、Oracle XML DBに登録されます。列の定義では、XMLメタデータ・ドキュメントを管理するために、データベースでは非構造化記憶域を使用することを指定します。非構造化記憶域を使用してXMLを管理する利点は、完全なドキュメントを高速に取得できることと、XMLIndex索引を使用してXPathベースの問合せのパフォーマンスを向上させる機能があることです。

インストール時に、このフォト・アルバム・アプリケーションは他のスキーマ・オブジェクトも作成します。これらのスキーマ・オブジェクトには、メタデータ検索を高速にする、CONTEXTテキスト索引およびXMLIndex索引という2種類の索引が含まれます。

CONTEXT型は、イメージに関する記述情報を含むすべての列に対するテキスト索引です。これらの列には、VARCHAR2データ型であるPHOTOS.DESCRIPTIONと、4つのXMLType列(PHOTOS.METAIPTCPHOTOS.METAEXIFPHOTOS.METAXMPおよびPHOTOS.METAORDIMAGE)が含まれます。CONTEXTテキスト索引は、ユーザーが写真をキーワードまたは語句で検索できるフォト・アルバム検索機能を実装することによって、メタデータ検索の速度を上げるために使用されます。

CONTEXTテキスト索引は、次の文によって作成されます。(この例では、フォト・アルバム・アプリケーションがSCOTTスキーマにインストールされていると想定します。)

-- Create preference PA_CTXIDX.
ctx_ddl.create_preference('SCOTT.PA_CTXIDX', 'MULTI_COLUMN_DATASTORE');
 
-- Create a multicolumn datastore.
ctxcols := 'description, '                   ||
            'SCOTT.photo_album.getClob(METAIPTC), ' ||
            'SCOTT.photo_album.getClob(METAEXIF), ' ||
            'SCOTT.photo_album.getClob(METAXMP), '  ||
            'SCOTT.photo_album.getClob(METAORDIMAGE)';
ctx_ddl.set_attribute( ctxpref, 'COLUMNS', ctxcols );
 
 
-- Create the CONTEXT text index.
create  index pa_ctx_idx on photos(description)
indextype is ctxsys.context
parameters ( 'DATASTORE SCOTT.PA_CTXIDX' );

XMLIndex索引は、ユーザーに特定の種類のイメージ・メタデータのみの検索を許可し、検索対象をXML文書の特定の部分に限定することで、メタデータ検索の速度を上げるために使用されます。たとえば、次の文では、XMLType型の列に対するexistsNode( )問合せ速度を上げるために、XMLIndex型の3つのテキスト索引を作成します。

create index pa_path_iptc_idx  on photos( metaIptc )
 indextype is XDB.XMLIndex;
 
create index pa_path_exif_idx  on photos( metaExif )
 indextype is XDB.XMLIndex;
 
create index pa_path_xmp_idx  on photos( metaXMP )
 indextype is XDB.XMLIndex;

インストール中に、PL/SQL Gatewayで定義したとおりに、次のCREATE TABLE文でドキュメント・アップロード表が定義されます。

CREATE TABLE PHOTOS_UPLOAD( name           VARCHAR2(256) UNIQUE NOT NULL,
                            mime_type      VARCHAR2(128),
                            doc_size       NUMBER,
                            dad_charset    VARCHAR2(128),
                            last_updated   DATE,
                            content_type   VARCHAR2(128),
                            blob_content   BLOB )
-- 
-- store BLOBs as SecureFiles LOBs
-- 
LOB(blob_content)  STORE AS SECUREFILE;

PL/SQL Gatewayを使用してアップロードされた各イメージは、PHOTOS_UPLOAD表に格納されます。アップロード・プロシージャ(insert_new_photo)は、アップロードされたイメージを、指定されたPHOTOS_UPLOAD表からphotosというフォト・アルバム・アプリケーションの表に自動的に移動します。

関連項目:

3.2 PL/SQLフォト・アルバム・サンプル・アプリケーションの実行

このトピックでは、PL/SQLフォト・アルバム・アプリケーションの実行方法について説明します。

セットアップ・タスクを完了してPL/SQLフォト・アルバム・アプリケーションを構築し、(README.txtファイルの説明に従って)データベース・アクセス記述子(DAD)エントリを作成すると、このアプリケーションを実行する準備ができます。

Webブラウザのアドレス・フィールドで、次のURLを入力します。

<protocol><hostname:port-number>/photoalbum
  1. <protocol>フィールドには、http://と入力します。
  2. <hostname:port-number>フィールドには、HTTPサーバーが実行されているシステムのホスト名とポート番号を入力します。

このフォト・アルバム・アプリケーションを初めて起動した際、その時点でアルバムに格納されているすべてのイメージが表示されます。アプリケーションを初めてインストールした直後は、デフォルトで、フォト・アルバムには何も入っていません。新しい写真をアップロードするには、「Upload new photo」をクリックします。写真の説明およびイメージ・ファイルの名前を入力するか、ディレクトリ内のイメージ・ファイルの位置を参照します。次に、「Upload photo」をクリックします。

新しい写真が追加されたフォト・アルバムの内容が表示されます。縮小イメージをクリックすると、写真が原寸で表示されます。このフォト・アルバム・アプリケーションに縮小イメージではなくテキスト「view image」が表示される場合、アップロードされたイメージのフォーマットがOracle Multimediaで認識されていません。「view image」をクリックすると、原寸イメージが表示されます。

前述の手順に従って、フォト・アルバム・アプリケーションに自由に写真をロードできます。

3.3 PL/SQLフォト・アルバム・サンプル・アプリケーションの説明

PL/SQLフォト・アルバム・アプリケーションは、1つのPL/SQLパッケージに編成された、PL/SQLプロシージャおよびファンクションのセットとして実装されています。

これらのPL/SQLプロシージャおよびファンクションは、いくつかのデータベース機能を組み合せてアプリケーションを作成します。Oracle Multimediaは、イメージ・データを格納および処理するために使用されます。さらに、イメージからメタデータを抽出し、イメージに新しいメタデータを埋め込むためにも使用されます。XMLType機能は、XMLメタデータ・ドキュメントの格納および処理に使用されます。Oracle Text索引は、2種類のメタデータ検索の速度を向上するために使用されます。最後に、PL/SQL Web Toolkitは、HTMLページを作成し、メディア・コンテンツを配信するために使用されます。

PL/SQLフォト・アルバム・アプリケーションのユーザー・インタフェースは、一連のWebページで構成されます。これらのWebページを使用して、タスク・セットを実行できます。このトピックではタスクおよびWebページについて紹介し、この後の項で詳細を説明します。

各Webタスク・ページ上部近くにあるナビゲーション・バーを使用して、このフォト・アルバム・アプリケーションを検索できます。ナビゲーション・バーの一番左のエントリに、現在のWebページ名が表示されます。右には、現在のページからアクセス可能なその他のWebページへのリンクがあります。各Webタスク・ページには、アプリケーションのホーム・ページである「View album」ページへのリンクが含まれます。

PL/SQLフォト・アルバム・サンプル・アプリケーションのページ

ここで概説する次のトピックでは、PL/SQLフォト・アルバム・アプリケーションの各ページについて説明します。

  • フォト・アルバムの参照

    「View album」ページを使用して、フォト・アルバムのすべてのイメージの縮小サイズ・バージョンと、各縮小イメージの下に配置される説明リンクを表示します。縮小イメージを選択すると、原寸イメージが表示されます。イメージの説明リンクを選択すると、そのイメージのすべてのメタデータが表示されます。「View album」ページは、フォト・アルバム・アプリケーションのホームページです。

  • フォト・アルバムへのイメージの追加

    「Upload photo」ページを使用して、新規イメージの説明およびローカル・コンピュータ上のイメージの位置までのディレクトリ・パスを収集するための、簡単なフォームを表示します。「Upload photo」ボタンをクリックすると、イメージがブラウザによってWebサーバーに送信され、アップロードしたイメージがデータベースに格納されます。

  • キーワードまたは語句でのイメージの検索

    「Search album」ページを使用して、すべてのイメージ・メタデータのフルテキスト検索を開始するためにキーワードまたは語句を収集するアルバム検索フォームを表示します。フォト・アルバム・アプリケーションは、データベースのすべてのイメージについて、特定のキーワードまたは語句を含むメタデータに対する問合せを行います。検索結果は、一連の縮小イメージとして表示されます。アルバム検索フォームは、「View album」ページからも使用できます。

  • 原寸イメージの表示

    「View entry」ページを使用して、イメージがアップロードされたときにそのイメージに対して入力された説明テキストとともに、指定した写真の原寸イメージを表示します。

  • イメージ・メタデータの調査

    「View metadata」ページを使用して、アップロード時にイメージから抽出されたすべてのメタデータを表示します。4種類までのメタデータを表示できます。

  • 新規XMPメタデータのイメージへの書込み

    「Write XMP metadata」ページを使用して、5つのメタデータ属性の入力を収集するフォームを表示します。これらの属性は、バイナリ・イメージに埋め込まれたXML文書に書式設定されます。新規XMPメタデータは、既存のすべてのXMPメタデータを上書きします。

  • 特定のメタデータ属性を含むイメージの検索

    「Search metadata」ページを使用して、入力を収集し、高度なメタデータ検索を実行します。検索するメタデータの種類を指定できます。特定の文書に含まれる指定したタグに検索を限定することもできます。検索結果は、一連の縮小イメージとして表示されます。

関連項目:

3.3.1 フォト・アルバムの参照

フォト・アルバム・アプリケーションの「View album」ページを使用して、フォト・アルバムのコンテンツの参照や、その他のフォト・アルバム機能へのアクセスができます。

このフォト・アルバム・アプリケーションのホームページである「View album」では、フォト・アルバムの内容を縮小イメージで4列に表示します。また、各縮小イメージは、「View entry」ページにもリンクされています。縮小イメージのリンクをクリックすると、アプリケーションは、「View entry」ページに原寸イメージで表示されます。「View album」ページの各縮小イメージの下には、イメージがアルバムにアップロードされたときに入力されたイメージの説明があります。この説明も「View metadata」ページにリンクされていて、「View metadata」ページでは、この写真に対するすべてのメタデータを調べることができます。

「View album」ページの上部付近には、すべてのフォト・アルバム・メタデータに対してフルテキスト検索を行うための、ユーザー入力が可能なテキスト入力フィールド(長方形のボックス)があります。テキスト・フィールドの右にある「Search」ボタンで、検索を開始します。検索結果は、「Search album」ページに表示されます。

「View album」ページ上部には、ナビゲーション・バーがあり、他のフォト・アルバム・ページへのリンクが含まれています。「View album」ページから、「Search metadata」ページまたは「Upload photo」ページに移動できます。

図3-1に、複数のイメージを含むアルバムの「View album」ページを示します。

図3-1 イメージがアップロードされている「View album」ページ

図3-1の説明が続きます
「図3-1 イメージがアップロードされている「View album」ページ」の説明

PL/SQLプロシージャview_albumprint_albumprint_image_linkおよびdeliver_mediaは、「View album」ページを実装する主要なアプリケーション・コンポーネントです。view_albumプロシージャは、1つのオプションの引数をとるパブリック・プロシージャです。デフォルトでは、引数はNULL値です。「Search album」ページのテキスト入力フィールドに入力した文字列を、引数にすることもできます。検索引数がNULLの場合、SELECT文は、photos表のすべてのエントリからid列、description列およびthumb列を取得します。検索文字列がNULLでない場合、SELECT文はCONTAINS演算子を使用して、検索文字列と一致するメタデータを持つイメージに結果セットを制限します。

例3-1に、view_albumプロシージャの関連するいくつかのコード行を示します。

SELECT文はカーソル変数album_curにバインドされ、プロシージャprint_albumに渡されます。このプロシージャはHTML出力を作成します。

print_albumプロシージャは、出力を4列の表に書式設定するHTMLタグを作成するために、PL/SQL Web ToolkitのHTPおよびHTFパッケージを使用します。表の各セルには、2つのリンクまたは2つのアンカー・タグが含まれます。1つ目のリンクは、「View entry」ページへのリンクで、イメージを原寸で表示します。このアンカーは、PHOTO_ALBUM.VIEW_ENTRYによって実装され、entry_idを問合せ文字列の入力引数として渡します。縮小イメージの長さが0(ゼロ)以外の場合、アンカー・リンクのコンテンツ(縮小イメージ)であるHTML <img>タグを作成するために、print_image_linkプロシージャがコールされます。文字列thumbおよびentry_idは、イメージの説明、縮小イメージの高さおよび幅とともに、print_image_linkプロシージャに渡されます。これらの値は<img>タグの作成に使用されます。

イメージがOracle Multimediaでサポートしていないフォーマットの場合、アプリケーションは、イメージの縮小イメージを作成できません。この場合、アンカー・リンクのコンテンツはテキストのビュー・イメージになります。

例3-2に、print_albumプロシージャの関連するいくつかのコード行を示します。

プロシージャprint_image_linkは、height引数およびwidth引数を使用して、<img>タグのheight属性およびwidth属性に移入します。description引数は、alt属性用のテキストの作成に使用されます。description引数が空の場合は、デフォルトの文字列が構成されます。最後に、2つの問合せ文字列の引数mediaおよびentry_idを使用して、src属性がURL PHOTO_ALBUM.DELIVER_MEDIAに設定されます。media引数は、配信されるイメージが縮小イメージか原寸イメージかを制御します。entry_id引数は、配信されるイメージを指定します。

例3-3に、print_image_linkプロシージャの関連するいくつかのコード行を示します。

プロシージャdeliver_mediaは、データベースからイメージ・コンテンツをフェッチします。If-Modified-Since HTTPリクエスト・ヘッダーが、イメージの最終変更時刻と比較されます。イメージが変更されていない場合、ブラウザでキャッシュからイメージを表示できるという内容のレスポンスが送信されます。イメージが変更されている場合は、イメージのMIMEタイプおよび最終変更時刻が、イメージ・コンテンツとともにWebサーバーに送信されます。

例3-4に、deliver_mediaプロシージャの関連するいくつかのコード行を示します。

例3-1 プロシージャview_album

   --
   -- no search criteria so fetch all entries
   --
   IF search IS NULL THEN
     OPEN album_cur FOR
       SELECT id, description, thumb
       FROM photos
       ORDER BY id;
     print_album( album_cur, 'The photo album is empty.' );
     CLOSE album_cur;
   ELSE
   --    -- use the full-text index to select entries matching the search criteria
   --
     OPEN album_cur FOR
       SELECT id, description, thumb
       FROM photos
       WHERE CONTAINS( description, trim(search) ) > 0
       ORDER BY id;
     print_album( album_cur, 'No photos were found.' );
     CLOSE album_cur;
   END IF; 

例3-2 プロシージャprint_album

       -- escape the description text
       sc_description := htf.escape_sc( entry.description );
 
       --
       -- Display the thumbnail image as an anchor tag which can be used
       -- to display the full-size image. If the image format is not
       -- supported by Oracle Multimedia, then a thumbnail would not have been
       -- produced when the image was uploaded, so use the text '[view
       -- image]' instead of the thumbnail.
       --
 
       htp.print( '<td headers="c' || colIdx || '" align="center" >
                   <a href="PHOTO_ALBUM.VIEW_ENTRY?entry_id=' ||
                   entry.id || '">' );
       IF entry.thumb.contentLength > 0
       THEN
           print_image_link( 'thumb', entry.id, sc_description,
                             entry.thumb.height, entry.thumb.width );
       ELSE
           htp.prn( '[view image]' );
       END IF;
       htp.print( '</a>' );
 
       -- Create link to the metadata
       htp.prn('<br>');
       htp.anchor( curl=>'PHOTO_ALBUM.VIEW_METADATA?entry_id=' || entry.id,
                   ctext=>sc_description );
       htp.prn('</td>');

例3-3 プロシージャprint_image_link

 -- add height and width to tag if non zero
 IF height > 0 AND width > 0 THEN
   attributes := attributes || ' height=' || height || ' width=' || width;
 END IF;
 
 -- create an alt text if none given
 IF alt IS NULL THEN
   IF type = 'thumb' THEN
     alt2 := 'thumb-nail image ';
   ELSE
     alt2 := 'full-size image ';
   END IF;
   alt2 := alt2 || 'for album entry ' || entry_id;
 ELSE
   alt2 := alt;
 END IF;
 
 htp.img( curl=>'PHOTO_ALBUM.DELIVER_MEDIA?media=' || type ||
                  ampersand || 'entry_id=' || entry_id,
            calt=>alt2, cattributes=>attributes ); 

例3-4 プロシージャdeliver_media

   --
   -- Fetch the thumbnail or full-size image from the database.
   --
   IF media = 'thumb'
   THEN
       SELECT thumb INTO local_image FROM photos WHERE id = entry_id;
   ELSE
       SELECT image INTO local_image FROM photos WHERE id = entry_id;
   END IF;
 
   --
   -- Check update time if browser sent If-Modified-Since header
   --
   IF ordplsgwyutil.cache_is_valid( local_image.getUpdateTime() )
   THEN
     owa_util.status_line( ordplsgwyutil.http_status_not_modified );
     RETURN;
   END IF;
 
   --
   -- Set the MIME type and deliver the image to the browser.
   --
   owa_util.mime_header( local_image.mimeType, FALSE );
   ordplsgwyutil.set_last_modified( local_image.getUpdateTime() );
   owa_util.http_header_close();
 
   IF owa_util.get_cgi_env( 'REQUEST_METHOD' ) <> 'HEAD' THEN
     wpg_docload.download_file( local_image.source.localData );
   END IF; 

3.3.2 フォト・アルバムへのイメージの追加

フォト・アルバム・アプリケーションの「Upload photo」ページを使用して、フォト・アルバムにさらにコンテンツを追加できます。

「Upload photo」ページは、フォト・アルバムへの新規イメージの追加に使用されます。このページには、2つのテキスト入力フィールドがあるフォームが表示されます。「Description:」フィールドには、イメージを説明する単語または短い語句を任意に入力できます。「File name:」フィールドには、イメージ・ファイルの名前を入力するか、「Browse」をクリックして、 アップロードするイメージの位置を検索します。「File name:」フィールドの下にある「Upload photo」ボタンを押すと、アップロード操作が開始されます。イメージが正常にアップロードされると、「View album」ページが表示されます。このページから、フォト・アルバムのコンテンツを表示できます。

「Upload photo」ページ上部には、ナビゲーション・バーがあり、他のフォト・アルバム・ページへのリンクが含まれています。「Upload photo」ページから、「View album」ページに戻るか、「Search metadata」ページを選択できます。

図3-2に、すべてのフィールドが入力されている「Upload photo」ページを示します。

図3-2 入力されている「Upload photo」ページ

図3-2の説明が続きます
「図3-2 入力されている「Upload photo」ページ」の説明

PL/SQLプロシージャview_upload_formprint_upload_formおよびinsert_new_photoは、「Upload photo」ページを実装する主要なアプリケーション・コンポーネントです。view_upload_formおよびprint_upload_formは、表示されるHTMLページを作成します。ページには、例3-5に示すformタグが含まれます。フォームのターゲットは、PHOTO_ALBUM.INSERT_NEW_PHOTOです。

例3-5に、print_upload_formプロシージャの関連するいくつかのコード行を示します。

プロシージャinsert_new_photoは、フォームを受信し、入力を処理し、データベースに新規イメージを格納します。

最初に、insert_new_photoが、ファイル名がアップロード・フォームに入力されていることを確認します。イメージ・コンテンツのサイズ、MIMEタイプおよびBLOBロケータがドキュメント・アップロード表から選択され、イメージの長さが0(ゼロ)でないかを確認します。descriptionフィールドが空白の場合、ファイル名を使用して説明が作成されます。

次に、ORDSYS.ORDIMAGE( )のコンストラクタをコールし、photos表に格納される新しい行のthumbおよびimage ORDImageオブジェクト型列を空のBLOBで初期化します。SQLのSELECT FOR UPDATE文によって、新しく初期化された縮小イメージおよび原寸イメージのオブジェクト型列が更新対象としてフェッチされます。DBMS_LOB.COPY操作によって、アップロード表からimage ORDImageオブジェクト型列にイメージがロードされます。

ORDImageオブジェクト・メソッドのsetProperties( )がイメージを読み込み、イメージ・オブジェクト属性を設定します。一部のイメージ・フォーマットをインラインで表示できないブラウザもあるため、このサンプル・アプリケーションでは、get_preferred_formatファンクションをコールすることで、BMPフォーマットのイメージをJPEG(色が8ビットを超えるイメージ)またはGIFF(色が9ビット未満のイメージ)イメージ・フォーマットに変換します。processCopy( )操作が原寸イメージに実行され、縮小イメージが作成されます。

ORDImageオブジェクトのgetMetadata( )メソッドがコールされ、サポートされているすべての種類のイメージ・メタデータが抽出されます。ドキュメントを正しい列に格納できるメタデータの型を判断するために、リターン・ベクトルの各XML文書のルート要素が調べられます。

その後、SQL UPDATE文が、原寸イメージ、縮小イメージおよびメタデータ・ドキュメントをデータベースに格納します。プロシージャsync_indexesが、テキスト索引を強制的に更新するためにコールされます。最後に、フォーム・データの入力内容が、ドキュメント・アップロード表から削除されます。アップロードが成功したことを示すメッセージがブラウザに表示され、ブラウザは「View album」ページにリダイレクトされます。

例3-6に、insert_new_photoプロシージャの関連するいくつかのコード行を示します。

例3-5 プロシージャprint_upload_form

<form action="PHOTO_ALBUM.INSERT_NEW_PHOTO"
method="post"
enctype="multipart/form-data">
database. 

例3-6 プロシージャinsert_new_photo

   --
   -- Make sure a file name has been provided. If not, display an error
   -- message, then re-display the form.
   --
   IF new_photo IS NULL OR LENGTH( new_photo ) = 0
   THEN
       print_page_header;
       print_error( 'Please supply a file name.' );
       print_upload_form;
       print_page_trailer( TRUE );
       return;
   END IF;
 
   --
   -- Get the length, MIME type and the BLOB of the new photo from the
   -- upload table.
   --
   SELECT doc_size,
          mime_type,
          blob_content
   INTO   upload_size,
          upload_mime_type,
          upload_blob
   FROM photos_upload
   WHERE name = new_photo;
 
   --
   -- Make sure we have a valid file. 
   --
   IF upload_size = 0
   THEN
       print_page_header;
       print_heading( 'Error message' );
       htp.print( '<hr size="-1"><p>Please supply a valid image file.</p>' );
       print_upload_form;
       print_page_trailer( TRUE );
       return;
   END IF;
 
   --
   -- If the description is blank, then use the file name.
   --
   IF c_description IS NULL
   THEN
       c_description := new_photo;
       pos := INSTR( c_description, '/', -1 );
       IF pos > 0
       THEN
           c_description := SUBSTR( c_description, pos + 1 );
       END IF;
       c_description := SUBSTR( 'Image from file: ' ||
                        c_description || '.', 1, 40 );
   END IF;
   --
   -- Insert a new row into the table, returning the newly allocated sequence
   -- number.
   INSERT INTO photos ( id, description, metaExif, metaIPTC, metaXMP,
                        image, thumb )
   VALUES ( photos_sequence.nextval, c_description, NULL, NULL, NULL,
                ORDSYS.ORDIMAGE(), ORDSYS.ORDIMAGE() )
   RETURN id
   INTO new_id;
 
   --
   -- Fetch the newly initialized full-size and thumbnail image objects.
   --
   SELECT image,
          thumb
   INTO new_image,
        new_thumb
   FROM photos
   WHERE id = new_id
   FOR UPDATE;
 
   --
   -- Load the photo from the upload table into the image object.
   --
   DBMS_LOB.COPY( new_image.source.localData, upload_blob, upload_size );
   new_image.setLocal(); 
   --
   -- Set the properties. If the image format is not recognized, then
   -- the exception handler will set the MIME type and length from the
   -- upload table.
   --
   BEGIN
       new_image.setProperties();
   EXCEPTION
       WHEN OTHERS THEN
            new_image.contentLength := upload_size;
            new_image.mimeType := upload_mime_type;
   END;
 
   --
   -- Some image formats are supported by Oracle Multimedia but cannot be 
   -- displayed inline by a browser. The BMP format is one example.
   -- Convert the image to a GIF or JPEG based on number of colors in the
   -- image.
   --
   IF new_image.contentFormat IS NOT NULL AND
      ( new_image.mimeType = 'image/bmp' OR
        new_image.mimeType = 'image/x-bmp' )
   THEN
       BEGIN
           new_image.process(
                        'fileFormat=' ||
                        get_preferred_format( new_image.contentFormat ) ); 
       EXCEPTION
           WHEN OTHERS THEN
               NULL;
       END;
   END IF;
 
   --
   -- Try to copy the full-size image and process it to create the thumbnail.
   -- This may not be possible if the image format is not recognized.
   --
   BEGIN
       new_image.processCopy( thumb_scale, new_thumb );
   EXCEPTION
       WHEN OTHERS THEN
           new_thumb.deleteContent();
           new_thumb.contentLength := 0;
   END;
  --
   -- fetch the metadata and sort the results
   --
   BEGIN
     metav := new_image.getMetadata( 'ALL' );
     FOR i IN 1..metav.count() LOOP
       meta_root := metav(i).getRootElement();
       CASE meta_root
         WHEN 'ordImageAttributes' THEN xmlORD := metav(i);
         WHEN 'xmpMetadata'  THEN xmlXMP  := metav(i);
         WHEN 'iptcMetadata' THEN xmlIPTC := metav(i);
         WHEN 'exifMetadata' THEN xmlEXIF := metav(i);
         ELSE NULL;
       END CASE;
     END LOOP;
   EXCEPTION
     WHEN OTHERS THEN
       NULL;
   END;
 
   --
   -- Update the full-size and thumbnail images in the database.
   -- Update metadata columns 
   --
   UPDATE photos
   SET image = new_image,
       thumb = new_thumb,
       metaORDImage = xmlORD,
       metaEXIF = xmlEXIF,
       metaIPTC = xmlIPTC,
       metaXMP = xmlXMP
   WHERE id = new_id;
 
   --    -- update the text indexes
   --    sync_indexes;
 
   --
   -- Delete the row from the upload table.
   --
   DELETE FROM photos_upload WHERE name = new_photo;
   COMMIT;
 
   --
   -- Redirect browser to display full album.
   --    print_page_header(
       '<meta http-equiv="refresh" content="2;url=PHOTO_ALBUM.VIEW_ALBUM">' );
   print_heading( 'Photo successfully uploaded into photo album' );

3.3.3 キーワードまたは語句でのイメージの検索

フォト・アルバム・アプリケーションの「View album」ページと「Search album」ページを使用して、フォト・アルバム内のコンテンツを検索できます。

「View album」ページおよび「Search album」ページを使用して、フォト・アルバムに格納されているメタデータのキーワード検索または語句検索を実行できます。いずれかのページで、「Full text search:」テキスト入力フィールドにキーワードまたは語句を入力し、「Search」をクリックします。このフォト・アルバム・アプリケーションは、CONTEXTテキスト索引を使用して、入力したテキストを含むメタデータを持つイメージを検索します。検索に成功すると、一致したイメージの縮小イメージが4列の表で表示されます。縮小イメージを選択して原寸イメージを表示するか、縮小イメージの下にある説明リンクを選択してイメージのメタデータを表示します。検索に失敗すると、「No photos were found」というメッセージが表示されます。

「Search album」ページ上部には、ナビゲーション・バーがあり、他のフォト・アルバム・ページへのリンクが含まれています。「Search album」ページから、「View album」ページに戻るか、「Search metadata」ページまたは「Upload photo」ページを選択します。

図3-3に、検索操作に成功し、結果が表示されている「Search album」ページを示します。

図3-3 「Search album」ページでの結果表示

図3-3の説明が続きます
「図3-3 「Search album」ページでの結果表示」の説明

フォト・アルバムのフルテキスト検索は、view_albumプロシージャによって実装されます。

3.3.4 原寸イメージの表示

フォト・アルバム・アプリケーションの「View entry」ページを使用して、フォト・アルバムで原寸イメージとその説明を表示できます。

縮小イメージを選択すると、アプリケーションによって「View entry」ページが表示されます。このページに、イメージの説明および原寸イメージが表示されます。

「View entry」ページ上部には、ナビゲーション・バーがあり、他のフォト・アルバム・ページへのリンクが含まれています。「View entry」ページから、「View album」ページに戻るか、「View metadata」ページ、Write metadataページ、「Search metadata」ページまたは「Upload photo」ページのいずれかを選択します。

図3-4に、イメージの説明および原寸イメージが表示されている「View entry」ページを示します。

図3-4 原寸イメージが表示されている「View entry」ページ

図3-4の説明が続きます
「図3-4 原寸イメージが表示されている「View entry」ページ」の説明

PL/SQLプロシージャview_entryprint_image_linkおよびdeliver_mediaは、「View entry」ページを実装する主要なアプリケーション・コンポーネントです。プロシージャview_entryは、photos表のイメージを一意に特定する単一のパラメータentry_idを受け取ります。説明およびイメージ・オブジェクトは、photos表からフェッチされます。プロシージャprint_image_linkは、HTML <img>タグを作成し、プロシージャdeliver_mediaをコールしてイメージ・コンテンツをフェッチします。

例3-7に、view_entryプロシージャの関連するいくつかのコード行を示します。

例3-7 プロシージャview_entry

   --
   -- Fetch the row.
   --
   BEGIN
     SELECT htf.escape_sc(description), image
     INTO sc_description, photo
     FROM photos
     WHERE id = entry_id;
     EXCEPTION
     WHEN no_data_found THEN
       print_error( 'Image <b>' || htf.escape_sc(entry_id) ||
                    '</b> was not found.</p>' );
       print_page_trailer( TRUE );
       return;
   END;
 
   print_image_link( 'image', entry_id, sc_description,
                      photo.height, photo.width );

3.3.5 イメージ・メタデータの調査

フォト・アルバム・アプリケーションの「View metadata」ページを使用して、フォト・アルバム内のイメージのメタデータを表示できます。

「View metadata」ページを使用して、指定したイメージのすべてのメタデータを調べることができます。通常、「View album」ページで縮小イメージの下にある説明リンクを選択して、このページにアクセスします。ナビゲーション・バーから「View metadata」リンクを選択しても、このページにアクセスできます。「View metadata」ページには、イメージの縮小イメージが表示されます。縮小イメージの右に、このイメージのメタデータ・ドキュメントのリストがあります。リストの各エントリは、「View metadata」ページのメタデータ・ドキュメントにリンクされています。

「View metadata」ページ上部には、ナビゲーション・バーがあり、他のフォト・アルバム・ページへのリンクが含まれています。「View metadata」ページから、「View album」ページに戻るか、「View entry」ページ、Write metadataページ、「Search metadata」ページまたは「Upload photo」ページのいずれかを選択します。

図3-5に、イメージの2種類のメタデータ(XMPおよびORDIMAGE)が表示されている「View metadata」ページを示します。

図3-5 アップロードしたイメージのメタデータが表示されている「View metadata」ページ

図3-5の説明が続きます
「図3-5 アップロードしたイメージのメタデータが表示されている「View metadata」ページ」の説明

PL/SQLプロシージャview_metadataおよびprint_metadataは、「View metadata」ページを実装する主要なアプリケーション・コンポーネントです。プロシージャview_metadataには、photos表のイメージを一意に識別する引数entry_idが渡されます。SELECT文は、指定したエントリのすべてのXMLtypeメタデータ列を取得します。メタデータ列がNULLでない場合は、HTML <pre>タグ内のXMLドキュメントを表示するためにプロシージャprint_metadataがコールされます。

例3-8に、view_metadataプロシージャの関連するいくつかのコード行を示します。

print_metadataプロシージャは、XMLType文書を引数として受け入れます。CLOBとして文書にアクセスするために、getClobVal( )メソッドが使用されます。CLOBのコンテンツは、ループに読み込まれ、htp.printsプロシージャを使用してHTMLページに書式設定されます。htp.printsプロシージャは、「<」および「>」文字を無視するため、Webブラウザによって適切にレンダリングされます。

例3-9に、print_metadataプロシージャの関連するいくつかのコード行を示します。

例3-8 プロシージャview_ metadata

   --
   -- Fetch the row.
   --
   SELECT metaOrdImage, metaEXIF, metaIPTC, metaXMP
   INTO   metaO, metaE, metaI, metaX
   FROM   photos
   WHERE  id = entry_id;
 
   -- display the EXIF metadata
   IF metaE IS NOT NULL THEN
     htp.print( '<span class="bigBlue" id="exifMetadata">EXIF</span>' );
     htp.print( '<br><pre>' );
     print_metadata( metaE );      htp.print( '</pre>' );
   END IF;

例3-9 プロシージャprint_ metadata

   metaClob := meta.getClobVal();
   len := dbms_lob.getLength( metaClob );
   IF bufSize > len THEN
     bufSize := len;
   END IF;
   WHILE len > 0 LOOP
     dbms_lob.read( metaClob, bufSize, pos, buf );
     htp.prints( buf );
     pos := pos + bufSize;
     len := len - bufSize;
   END LOOP;

3.3.6 イメージへの新規XMPメタデータの書込み

フォト・アルバム・アプリケーションの「Write XMP metadata」ページを使用して、フォト・アルバム内のイメージのXMPメタデータを追加または改訂できます。

「Write XMP metadata」ページを使用して、イメージに新規XMPメタデータを書き込んだり、既存のXMPメタデータを置換することができます。Oracle Multimediaでは、XMPメタデータの書込みのみをサポートしています。「View entry」ページまたは「View metadata」ページのいずれかからナビゲーション・バーの「Write metadata」リンクを選択することで、「Write XMP metadata」ページにアクセスできます。

「Write XMP metadata」ページには、変更するイメージの縮小イメージが表示されます。このページには、次の5つのテキスト入力フィールドのメタデータ属性を収集するための入力フォームも表示されます。

  • Title:写真のタイトルを指定します。

  • Creator:撮影者の名前を入力します。このフィールドは省略可能です。

  • Date:撮影日を入力します。このフィールドは省略可能です。

  • Description:写真のテーマなどの説明を入力します。このフィールドは省略可能です。

  • Copyright:写真を撮影した月および年を入力します。このフィールドは省略可能です。

Write it!」をクリックして、 アプリケーションにフォームを送信し、イメージにXMP形式でメタデータを埋め込みます。

「Write XMP metadata」ページ上部には、ナビゲーション・バーがあり、他のフォト・アルバム・ページへのリンクが含まれています。「Write XMP metadata」ページから、「View album」ページに戻るか、「View entry」ページ、「View metadata」ページ、「Search metadata」ページまたは「Upload photo」ページのいずれかを選択します。

図3-6に、イメージについてのエントリが入力されている「Write XMP metadata」ページを示します。

図3-6 アップロードしたイメージについてのXMPメタデータが入力されている「Write XMP metadata」ページ

図3-6の説明が続きます
「図3-6 アップロードしたイメージについてのXMPメタデータが入力されている「Write XMP metadata」ページ」の説明

PL/SQLプロシージャwrite_metadataは、ブラウザからフォーム入力フィールドを受信します。プロシージャは、Oracle Multimedia XMPスキーマhttp://xmlns.oracle.com/ord/meta/xmpで有効なXML文書を文字列バッファとして作成します。文字列バッファは、XMLTypeオブジェクトの作成に使用されます。

SELECT FOR UPDATE文は、変更するイメージを取得します。Oracle MultimediaのputMetadata( )メソッドが、XML文書をイメージに埋め込むためにコールされます。変更されたイメージは、photos表に再度格納されます。最後に、プロシージャsync_indexesが、テキスト索引を更新するためにコールされます。

例3-10に、write_metadataプロシージャの関連するいくつかのコード行を示します。

例3-10に示す入力データによって、メタデータは次のようにイメージに格納されます。

<xmpMetadata xmlns="http://xmlns.oracle.com/ord/meta/xmp"
            xsi:schemaLocation="http://xmlns.oracle.com/ord/meta/xmp
            http://xmlns.oracle.com/ord/meta/xmp"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
   <rdf:Description about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
     <dc:title>Story time</dc:title>
     <dc:creator>father</dc:creator>
     <dc:date>July 4, 2001</dc:date>
     <dc:description>family reading</dc:description>
     <dc:copyright>mother</dc:copyright>
   </rdf:Description>
 </rdf:RDF>
</xmpMetadata> 

例3-10 プロシージャwrite_ metadata

   -- Create the XMP packet it must be schema valid
   -- to "http://xmlns.oracle.com/ord/meta/xmp"
   -- and contain an <RDF> element. This example uses
   -- the Dublin Core schema as implemented by Adobe XMP
   buf := '<xmpMetadata xmlns="http://xmlns.oracle.com/ord/meta/xmp"
            xsi:schemaLocation="http://xmlns.oracle.com/ord/meta/xmp
            http://xmlns.oracle.com/ord/meta/xmp"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
     <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
     <rdf:Description about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
     <dc:title>' || htf.escape_sc(title) || '</dc:title>';

   IF c_creator IS NOT NULL THEN
     buf := buf || '<dc:creator>' || htf.escape_sc(c_creator)
                || '</dc:creator>';
   END IF;
   IF c_date IS NOT NULL THEN
     buf := buf || '<dc:date>' || htf.escape_sc(c_date)
                || '</dc:date>';
   END IF;
   IF c_description IS NOT NULL THEN
     buf := buf || '<dc:description>' || htf.escape_sc(c_description)
                || '</dc:description>';
   END IF;
   IF c_copyright IS NOT NULL THEN
     buf := buf || '<dc:copyright>' || htf.escape_sc(c_copyright)
                || '</dc:copyright>';
   END IF;
   buf := buf || '
     </rdf:Description>
     </rdf:RDF>
     </xmpMetadata>';
 
   xmp := XMLType.createXML(buf, 'http://xmlns.oracle.com/ord/meta/xmp'); 

   --    -- select image for update
   -- description is selected to force update of CTX index
   --
   SELECT image, description
   INTO img, des
   FROM photos
   WHERE id = entry_id
   FOR UPDATE;
 
   --
   -- write the metadata
   --
   img.putMetadata( xmp, 'XMP' );
 
   --
   -- save updated image and new metadata to table
   -- description updated to force update of CTX index
   --
   UPDATE photos
   SET image = img,
       metaXMP = xmp,
       description = des
   WHERE id = entry_id;
 
   -- update the text indexes
   sync_indexes;

3.3.7 特定のメタデータ属性を含むイメージの検索

フォト・アルバム・アプリケーションの「Search metadata」ページを使用して、フォト・アルバム内のイメージの特定のメタデータを検索できます。

「Search metadata」ページを使用して、特定のメタデータ型を検索したり、メタデータ・ドキュメント内の特定のタグに検索を限定できます。「Search metadata」ページには、任意のフォト・アルバム・アプリケーションWebページのナビゲーション・バーから「Search metadata」リンクを選択することによってアクセスできます。

「Search metadata」ページには、検索の実行方法を定義するための4つのフィールドがあるフォームが表示されます。「Search in metadata:」フィールドのメニューを使用して、検索するメタデータのタイプ(EXIFIPTCまたはXMP)を選択します。このフィールドを変更すると、フィールド「Search in tag:」および「Search method:」が、検索するメタデータの型に適した値に初期化されます。

Search in tag:」フィールドのドロップダウン・リストを使用して、メタデータ・ドキュメント内の特定のXML要素に検索を限定します。選択したメタデータの型に適した要素名が、リストに移入されます。「--Any tag--」が表示された場合は、ドキュメント・タイプにあるすべての要素が検索されます。メタデータの型にXMPを選択すると、親RDF要素内のDescription要素に検索が限定されます。メタデータ・ドキュメントが適切に構成されている場合、このフィールドで「RDF/Description」を選択すると、XMPドキュメント内の関連するすべてのメタデータが検索されます。

「Search method:」フィールドで、「Contains」を選択すると、検索対象が、検索文字列を含む要素に特定されます。「Equals」を選択すると、検索対象が、検索文字列と完全に一致する要素の値に特定されます。XMPメタデータの検索に関しては、「Contains」検索方法のみを実行できます。

最後に、「Search string:」フィールドにキーワードまたは語句を入力して、「Search」をクリックします。検索に成功すると、一致したイメージの縮小イメージが4列の表で表示されます。縮小イメージをクリックすると、イメージが原寸で表示されます。または、縮小イメージの下にある説明リンクを選択すると、イメージのメタデータが表示されます。検索に失敗すると、「No photos matched the search criteria.」というメッセージが表示されます。

「Search metadata」ページ上部には、ナビゲーション・バーがあり、他のフォト・アルバム・ページへのリンクが含まれています。「Search metadata」ページから、「View album」ページに戻るか、「Upload photo」ページを選択します。

図3-7に、サンプルの検索条件が含まれ、検索操作に成功して結果が表示されている「Search metadata」ページを示します。

図3-7 アップロードしたイメージに対する検索実行後の「Search metadata」ページ

図3-7の説明が続きます
「図3-7 アップロードしたイメージに対する検索実行後の「Search metadata」ページ」の説明

PL/SQLプロシージャsearch_metadataは、Webブラウザからフォーム入力フィールドを受信します。検索パラメータは、希望するメタデータを含むイメージを検索するための問合せ作成に使用されます。検索は、SQLファンクションXMLExistsを使用して実行されます。XMLExistsファンクションを使用して、指定されたXQuery式に一致するコンテンツのXMLドキュメントが検索されます。文書で検索が一致した場合はTRUEが、一致しない場合はFALSEがファンクションによって戻されます。

たとえば、search_metadataプロシージャが、キーワード「farm」と完全一致するcaptionタグをIPTCメタデータで検索するように指定された入力を受信したとします。この検索を実行するための問合せは、次のとおりです。

 SELECT id, description, thumb
 FROM photos
 WHERE xmlexists('declare default element namespace ' ||
                 ' "http://xmlns.oracle.com/ord/meta/iptc"; $x' ||
                 '/iptcMetadata[//caption="farm"]' passing metaIptc as "x");

XQuery式のXPathコンポーネントである'/iptcMetadata[//caption="farm"]'は、ルート要素<iptcMetadata>の下のすべての<caption>要素に対する検索を指定します。ここで<caption>コンテンツは"farm"です。

関連項目:

XMLExistsファンクションの詳細は、『Oracle XML DB開発者ガイド』を参照してください

例3-11に、search_metadataプロシージャの関連するいくつかのコード行を示します。

例3-11 プロシージャsearch_ metadata

    -- Set up search variables for EXIF documents.
    IF mtype = 'exif' THEN
      IF op = 'equals' THEN
        xpath  := '/exifMetadata[//' || tag || '="' || c_search || '"]';
      ELSE  -- default to contains
        xpath  := '/exifMetadata//' || tag ||
                  '[contains(., "' || c_search || '")]';
      END IF;
 
      xquery := 'declare default element namespace ' ||
                ' "http://xmlns.oracle.com/ord/meta/exif"; $x' || xpath;
 
      OPEN album_cur FOR
        SELECT id, description, thumb
        FROM photos
        WHERE xmlexists(xquery passing metaExif as "x");
 
    -- Set up search variables for IPTC documents.
    ELSIF mtype = 'iptc' THEN
      IF op = 'equals' THEN
        xpath  := '/iptcMetadata[//' || tag || '="' || c_search || '"]';
      ELSE  -- default to contains
        xpath  := '/iptcMetadata//' || tag ||
                  '[contains(., "' || c_search || '")]';
      END IF;
 
      xquery := 'declare default element namespace ' ||
            ' "http://xmlns.oracle.com/ord/meta/iptc"; $x' || xpath;
 
      OPEN album_cur FOR
        SELECT id, description, thumb
        FROM photos
        WHERE xmlexists(xquery passing metaIptc as "x");
 
    -- Set up search variables for XMP documents.
    ELSIF mtype = 'xmp' THEN
      -- default to contains
      xpath  := '//rdf:Description//*[contains(., "'
                || c_search || '")]';
 
      -- Add rdf namespace prefix.
      xquery := 'declare namespace rdf = ' ||
             ' "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; ' ||
             'declare default element namespace ' ||
             ' "http://xmlns.oracle.com/ord/meta/xmp"; $x' || xpath;
 
      OPEN album_cur FOR
        SELECT id, description, thumb
        FROM photos
        WHERE xmlexists(xquery passing metaXMP as "x");
 
    ELSE
      errorMsg := 'Search domain is invalid: ' || htf.escape_sc(mtype);
    END IF;
 
    print_search_form( mtype, tag, op, c_search );
    htp.print('<hr size="-1">');
    print_album( album_cur, 'No photos matched the search criteria.' );