作って学ぶXMLデータベースNeoCore XMS実践 第4回
2006年12月15日 更新
第4回:検索式を組み込んでシステムを完成させる(前編)
著者:ウルシステムズ 小松 要 2006/4/14
システムの構築をはじめる前に
本連載ではこれまでXML DBを有効に活用するシステムの例として、XMLフォーマットを採用した提案書を活用する営業支援システムの設計を行ってきました。前回はXML DBの構築、非定型文書である提案書の登録、登録した提案書の定型部分を用いて情報を取得するための検索式の検討を行いました。
検索式として、具体的にXML DBに対する標準の問い合わせ言語であるXPathやXQueryをどのように用いれば、作成するシステムに必要な、項目指定による検索や、フリーワードによる検索が可能になるかを解説しました。
第4回では検討した検索式を組み込んだJavaプログラムを実装し、営業支援システムを構築していきます。
まず今回構築するシステムの機能について確認をしておきます。このシステムは営業支援を目的にしており、下記のような機能が必要になります。
提案書登録機能 |
利用者のPCから提案書をアップロードする機能 |
提案書のデータをXMLデータベースに格納する機能 |
提案状況一覧機能 |
一覧する条件を入力する機能 |
入力された一覧条件に合致する提案の概要情報を一覧表示する機能 |
提案書検索機能 |
参照したい提案書を検索する条件を入力する機能 |
入力された検索条件に合致した提案書を一覧表示する機能 |
検索結果の一覧から指定された提案書をダウンロードする機能 |
▲表1:必要な機能
このシステムはユーザが直接操作するWebブラウザから、ビジネスロジックを実現するServletを介してデータベースにアクセスする3層レイヤのアーキテクチャを採用します(図1)。それぞれ表1の機能ごとに必要な処理を洗い出し、Servletとして実現してシステムを完成させます。
▲図1:システム構成図(画像をクリックすると別ウィンドウに拡大図を表示します)
Servlet からNeoCoreXMSのデータベース操作を呼び出すにはJavaAPI(xmsclient)を用います。このAPIはJavaプログラムから HTTPを使用してNeoCoreXMSのサーバにアクセスするもので、検索・更新・削除などの操作を可能にします。使い方の具体例は、以下のサンプルプログラムの中で説明します。詳細についてはAPIのJavaDoc (デフォルトでは\docs\Java_APIの配下)を参考にしてください。
提案書登録機能処理の概要
それでは機能ごとに、処理の概要と実装方法の説明を行います。提案書登録機能では、以下の処理が必要となります。
- 提案書アップロード処理
ユーザから送信された提案書を取得する処理
- アップロードされた提案書をzip解凍してcontent.xmlを取り出す
データベースで管理するcontent.xmlを取り出すために、アップロードされた提案書をzip解凍する
- 取り出したcontent.xmlをXML DBにストアする処理
XML DBとのセッションを確立し、content.xmlをDBにストアする
▲表2:必要な処理
提案書登録機能をJavaで実装する
これらの処理をJavaにより実装するため図2のような構成にします。
▲図2:提案書登録機能構成
実装するために主要なクラスとしては次のようなものがあります。
FileRegisterServletクラス
送信された提案書の取得、zip解凍後に取り出されたcontent.xmlファイルをNeoCoreXMSへストアする処理を行います
提案書登録機能のプログラムサンプル
FileRegisterServlet クラスのサンプルを以下に示します。この中で赤文字部分が実際にNeoCoreXMSへファイルをストアする処理になります。セッションを確立してDBにファイルをストアする流れは、RDBのLOB型カラムに登録する場合と大きく変わるものではないということを確認してください。
package jp.co.ulsystems.xmldb.servlet
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.neocore.httpclient.SessionManagedNeoConnection;
public class FileRegisterServlet extends HttpServlet{
static private final String ANSWER_JSP = "/jsp/register/complete.jsp";
public void doPost(HttpServletRequest req,HttpServletResponse res) {
try {
// ファイルアップロード保存先のディレクトリ
String path = getServletContext().getRealPath + "/";
// 提案書を指定したディレクトリにアップロード
File file = upload(path,req);
// 提案書をZIP解凍し、content.xmlの抽出
File contents = getContents(path, file);
// content.xmlをXML DBにストアする
// XML DBとのセッションを確立
SessionManagedNeoConnection session =
new SessionManagedNeoConnection("localhost",7701);
session.login("Administrator","admin");
// content.xmlをストア
String docId = session.storeFileXML (contents.getAbsolutePath(), null, null);
// XML DBからログアウト
session.logout ();
// JSPへの転送
RequestDispatcher dispatch = req.getRequestDispatcher(ANSWER_JSP);
dispatch.forward(req, res);
} catch(Exception e) {
e.printStackTrace();
}
}
}
|
▲FileRegisterServlet.javaのサンプルプログラム
※注: サンプルのため、一部省略しています。
提案書登録機能の動作確認
提案書をシステムに登録し、NeoCore管理コンソールを使用してデータベースに登録されていることを確認しましょう。登録する提案書は「お客様名」「提案日」「担当営業者」項目に機密情報スタイルが適用されています。図3の赤枠部分が機密情報スタイルを適用している部分です。
▲図3:提案書サンプル(画像をクリックすると別ウィンドウに拡大図を表示します)
に作成したシステムに上記の提案書を登録します(図4)。
▲図4:提案書登録機能の動作確認(画像をクリックすると別ウィンドウに拡大図を表示します)
提案書の登録が完了したら、NeoCore管理コンソールを使用してNeoCoreXMSに登録されているかを確認します。検索条件として、提案書の定型部分であるお客様名項目の情報「小泉運輸株式会社」を指定して検索します(図5)。
▲図5:NeoCore管理コンソールによる確認(画像をクリックすると別ウィンドウに拡大図を表示します)
提案状況の一覧機能
次に提案状況一覧機能について、処理の概要と実装方法の説明を行います。提案状況一覧機能では、以下の処理が必要となります。
項目指定による検索処理
お客様名などのオブジェクト名を持つ定型部分の値を検索して、対象となる提案書を見つける処理です。前回の記事では項目指定による検索はXPathを使用する例を示しましたが、ここでは一覧表示を簡単にするために検索結果のフォーマットを指定できるXQueryを使用して実現します。
for $data in /ND/document-content/body/presentation sortby (integer(root(.)//DocID/text()))
let $customer:= $data//frame[@name='お客様名']//text()
,$title := $data//frame[@name='提案タイトル']//text()
,$date := $data//frame[@name='提案日']//text()
,$location := $data//frame[@name='営業拠点']//text()
,$charge := $data//frame[@name='担当営業者']//text()
,$system := $data//frame[@name='提案機種']//text()
,$estimate := $data//frame[@name='見積もり金額']//text()
where contains($customer/text(),'お客様名項目検索条件') and
contains($title/text(),'提案タイトル項目検索条件') and
contains($location/text(),'営業拠点項目検索条件') and
contains($charge/text(),'担当営業者項目検索条件')
return
<result>
<customer>{string($customer)}</customer>
<title>{string($title)}</title>
<date>{string($date)}</date>
<location>{string($location)}</location>
<charge>{string($charge)}</charge>
<system>{string($system)}</system>
<estimate>{string($estimate)}</estimate>
</result>
|
▲使用するXQuery
XSLスタイルシートを使用した画面表示処理
画面の表示スタイルを設定するためにはXSLスタイルシートを使用します。XSLはXML文書を異なる標準のXMLやHTMLなど様々な形式に変換するための言語で、Webブラウザの画面や印刷するための書式を整えたりするのに用いられます。
ここでは前項で得られた検索結果に対してXSLスタイルシートを適用し、画面表示に必要なHTMLの一部を生成します。
提案状況一覧機能をJavaで実装する
これらの処理をJavaにより実装するため図6のような構成にします。
▲図6:提案状況一覧機能構成(画像をクリックすると別ウィンドウに拡大図を表示します)
ここで利用する主要なクラスとしては次のようなものがあります。
- SelectListinputクラス
- 指定された検索条件によりXQuery式のwhere句を生成します。
- SelectListLogicクラス
- XQuery式全体を作成し、検索処理を実行します。
SelectListinputクラスとSelectListLogicクラスのサンプルを以下に示します。SelectListLogicクラスの赤文字部分がXQueryを実行する処理になります。
package jp.co.ulsystems.xmldb.input
import javax.servlet.http.HttpServletRequest;
public class SelectListinput {
private String customer;
private String title;
private String location;
private String charge;
public void evaluateParams(HttpServletRequest request) throws Exception {
customer = (String)request.getParameter("customer");
title = (String)request.getParameter("title");
location = (String)request.getParameter("location");
charge = (String)request.getParameter("charge");
}
public String createWhere() {
String where = "";
//入力された条件からwhrere句の文字列取得
// 検索条件:お客様名
if(!customer.equals("")){
where = " where " + "contains($customer/text(),'" + customer + "')";
}
// 検索条件:提案タイトル
if(!title.equals("")){
if(where.equals("")){
where += " where " + "contains($title/text(),'" + title + "')";
}else{
where += " and " + "contains($title/text(),'" + title + "')";
}
}
// 検索条件:営業拠点
if(!location.equals("")){
if(where.equals("")){
where += " where " + "contains($location/text(),'" + location + "')";
}else{
where += " and " + "contains($location/text(),'" + location + "')";
}
}
// 検索条件:担当営業者
if(!charge.equals("")){
if(where.equals("")){
where += " where " + "contains($charge/text(),'" + charge + "')";
}else{
where += " and " + "contains($charge/text(),'" + charge + "')";
}
}
return where;
}
}
|
▲SelectListinput.javaクラスサンプルプログラム
※注: サンプルのため、一部省略しています。
package jp.co.ulsystems.xmldb.logic
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import Listinput;
import com.neocore.httpclient.SessionManagedNeoConnection;
public class SelectListLogic {
private String queryResultsXml = null;
SelectListinput input = null;
public ListSearchLogic(HttpServletRequest request,HttpServletResponse response) throws Exception {
queryResultsXml = null;
input.evaluateParams(request);
}
public void execute(){
SessionManagedNeoConnection session = null;
try{
//XQuery式の構築
String query = "for $data in /ND/document-content/body/presentation sortby
(integer(root(.)//DocID/text()))" +
" let $customer := $data//frame[@name='お客様名']//text()" +
",$title := $data//frame[@name='提案タイトル']//text()" +
",$date := $data//frame[@name='提案日']//text()" +
",$location := $data//frame[@name='営業拠点']//text()" +
",$charge := $data//frame[@name='担当営業名']//text()" +
",$system := $data//frame[@name='提案機種']//text()" +
",$estimate := $data//frame[@name='見積もり金額']//text()" +
input.createWhere() +
" return" +
"<result>" +
"<customer>{string($customer)}</customer>" +
"<title>{string($title)}</title>" +
"<date>{string($date)}</date>" +
"<location>{string($location)}</location>" +
"<charge>{string($charge)}</charge>" +
"<system>{string($system)}</system>" +
"<estimate>{string($estimate)}</estimate>" +
"</result>";
// XQueryを使用し検索を実行する
// XML DBとのセッションを確立
SessionManagedNeoConnection session =
new SessionManagedNeoConnection("localhost",7701);
session.login("Administrator","admin");
// 検索の実行
queryResultsXml = session.queryXML(query);
// XML DBからログアウト
session.logout ();
} catch (Exception e) {
e.printStackTrace();
}
}
}
|
▲SelectListLogic.javaクラスサンプルプログラム
※注: サンプルのため、一部省略しています。
次に、検索処理によって得られたXML文書を画面表示用に整形するXSLスタイルシートを以下に示します。このXSLスタイルシートは検索結果の一覧表示画面に含まれるテーブル中の項目を生成しています。
<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version
="1.0">
<xsl:template match="/Query-Results">
<!--[result]要素分繰り返す -->
<xsl:for-each select="./result">
<tr>
<!--[お客様名]項目の表示 -->
<td class="valueAndULine"><xsl:value-of select="./customer"/></td>
<!--[提案タイトル]項目の表示-->
<td class="valueAndULine"><xsl:value-of select="./title"/></td>
<!--[提案日付]項目の表示-->
<td class="valueAndULine"><xsl:value-of select="./date"/></td>
<!--[営業拠点]項目の表示-->
<td class="valueAndULine"><xsl:value-of select="./location"/></td>
<!--[担当営業者]項目の表示-->
<td class="valueAndULine"><xsl:value-of select="./charge"/></td>
<!--[提案機種]項目の表示-->
<td class="valueAndULine"><xsl:value-of select="./system"/></td>
<!--[見積もり金額]項目の表示-->
<td class="valueAndULine"><xsl:value-of select="./estimate"/></td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
|
▲list.xslスタイルシート
提案状況一覧機能の動作確認
先ほど登録した提案書が項目指定で検索できることを確認します。検索条件として、提案書の定型部分である提案書タイトル項目の情報の一部「SCMシミュレーション」を指定して検索します(図7)。
▲図7:提案状況一覧機能の動作確認(画像をクリックすると別ウィンドウに拡大図を表示します)
次回は、提案書の検索や提案書のダウンロードを行う提案書検索機能の処理概要と実装方法について説明します。