xmlデータの検索プログラム



0   名前: mori : 2007/03/31(土) 15:56  ID:bEwhvJYy sub-9f
解決不能な為質問させていただきます。
あるwebページにて検索フォームで入力し、./testディレクトリ内の全てのxmlファイルを検索してnode1とnode2要素及び.xmlを除いたファイル名(数字です)にマッチすれば下記の並びで表示するというものです。
(下記12345.xmlファイルでの例)
12345 555 {333種目/性別}  777
    999 
    111

ただ条件があり、
条件1.noded要素の値がnoの時は111のところに×××と表示させなければならない
条件2.ファイル名(半角数字)でマッチはしたがnode2とnode5の値が空のときは他は何も表示せず□□□と表示。
条件3.ヒットしなかった場合は△△△と表示
の3つです。
検索フォームは、下記になります
=test.html=
<script language="JavaScript" src="test.js"></script>

<form name="form1">
<input type="text" name="text1" size="40">
<input type="button" value=" 検索 " onclick="SearchName();">
</form>

======
スクリプトは下記test.jsです。
このxmldoc.load("./test/"");の行の書き方と、その後のスクリプトがわかりません。※文字列変換は情報があったのでわかります。
=test.js=
var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
xmldoc.async = false;
xmldoc.validateOnParse = true;
xmldoc.load("./test/"");→ここから先がわかりません。

function SearchName(){→ここから先がわかりません。

======
検索対象のファイル達は下記フォーマットになっています。
=./test/=
【ファイル名12345.xmlの例】
<?xml version="1.0" encoding="EUC-JP"?>
<rootnode>
<node1>111</node1>
<node2>222</node2>
<node3>333</node3>
<node4>m</node4>
<node5>555</node5>
<node6>666</node6>
<node7>777</node7>
<node8>888</node8>
<node9>999</node9>
<nodea>aaa</nodea>
<nodeb>bbb</nodeb>
<nodec>ccc</nodec>
<noded>ddd</noded>
<nodee>eee</nodee>
</rootnode>
===============

ちょっと本気で困っています。
よろしくお願いいたします。

1   名前: NullPo : 2007/03/31(土) 15:56  ID:Z0FHbpib sub-ii
要件がよくわからないので適当に直してください。
あと、IEでしか動かないです。IE6でテスト済み。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<meta http-equiv="Content-Language" content="ja">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<script type="text/javascript">
<!--

function SearchName()
{
  try {
    var targetFile = document.getElementsByName("text1")[0].value;
   } catch(e) {
    return;
  }

  var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
  var display = document.getElementById("display");
  var newDisplay = document.createElement("div");
  newDisplay.id = "display";
  xmldoc.async = false;
  xmldoc.validateOnParse = true;
  var fileCheck = xmldoc.load("./test/" + targetFile + ".xml");
  var xmlArray = parseArray(xmldoc);

  if(!fileCheck) {
    newDisplay.appendChild(document.createTextNode("△△△"));
    display.parentNode.replaceChild(newDisplay, display);
    return;
  }

  if(!xmlArray["rootnode"]["node2"] && !xmlArray["rootnode"]["node5"]) {
    newDisplay.appendChild(document.createTextNode("□□□"));
    display.parentNode.replaceChild(newDisplay, display);
    return;
  }

 //1行目の追加
  var row = document.createElement("p");
  var text = targetFile + " ";
  text += xmlArray["rootnode"]["node5"] + " ";
  text += "{" + xmlArray["rootnode"]["node3"] + "種目/性別}  ";
  text += xmlArray["rootnode"]["node7"];

  row.appendChild(document.createTextNode(text));
  newDisplay.appendChild(row);

 //2行目の追加
  row = document.createElement("p");
  text = "    " + xmlArray["rootnode"]["node9"] + " ";

  row.appendChild(document.createTextNode(text));
  newDisplay.appendChild(row);

 //3行目の追加
  row = document.createElement("p");
  text = "    " + (xmlArray["rootnode"]["noded"] == "no" ? "×××" : xmlArray["rootnode"]["node1"]);

  row.appendChild(document.createTextNode(text));
  newDisplay.appendChild(row);

  display.parentNode.replaceChild(newDisplay, display);
}

//オブジェクトの配列変換
function parseArray(xmlObject)
{
  var xmlArray = new Array();
  var nameArray = new Array();
  var nodeNumber = 0;

 //子ノードをすべて取得する。
  for(var ix = 0; ix < xmlObject.childNodes.length; ix++) {
    var thisNode = xmlObject.childNodes.item(ix);
    var thisName = thisNode.tagName;

    if( !thisName ) {
     //テキストノード取得。
      xmlArray[nodeNumber++] = thisNode.nodeValue;
     } else {
     //要素ノードである場合は再帰呼び出しを行う。
      if( typeof nameArray[thisName] == "undefined" ) {
        nameArray[thisName] = 1;
        xmlArray[thisName] = this.parseArray(thisNode);
       } else {
        if( nameArray[thisName] == 1 )
          xmlArray[thisName] = new Array(xmlArray[thisName]);
        xmlArray[thisName][nameArray[thisName]++] = this.parseArray(thisNode);
      }
    }
  }

 //子ノードがテキストノードのみの場合は値を返す。
  if( xmlObject.childNodes.length == nodeNumber )
    return xmlArray[0];
   else
    return xmlArray;
}

// -->
</script>
<title>non-title</title>
</head>
<body>

<form name="form1">
<input type="text" name="text1" size="40">
<input type="button" value=" 検索 " onclick="SearchName();">
</form>

<div id="display">
</div>

</body>
</html>

2   名前: mori : 2007/03/31(土) 15:56  ID:O5SgbufL sub-99
NullPo様

moriです。
わかりづらい用件で申し訳ないです。

ちょっと私の質問の仕方が悪かったです。
動作の確認を行ったところ、ファイル名である数字で検索するとヒットします。
しかし、node1、node2およびnode5の要素で検索してみてもヒットしないです。
(そもそもnode5は検索対象ということを忘れていました)

ちょっと用件を整理して記載します。

フォームに入力された検索文字が、このスクリプトにより検索するところは
./testディレクトリ内の全てのxmlファイルの下記になります。
〜〜〜〜〜〜
node1要素
node2要素
node5要素
ファイル名
〜〜〜〜〜〜
そして最初の質問投稿の際に記載し忘れてしまったのですが

ヒットして表示させる際に
node4の値がmの場合は
性別というところに男性と入るようにしたいです。

要素が空の際に表示されるundefineと
"undefined"も表示させたくないです。


度々ホントに恐れ入ります。
よろしくお願いいたします。

3   名前: 匿名 : 2007/03/31(土) 15:56  ID:6fAvcTJO sub-kJ
http://oshiete1.goo.ne.jp/qa2862967.html

| 条件外のマルチポスト(同じ質問を複数の掲示板に投稿する行為)は禁止です。

4   名前: 匿名 : 2007/03/31(土) 15:56  ID:6fAvcTJO sub-kJ
と言うか、XSL 使ったら?

5   名前: NullPo : 2007/03/31(土) 15:56  ID:hqL.4zaf sub-.G
>>2
マルチポストはやめましょう。

6   名前: mori : 2007/03/31(土) 15:56  ID:bEwhvJYy sub-9f
回答くださった方々へ

"マルチポスト"というものの存在を知りませんでした。
大変失礼いたしました。

決して悪気は無く、
私の技量とは裏腹に納期が迫っているので違う質問スレッドにも質問してしまいました。

技術的なご回答いただけたNullPo様、大変感謝しいたします。
不快な思いをさせてしまい、申し訳ございませんでした。
違う質問スレッドは回答を打ち切り、締め切りました。



7   名前: 匿名 : 2007/03/31(土) 15:56  ID:6fAvcTJO sub-kJ
古いのを引っ張りだしてみたが、IE が手元にないのでテストしてない。エラーが出たらご愛嬌。

データファイル(12345.xml):
<?xml version="1.0" encoding="EUC-JP"?>
<rootnode>
  <node1>111</node1>
  <node2>222</node2>
  <node3>333</node3>
  <node4>m</node4>
  <node5>555</node5>
  <node6>666</node6>
  <node7>777</node7>
  <node8>888</node8>
  <node9>999</node9>
  <nodea>aaa</nodea>
  <nodeb>bbb</nodeb>
  <nodec>ccc</nodec>
  <noded>ddd</noded>
  <nodee>eee</nodee>
</rootnode>

テンプレート(template.xsl):
<?xml version="1.0" encoding="EUC-JP"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!-- テキストで出力 -->
<xsl:output
  method="text"
  encoding="EUC-JP"/>

<!-- パラメータとデフォルト値(デフォルト値は誤ヒットしないよう調節) -->
<xsl:param name="input.node1" select="0"/>
<xsl:param name="input.node2" select="0"/>
<xsl:param name="input.node5" select="0"/>
<xsl:param name="input.fileName" select="0"/>

<!-- テンプレート -->
<xsl:template match="rootnode">
  <xsl:choose>
    <!-- node1、node2、node5 がヒットした場合 -->
    <xsl:when test="node1 = $input.node1 and node2 = $input.node2 and node5 = $input.node5">
      <xsl:value-of select="$input.fileName"/>
      <xsl:text> </xsl:text>
      <xsl:value-of select="node5"/>
      <xsl:text> {</xsl:text>
      <xsl:value-of select="node3"/>
      <xsl:text>種目/</xsl:text>
      <xsl:choose>
        <xsl:when test="node4 = 'm'">
          <xsl:text>男性</xsl:text>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>女性</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:text>}  </xsl:text>
      <xsl:value-of select="node7"/>
      <xsl:text>
    </xsl:text>
      <xsl:value-of select="node9"/>
      <xsl:text> 
    </xsl:text>
      <xsl:choose>
        <xsl:when test="noded = 'no'">
          <xsl:text>×××</xsl:text>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="node1"/>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:text>
</xsl:text>
    </xsl:when>
    
    <!-- node1 はヒットしたが、node2、node5 の値が空の場合 -->
    <xsl:when test="node1 = $input.node1 and node2 = '' and node5 = ''">
      <xsl:text>□□□
</xsl:text>
    </xsl:when>
    
    <!-- node1、node2、node3 のいずれもヒットしなかった場合 -->
    <xsl:otherwise>
      <xsl:text>△△△
</xsl:text>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>

検索フォーム(form.xhtml):
<?xml version="1.0" encoding="EUC-JP"?>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Search Form</title>
    <script type="text/javascript" src="search.js"></script>
  </head>
  <body>
    <form action="#">
      <p>
        <label>node1: <input name="input.node1" value="111" /></label>
        <label>node2: <input name="input.node2" value="222" /></label>
        <label>node5: <input name="input.node5" value="555" /></label>
        <label>fileName: <input name="input.fileName" value="12345" /></label>
        <input type="button" value="TEST" onclick="
            var result = SearchName (
                this.form.elements['input.node1'],
                this.form.elements['input.node2'],
                this.form.elements['input.node3'],
                this.form.elements['input.fileName']
            );
            this.form.elements['output.test'].value = result;
        " />
      </p>
      <p>
        <textarea cols="80" rows="25" name="output.test"></textarea>
      </p>
    </form>
  </body>
</html>

テンプレート呼び出し(search.js):
/**
 * - この関数は、テンプレートを呼び出して結果を返すだけ。
 * - Firefox 対応が必要なら XSLTProsessor で書き換える。
 * - Microsoft.XMLDOM はメンテナンスが終了しているので、MSXML2 を使う。
 * - 検索のたびにファイルを読み込むのは馬鹿馬鹿しいので、フォーム読み込みと同時に
 *   XSLT プロセッサの作成までしておいた方が良い。
 * - ここではファイルの存在チェックをしていない。
 */
function SearchName (nodeValue1, nodeValue2, nodeValue5, fileName) {
    // for IE6+
    try {
        // XML ドキュメントの読み込み
        var xmlDoc = new ActiveXObject ('Msxml2.DOMDocument.3.0');
        xmlDoc.async = false;
        xmlDoc.load (fileName + '.xml');
        
        // XSL ドキュメントの読み込み
        var xslDoc = new ActiveXObject ('Msxml2.FreeThreadedDOMDocument.3.0');
        xslDoc.async = false;
        xslDoc.load ('template.xsl');
        
        // XSL テンプレートの作成
        var xslTemp = new ActiveXObject ('Msxml2.XSLTemplate.3.0');
        xslTemp.stylesheet = xslDoc;
        
        // XSLT プロセッサの作成
        var xsltProc = xslTemp.createProcessor ();
        xsltProc.input = xmlDoc;
        
        // パラメータのセット
        xsltProc.addParameter ('input.node1', nodeValue1);
        xsltProc.addParameter ('input.node2', nodeValue2);
        xsltProc.addParameter ('input.node5', nodeValue5);
        xsltProc.addParameter ('input.fileName', fileName);
        
        // 変換開始
        xsltProc.transform ();
        
        // 結果を返す(このままならテキスト)
        return xsltProc.output;
        
    } catch (error) {
        throw error;
    }
}

8   名前: 匿名 : 2007/03/31(土) 15:56  ID:6fAvcTJO sub-kJ
訂正。

form.xhtml:
        <input type="button" value="TEST" onclick="
            var result = SearchName (
                this.form.elements['input.node1'].value,
                this.form.elements['input.node2'].value,
                this.form.elements['input.node5'].value,
                this.form.elements['input.fileName'].value
            );
            this.form.elements['output.test'].value = result;
        " />

9   名前: mori : 2007/03/31(土) 15:56  ID:HA2EdKCD sub-99
>>7 の方
変身遅くなり申し訳ございません。

ご返信ありがとうございます。
さっそく試してみたいと思います。

進捗等またこの掲示板に記載いたします。

本当にありがとうございます。

10   名前: 匿名 : 2007/03/31(土) 15:56  ID:6fAvcTJO sub-kJ
補足。XSL を使わず、あくまで JScript だけで処理する場合、

>>1 は、XML データを参照するのに、とっても面白い工夫をしている。特に (X)HTML をクロスブラウザ的に処理するのに有効なので、お勧め。

ただ今回、どうせ IE しか対象にしないのであれば、XML ドキュメントなら XPath を使える(IXMLDOMDocument.selectNodes/selectSingleNode)。
xmlDoc.load (...);
xmlDoc.setProperty ('SelectionLanguage', 'XPath');  // for MSXML 3.0-

var value1 = xmlDoc.selectSingleNode ('descendant::node1');
var value2 = xmlDoc.selectSingleNode ('descendant::node2');
var value5 = xmlDoc.selectSingleNode ('descendant::node5');

XML データが平坦だから、簡単な XPath 式で済む。値さえ抜き取れれば、あとは整形と出力だけだから、力技で何とかなるだろう。

11   名前: mori : 2007/03/31(土) 15:56  ID:HA2EdKCD sub-99
moriです。
進捗を報告いたします。

組み込んでみて判明したのですが、
>>1 様の方法のほうが組み込みたい環境に適しています。検索文字列をkeyにfilenameしか検索していないような動きです。
>>7 様の方法で書いてみましたが、3つのフィールドがあることがネックになってしまいます。
>>1 様の方法で1つのtextフィールド(name="text1")で入力した検索文字列がkeyにfilename/node1/node2/node5の要素をそれぞれ検索する方法はございますでしょうか?



12   名前: 匿名 : 2007/03/31(土) 15:56  ID:6fAvcTJO sub-kJ
>>10 の訂正。ノードのままだった。
var value1 = xmlDoc.selectSingleNode ('descendant::node1').xml;
var value2 = xmlDoc.selectSingleNode ('descendant::node2').xml;
var value5 = xmlDoc.selectSingleNode ('descendant::node5').xml;


>>11
> 3つのフィールドがあることがネックになってしまいます。
> 1つのtextフィールド(name="text1")で入力した検索文字列がkeyに

どんな文字列で何を検索するのか、私には未だに分からない。だから、とりあえず 3 つ置いた。key が固定なら、SearchName() にそう与えるなり、Wrapper でも作るなりすれば良いだけ。

あと不安になったので言っておくが、納品するなら間違っても >>7 のままではいけない。あれはあくまで動作サンプル。ファイルの読み込み方法を工夫しる。あと >>10 に書いたのは、>>1 と同じやり方。

13   名前: mori : 2007/03/31(土) 15:56  ID:O5SgbufL sub-99
皆様のおかげで何とか無事上がりました。

>>12 様のWrapperというご提案及びスクリプト内の".xml"への修正
を行い、あとはちょこっと加工して希望どおりの動きが作れました。
当初はルール違反を犯してしまったにもかかわらず、最後までお付き合いいただき、誠に感謝いたします。
どうもありがとうございました。

本掲示板ははじめての参加でしたが、
色んな意味でとても良い場所であると感じました。
是非、今後も参加させていただきます。

今回は本当にありがとうございました。

一覧へ戻る