レベル: 中級 山田 浩司, 情報マネジメント技術/大和ソフトウェア開発研究所 , IBM
2006年 12月 15日 Content Managerで管理されているコンテンツ(データ)を、XML形式でエクスポート・インポートを行うことができます。Java API, Java Beans APIのほかにXMLサービスAPIを通じたコンテンツの入出力の方式について解説します。
はじめに
IBM DB2 Content Manager バージョン8.3 (以下、Content Managerと略す)から、XMLサービスの機能が提供されています。Content Managerで管理されているコンテンツを、XML形式でエクスポート・インポートを行うことができます。この記事では、XMLサービスAPIを通じたコンテンツの入出力の方式について解説します。
DDO(Dynamic Data Object)をXMLで表現することにより、システムごとに固有のインターフェースを開発する必要がなくなり、コーディング量を格段に減らすことができるようになります。加えて、XMLを用いることで異なるシステム間でさまざまなオブジェクトを統一的に扱うことが可能となります。
なお、XMLサービスAPIに関しては、提供されている言語としてはJavaのみとなり、C++は提供されません。
XMLで表現されたDDO属性
XMLで表現された属性と、ファイル形式のバイナリー・データを、Content ManagerのDDOとしてインポートおよびエクスポートを行うサンプル・コードを用いて、XMLサービスAPIに関して解説します。
まず、入力となるXMLファイルを見てみましょう。これはサンプル・コードと共にDefineAttributes.xmlとして提供されています。
リスト1: 属性を表現したXMLファイルの例
<?xml version="1.0" encoding="UTF-8"?>
<?icmxml version="1.0"?>
<NOINDEX SOURCE="TEST_XML" TIMESTAMP="2006-11-11T12:34:56.789"
USER_ID="icmadmin"
xmlns:cm="http://www.ibm.com/xmlns/db2/cm/api/1.0/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<cm:properties type="document">
<cm:createUserid value="ICMADMIN"/>
<cm:semanticType value="1"/>
<cm:ACL name="PublicReadACL"/>
</cm:properties>
<ICMBASE>
<cm:properties type="item" xsi:type="cm:partPropertyType">
<cm:createUserid value="ICMADMIN"/>
<cm:ACL name="PublicReadACL"/>
<cm:semanticType value="128"/>
</cm:properties>
<cm:resourceObject MIMEType="image/jpeg" RMName="rmdb"
SMSCollName="CBR.CLLCT001" externalObjectName=" ">
<cm:label name="NOINDEXTEST"/>
</cm:resourceObject>
</ICMBASE>
</NOINDEX>
|
生成されるDDOのバイナリー・データはサンプルのファイルから入力されることになりますが、そのラベルが label name=”NOINDEXTEST” として本XML内に定義されています。この属性とバイナリー・データはこのラベルを通じてメソッドで紐付けられることになります。言い換えると、このXML内にはどこにもバイナリー・データのファイル名が示されていないことに注目してください。このラベルの扱いは、後にサンプル・コード内のメソッドと共に説明します。
XMLサービスAPIを用いたDDOのインポートとエクスポート
本節では、具体的なXMLサービスAPIの使用法について解説します。
XMLに関する操作を、DDOに関する操作と対応させてみた場合の操作を、以下のリスト2にまとめました。
リスト2: DDOとXMLそれぞれに対する操作
|
| DDOに対する操作 | XMLに対する操作 |
|---|
| コネクター | DKDatastoreICMオブジェクト |
|---|
| オブジェクト(インスタンス)の作成 | DKDDOオブジェクトをDKDatastoreICM#createDDO()で作成する。 | 属性を表現したDocumentオブジェクトを引数とし、DKXMLItemオブジェクトをコンストラクターにて作成する。 |
|---|
| これらは DKXMLDataInstanceService#ingest(), extract() により相互に変換可能である。 | | 属性の付与 | DKDDOオブジェクトにsetData()で付与する。 | XMLに対してタグ付けを行い、Documentオブジェクトを作成する。 |
|---|
| バイナリー・データの付与 | DKLobICMオブジェクトのsetAddLocationOption()メソッドを使用する。 | DKXMLItemオブジェクトのsetContentAsStream()メソッドを使用する。 |
|---|
| 属性の取り出し | DKDDOオブジェクトのgetData()で取得する。 | DKXMLItemオブジェクトのgetXmlItem()メソッドでDocumentオブジェクトを得る。 |
|---|
| バイナリー・データの取り出し | DKLobICMオブジェクトのretrieve()メソッドを使用する。 | DKXMLItemオブジェクトのgetContentAsStream()メソッドで取得する。 |
|---|
XMLサービスの役割の中心となるのはDKXMLItemオブジェクトです。このDKXMLItemオブジェクトには、以下の情報が含まれます。
- 項目とバージョン (子コンポーネントを含む)
- システム属性、リソース属性、およびリンク情報などのプロパティー
- バイナリー・データで構成されているファイル
上記の情報を含んだXMLをorg.w3c.dom.Documentオブジェクトとして準備します。このDocumentオブジェクトの生成は、Javaの一般的なXML操作で行うことができます。
このDocumentオブジェクトは、DKXMLItemクラスのコンストラクターにパラメーターとして与えることにより、DKXMLItemオブジェクトに変換することができます。また、DKXMLItemオブジェクトは、getXmlItem()メソッドによってDocumentオブジェクトに変換することができます。
DDOは「属性とファイル」で構成されますが、このDKXMLItemクラスも同様に、ファイルを関連付ける必要があります。DKXMLItemクラスには setContentAsStream(), getContentAsStream()メソッドが提供されており、これによりファイルの入出力が可能です。ここで「ファイル」と書きましたが、ストリームで表現できるものであればファイルである必要はありません。
DKXMLItemオブジェクトとDDOの変換には、DKXMLDataInstanceServiceクラスの ingest(), extract() メソッドを使用します。なお、管理オブジェクトを扱うDKXMLDOMObjectDefsクラスも同名のメソッド名を持っており、XMLサービスAPIでメソッド名が統一化されています。DKXMLDataInstanceServiceクラスのコンストラクターにDKDatastoreICMオブジェクトをパラメーターとして指定することにより、オブジェクトを生成することができます。
サンプル・コードをもとに、クラス、メソッドの具体的な使用方法を説明します。説明においては、コード内の要点をピック・アップしています。完全な形のサンプル・コードは、この記事の「ダウンロード」セクションを参照してください。
- サンプル・コードの定数フィールド定義部分です。
private static final String connectDatasource = "icmnlsdb"; //サーバー名
private static final String connectUserid = "icmadmin"; //ユーザーID
private static final String connectPassword = "password"; //パスワード
private static final String CONTENT_SEARCH_TOKEN = "TEST_XML"; //SOURCE属性(検索時に参照)
private static final String CONTENT_XML_LABEL = "NOINDEXTEST"; //コンテンツのラベル
private static final String inDataFilename = "Sample.jpg"; //サンプル入力ファイル
private static final String inXmlFilename = "DefineAttributes.xml"; //XMLによる属性表現
|
サーバー名、ユーザーID、パスワードはそれぞれ利用可能なものに修正してください。またサンプルの入力データとして、ファイルSample.jpgを準備してください。これは任意のもので構いません。これらの準備が整えば、コンパイルし、クラス・ファイルを作成してください。
- XMLデータ・インスタンス・サービスのインスタンスを作成します。
DKDatastoreICM dsICM = new DKDatastoreICM();
dsICM.connect( connectDatasource, connectUserid, connectPassword, "" );
DKXMLDataInstanceService
instService = new
DKXMLDataInstanceService(dsICM);
|
- 属性を表現したXMLファイルDefineAttributes.xmlをもとに、Documentクラスのインスタンスを作成します。
FileInputStream iXmlStr = new FileInputStream(inXmlFilename);
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
docFactory.setNamespaceAware(true); //パーサがXML名前空間をサポートするように指定
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document fileDoc = docBuilder.parse(iXmlStr);
|
前節で説明したように、この部分はJavaの一般的なXML操作で行うことができ、Content Manager固有の処理はありません。
- DocumentオブジェクトをDKXMLItemオブジェクトに変換し、ファイルをインポートします。
?DKXMLItem xmlItem = new DKXMLDOMItem(fileDoc, null);
FileInputStream iStr = new FileInputStream(inDataFilename);
xmlItem.setContentAsStream(CONTENT_XML_LABEL, iStr);
//CONTENT_XML_LABEL="NOINDEXTEST"は代入済み。 |
setContentAsStream()メソッドは2つのパラメーターを必要とします。最初のパラメーターはラベルです。XMLで定義された属性と、ストリームは、ここで紐付けられます。次のパラメーターは入力のストリームです。ここではファイルSample.jpgをもとにしたストリームを指定しています。 setContentAsStream()メソッドは、単にストリームをセットするという役目のみならず、「ラベルとストリーム」という組を明確に定義するという役目を担うことになります。すなわち、この例のsetContentAsStream()メソッドの動作を言葉で説明すると、「ラベル“NOINDEXTEST”に対応するファイルとしてSample.jpgを定義した」と言えます。
- XMLデータ・インスタンス・サービスのingest()メソッドにより、DKXMLItemオブジェクトをDDOに変換します。
DKDDO ddo1 =
(DKDDO)
instService.
ingest( xmlItem, ingestOption );
ddo1.add();
|
ingest()メソッドの2つ目のパラメーターとなるオプションには、DK_CM_XML_IMPORT_CREATE_UPDATE, DK_CM_XML_IMPORT_CONTINUE_ON_ERROR, またはそれらの和を指定することができ、インポート動作を制御することができます。詳しくは「参考文献[3]」を参照してください。そしてadd()メソッドによりDDOをContent Managerに追加することでインポート処理が完了します。 Content ManagerのeClientあるいはClient for Windowsが利用可能なら、1つのDDOが新規に追加されていることを確認してみてください。その後、サンプル・コードはこのDDOを取り出し、属性をXMLとして保存します。
- DDOを検索します。XQUERYによって入力のXMLで定義したSOURCE属性で検索してみます。
dkResultSetCursor cursor = dsICM.execute(
"/NOINDEX[@SOURCE=\"" + CONTENT_SEARCH_TOKEN + "\"]",
DKConstantICM.DK_CM_XQPE_QL_TYPE, options);
DKDDO ddo2 = null;
while( (ddo2 = cursor.fetchNext()) != null )
{
ddo2
.retrieve(DKConstant.DK_CM_CONTENT_ITEMTREE_NO_LINKS + DKConstant.DK_CM_CONTENT_YES);
|
- XMLデータ・インスタンス・サービスのextract()メソッドにより、DDOをDKXMLItemオブジェクトに変換します。ingest()メソッドと同様に、extract()メソッドにもオプションを指定することが可能で、これにより、依存関係の消失による問題を回避することができます。その採り得るオプションには DK_CM_XML_EXPORT_PREREQUISITE などがあります。
DKXMLItem outputItem = instService.
extract( ddo2, extractOption );
|
- DKXMLItemオブジェクトをDocumentオブジェクトに変換します。
Document document =
(Document)
( (DKXMLDOMItem)outputItem ).
getXMLItem();
|
- 属性を示したDocumentオブジェクトをXML形式のファイルNOINDEX.xmlとして保存します。
FileOutputStream fosXml = new FileOutputStream( (ddo2.getObjectType() + ".xml") );
OutputFormat outputFormat = new OutputFormat(document);
outputFormat.setIndenting(true);
outputFormat.setIndent(4);
outputFormat.setPreserveSpace(false);
XMLSerializer
serializer = new
XMLSerializer(fosXml, outputFormat);
serializer.serialize(document);
|
この部分もContent Manager固有の処理はありません。
- DKXMLItemオブジェクトから、ストリームをエクスポートします。
BufferedInputStream biStream = new BufferedInputStream( outputItem.getContentAsStream(label) );
|
この後、ストリームをファイルとして保存しています。作成されるファイル ExtractedContent-x-y.binが入力ファイルSample.jpgと相違ないことを確認してください。(ファイル名の x, y は検索されたDDOの数によって異なります。)

 |
おわりに
XMLサービスAPIを通じたコンテンツの入出力に関してご紹介しました。Content Manager固有部分のコーディング量が格段に減ったことが、サンプルなどからお分かりになったと思います。
システム管理データと呼ばれる定義関連の操作も、XMLで行うことが可能となりました。これについては参考文献[2]の別記事で紹介しています。そちらも是非ご覧ください。
さらに詳しい情報を得るには、「参考文献[3]」の「第11章 XMLサービスの使用」を参照してください。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| SampleXMLServiceDDO.zip | SampleXMLServiceDDO.zip | 4KB | HTTP |
|---|
参考文献
著者について  | |  | 山田 浩司は大和ソフトウェア開発研究所のエンジニアで、Content ManagerのLab. Based Service (LBS)に従事しています。 |
記事の評価
|