Webアプリ開発事始 第21回

XMLとプログラミング(2)
~JavaScriptによる検索処理の実例
長谷川裕行
有限会社 手國堂

finditem.js~検索処理のJavaScript(リスト3)

リスト3が、XML文書からデータの検索を行って結果を表示するJavaScriptファイル“finditem.js”です。処理ごとに、その働きを説明しておきます。


- finditem~検索処理の本体(1) -

HTML文書の[検索]ボタンに割り当てられたOnClickイベントで呼び出されます。

引数はHTML文書内のフォーム(FORMタグで定義されたフォーム)を示す識別子とXML IDです。

  function finditem(form, xmldocument)

呼び出し元のHTML文書内にあるフォーム上のコントロールは、フォームを示す引数formから以下のようにして参照できます。

  テキストボックス「部品ID」:form.itemId
  テキストボックス「部品ID」に入力された値:form.itemId.value
  テキストボックス「ファイル」:form.fname
  テキストボックス「ファイル」に入力された値:form.fname.value

これらを、以下のようにして変数に代入しておきます。

・XML文書名を変数fnameに格納
  var fname = form.fname.value,
・処理結果を表示するテキストボックスを変数outputに格納
  output = form.output,
・テキストボックスに入力された部品IDをitemIdに保存
  itemId = form.itemId.value;

変数宣言と同時に値を代入しているため、各変数の代入文の最後は「,」で区切り、最後の代入文の後に「;」を付けています。


- finditem~検索処理の本体(2) -

parseは、HTML文書中で定義したデータアイランド(仮引数xmldocument)に変数fnameの保持するXML文書を読み込み、戻り値であるXMLDOMDocumentオブジェクトへの参照を、変数documentに代入します。parseの具体的な動作については後述します。

  var document = parse(fname, xmldocument),

こうして取得したXMLDOMDocumentオブジェクトを示す変数documentのdocumentElementプロパティには、XML文書のルート要素が保持されています。これを、変数topLevelに代入します。

  topLevel = document.documentElement;

これで、XML文書内のデータを自在に操作できるようになりました。

最後にsearchItemを呼び出し、実際の検索と結果表示を行います。searchItemは、XML文書のルート要素topLevel、出力先output、検索キーitemIdの3つの引数を取ります。具体的な働きについては後述します。

  searchItem(topLevel, output, itemId);


- parse~XML文書の読み込み -

finditemから呼び出され、データアイランドにXML文書のリストを読み込みます。引数は、XMLファイル名を示すfnameとXML IDを示すxmldocumentです。

  function parse(docname, xmldocument)

XML IDで示されるデータアイランドにXML文書を読み込ませる手順は、以下のようになります。

  asyncプロパティをfalse(偽)に設定
  XML文書を指定してloadメソッドを実行

これをソースコードにすると、以下のようになります

  xmldocument.async = false;
  xmldocument.load(docname);

asyncは規定値がtrueとなっているため、文書の読み込みとデータ処理が非同期で実行されます。そのため、XML文書がすべて読み込まれないうちにデータ処理が実行される場合があります。単に全データを一覧表示するだけのような単純な処理ならこれでも構いませんが、検索などの処理では都合が悪いので、すべてのデータを読み込んでから処理を行わせるためにfalseと設定します。

parseErrorはDOMのエラーを保持するオブジェクトで、XMLDocumentのparseErrorプロパティから参照できます。XML文書の読み込みが失敗すると、parseError.errorCodeが0以外の値とり、parseError.reasonにエラーメッセージ保持されます。

  if(xmldocument.parseError.errorCode != 0)
      ↑エラー発生時には……
   alert(xmldocument.parseError.reason);
      ↑メッセージを表示する
 エラーがなければ、XML文書を読み込んだXMLDOMDocumentオブジェクトへの参照を返します。
return xmldocument;

 前回紹介したように、asyncプロパティもloadメソッドもInternet Explorer固有の機能です。他のブラウザでは利用できません。


- searchItem~実際の検索処理(1) -

指定されたXML文書からキーワードに合致する要素を探し出し、その中の子要素をすべて出力します。引数は、XML文書のルート要素を示すnode、出力先のテキストボックスを示すoutput、検索キーワードitemIdの3つです。

  function searchItem(node, output, itemId)

