プロが教える店舗&オフィスのセキュリティ対策術

XMLでデータベースを作り、Javascriptで検索、HTMLで表示させていますが、一単語しか受け付けません(compareStringで検索させているためだと思います)。

yahooやgoogleのように複数単語を受け付けるようにしたいです。
複数キーワードをスペース区切りなどで入れ、AND検索できるようにするにはどうしたらいいでしょうか。

参考サイトや助言などご教授いただきたく、よろしくお願いいたします。

A 回答 (2件)

No.1 補足より。

ずいぶん古いサンプルコードですが、IE5.5+ で動けば良いのですね? 他のブラウザは考慮外で、ウェブ上ではなく手元で動けば十分なのですね?

ならば、次のようなフォームがあるとして(載っていないのでこちらで作りました)、

<form action="#" onsubmit="try { Search (this); } finally { return false; }">
 <fieldset>
  <legend>検索</legend>
  <p><input type="text" name="keywords" value=""></p>
  <div id="hyouji"></div>
 </fieldset>
</form>

次のように Search() を修正します。xslt.xsl の中身は分かりませんが、そのまま使えるはずです。

function Search (form) {
 try {
  var srcURI = 'sampAl.xml';
  var xslURI = 'xslt.xsl';
  var contextNode = form.document.all ('hyouji');
  var i;

  // 後で使う IE の split() にはバグがあるので、先に処理しておく
  var keywordString = form.elements['keywords'].value.
   replace (/^\s+|\s+$/g, '').replace (/\s+/g, '\x20');

  if (keywordString.length === 0) {
   contextNode.innerHTML = '<p>キーワードなし。<\/p>';
   return;
  }

  if (keywordString.indexOf ('"') > -1) {
   contextNode.innerHTML = '<p>検索語に二重引用符を含めないで下さい。<\/p>';
   return;
  }
  
  var keywords = keywordString.split ('\x20');
  var keywordCount = keywords.length;

  // "Microsoft.XMLDOM" は古いので使わないこと
  var srcDoc = new ActiveXObject ('Msxml2.DOMDocument.3.0');
  srcDoc.async = false;
  srcDoc.setProperty ('SelectionLanguage', 'XPath'); // MSXML 3.0 のため
  srcDoc.load (srcURI);

  if (srcDoc.parseError.errorCode !== 0) {
   contextNode.innerHTML = '<p>データの読み込みに失敗しました。<\/p>';
   return;
  }

  var expr = [ ];
  for (i = 0; i < keywordCount; i++) {
   expr[expr.length] = 'contains(., "' + keywords[i] + '")';
  }

  var nodes = srcDoc.selectNodes (
   'child::英語 / child::色データ' +
   '[ child::英単語 [' + expr.join (' and ')+ ' ]]');

  var nodeCount = nodes.length;

  if (nodeCount === 0) {
   contextNode.innerHTML = '<p>データなし。<\/p>';
   return;
  }

  // XML 宣言は処理命令ではない
  var newDoc = new ActiveXObject ('Msxml2.DOMDocument.3.0');
  var newRoot;
  newDoc.loadXML ('<?xml version="1.0"?><英語 />');
  newRoot = newDoc.documentElement;

  // MSXML 3.0 を使っているので importNode() がない
  for (i = 0; i < nodeCount; i++) {
   newRoot.appendChild (nodes[i].cloneNode (true));
  }

  var xslDoc = new ActiveXObject ('Msxml2.FreeThreadedDOMDocument.3.0');
  xslDoc.async = false;
  xslDoc.load (xslURI);

  if (xslDoc.parseError.errorCode !== 0) {
   contextNode.innerHTML = '<p>スタイルシートの読み込みに失敗しました。<\/p>';
   return;
  }

  var xslTemp = new ActiveXObject ('Msxml2.XSLTemplate.3.0');
  xslTemp.stylesheet = xslDoc;

  var xsltProc = xslTemp.createProcessor ();
  xsltProc.input = newDoc;
  xsltProc.transform ();

  contextNode.innerHTML = xsltProc.output;
 }
 catch (err) {
  throw err;
 }
}

この回答への補足

Chaire様

質問者のsuimii_eoです。あれから何度か上記ソースでトライして、無事に検索可能になりました・・!
本当にありがとうございました。

補足日時:2011/10/07 10:07
    • good
    • 0
この回答へのお礼