仮引数nodeはXML文書内のルート要素を指します。mr_parts.xml(リスト1)の場合は「部品マスター」となります。ここから、処理の対象となる要素を1つ下の「部品」に移動し、その要素の数だけ処理を繰り返します。

子要素はルート要素を示すオブジェクトのchildNodesで参照できます。これはchildNodeオブジェクトのコレクションで、lengthプロパティに要素数が保持されています。従って、以下のようなforループで、処理を子要素の数だけ繰り返す構造が出来上がります。

  for(i = 0;i < node.childNodes.length;i++)


- searchItem~実際の検索処理(2) -

forループの中では、要素「部品」のさらに子要素である「部品ID」の値を取り出し、それが仮引数itemIdと合致するかどうかを調べなければなりません。

まず、変数childに子要素への参照を代入します。先述したchildNodesコレクションは、( )内にインデックス番号を指定することで「何番目の子要素」かを指定できます。インデックスは0から始まるため、forループのカウンタ変数iをインデックスに用いれば、、ループを回るごとに順次子要素にアクセスできます。childには、ルート要素の直下にある「部品」への参照が代入されることに注意してください。

  child = node.childNodes(i);


- searchItem~実際の検索処理(3) -

最終的な検索は、変数childのさらに子要素である「部品ID」を参照し、それがキーワードである仮引数itemIdの値と等しいかを調べる処理となります。

先に取り出した子要素childにも、childNodesプロパティがあります。これは、子要素内のさらに子要素の集合となります。これは、「部品ID」「部品名」「単価」の各要素となります。

childNodesコレクションから特定の要素を参照するには、itemプロパティを用います。その要素の値はtextプロパティで取り出せます。

itemも0から始まるインデックスで指定できます。要素「部品ID」は先頭要素となるのでitem(0)です。

これで、現在処理している要素内の「部品ID」の値と、キーワードitemIdが等しいかどうかを調べる処理が出来上がります。

  if(child.childNodes.item(0).text == itemId)


- searchItem~実際の検索処理(4) -

itemIdの保持しているキーワードと「部品ID」の値が一致したら、makeListを呼び出します。makeListは、forループ内で現在処理対象となっている要素(変数childが示すオブジェクト)からその子要素(各項目)の値を取り出し、結果表示用の文字列を生成します。これを変数textに受け取り、最終的に結果表示領域であるテキストボックスoutputのvalueに代入します。

  text = makeList(child);

もし該当する項目が見つからなかったら、エラーメッセージを表示しなければなりません。forループの最後まで到達しても合致する項目が見つからなかった場合、変数textは初期化されたまま("")となっているので、それをifで白め手処理を切り替えます。

  if(text == "")    ←該当レコードが見つからなかった場合
  text = "データが見つかりません。" +"\r";
  output.value = text; ←結果をテキストボックスに表示


- makeList~検索結果の表示 -

要素node(部品)を引数に受け取り、その中の各子要素(最終要素)の値を表示用の文字列に整形します。

  function makeList(node)

以下のように、部品ID、部品名、単価の3つの要素を他の必要な文字列と連結しているだけです。

  textList += "部品ID:" + node.childNodes.item(0).text + "\r";
  textList += "部品名:" + node.childNodes.item(1).text + "\r";
  textList += "単 価:" + node.childNodes.item(2).text + "円" + "\r";

要素名や通貨単位(円)などの表示が不要なら、以下のようにforループで処理しても構いません。

  var i;
  for(i = 0;i < 3; i++)
   textList += child.childNodes.item(i).text + "\r";

これで、部品検索処理が出来上がりました。サンプルで動作を試してみてください。

XML文書、HTML文書ともに、特に難しいことはしていません。JavaScriptの基本構造を押さえておけば、他の処理にも応用できるはずです。

リスト3:XML文書から商品検索を行うjavaスクリプト~finditem.js


トップページ
部品リスト~mr_parts.xml(リスト1)
items.html~Webページ(リスト2)
finditem.js~検索処理のJavaScript(リスト3)
finditem~検索処理の本体(1)
finditem~検索処理の本体(2)
parse~XML文書の読み込み
searchItem~実際の検索処理(1)
searchItem~実際の検索処理(2)
searchItem~実際の検索処理(3)
searchItem~実際の検索処理(4)
makeList~検索結果の表示
スタイルシートのパターンマッチング
あとがき

Copyright © MESCIUS inc. All rights reserved.