再度の回答、ありがとうございます。
ご指摘の通り、IE+7以上で動き、サーバーを介さずにデータを渡す、ということがしたいのです。

職場にて、ソースをそのまま使用して動かしてみました。結果として「キーワードなし」と「データなし」は表示されるのですが、検索が機能できず・・。ただ、見ていただいたものが古いことを教えていただき、それを踏まえての丁寧な回答をいただき、とても勉強になります。

コードを見ても全然ピンとこない部分もあり、かなりの勉強不足を痛感しています。ここに記していただいたコードを元に、(xPath含め)再度やり直してみたいと思います。

いったん質問は締めたいと思いますが、またこちらに質問させていただく際には、どうぞよろしくお願いいたします。

お礼日時:2011/09/26 14:16

JavaScript や XML 周辺で compareString() なる標準関数は(現状)ありませんので、独自関数・システムのお話であればもう少し詳細を説明なさった方が回答がつくと思います。



とにかく、XML を読み込めるブラウザ(メジャー所では IE、Fx、Op、Sa、Ch)なら最低限 XPath 1.0 を使えるはずですので、

・OR 検索例:文字列値が 1 または 2 の HUGA 要素を持つ HOGE 要素
/descendant::HOGE[child::HUGA = "1" or child::HUGA = "2"]

・AND 検索例:文字列値が 1 の HUGA 要素と、3 の GEHO 要素を持つ HOGE 要素
/descendant::HOGE[child::HUGA = "1" and child::GEHO = "3"]

のような XPath 式を作れば良い。そのまま XSLT で HTML 変換するのが手っ取り早いでしょう。

※バックエンドで XQuery でも使えれば一番早いのですけどね。

この回答への補足

丁寧な回答、本当にありがとうございます。XPathを使って検索(AND検索希望)できるのですね。まだよくわかっていないので、調べたいと思います。

私の質問が悪く自分でも混乱してきましたので、おこがましいのですが質問元となったソースをみていただきたく、こちらに書かせていただいています。

xml:
<?xml version="1.0" encoding="shift_jis"?>
<英語>
<色データ>
<番号>1</番号>
<色>赤</色>
<英単語>red</英単語>
</色データ>
<色データ>
<番号>2</番号>
<色>青</色>
<英単語>blue</英単語>
</色データ>
</英語>

***
javascript:

function Search(ky)
{
var obXML = new ActiveXObject('microsoft.XMLDOM');
obXML.async = false;
obXML.load('sampAl.xml');
var Rnode = obXML.documentElement;
var hzn = new ActiveXObject('microsoft.XMLDOM');
var Rhzn = hzn.createElement("英語");
var string = "";
var tx = "";
if(Rnode.hasChildNodes())
{
for(i = 0;i <= Rnode.childNodes.length -1;i++)
{
tx = Rnode.childNodes.item(i).childNodes.item(2).text;
if(compareString(ky.value,tx))
{
Rhzn.appendChild(Rnode.childNodes.item(i));
i = i - 1;
}
}
}
else
{
string += "データなし<br>";
hyouji.innerHTML = string;
return;
}
var sen = hzn.createProcessingInstruction("xml", 'version="1.0"');
hzn.insertBefore(sen, hzn.childNodes.item(0));
hzn.appendChild(Rhzn);
var obXSL = new ActiveXObject('microsoft.XMLDOM');
obXSL.async = false;
obXSL.load("xslt.xsl");
hyouji.innerHTML = hzn.transformNode(obXSL);
}
function compareString(inputky,nodetext)
{
if(inputky == "")
{return false;}
if(inputky == nodetext)
{
return true;
}
else
{
var ofs = nodetext.indexOf(inputky);
if(ofs != -1)
{
return true;
}
return false;
}
}
</script>

以上

***

web上で見つけたソースを参考に作りました。htmlの<form>タグで検索することができます。
検索キーワードに(上記で例えると)「e b」と入力することで、絞込み(AND)検索ができることを目指しています。(キーワードの間はスペースでも、コンマでもなんでも構いません)
情報が足りない場合は再度書き込みたいと思います。
私の理解としては、if(compareString(ky.value,tx)) にて、入力したキーワードとxmlの中を比較し、var ofs = nodetext.indexOf(inputky); で、返していると思っていました・・。

稚拙な質問ですみません・・。どうぞよろしくお願いいたします。

補足日時:2011/09/22 22:36
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!