• 検索結果がありません。

tabindex='3'>タイトル 1 はとても面白かったです。

ドキュメント内 Microsoft Word - 3部.doc (ページ 37-64)

27:ぜひ聞いてみてください。</textarea>

28: </td>

29: </tr>

30: </table>

31: </div>

32: </form>

リスト7の太字部分をXMLから出力します。それ以外はリスト7の内容を、そのまま

PrintWriterオブジェクトに出力するだけです。

383: } else if (_mode.equals("modify_form")) { 384: // 更新フォームの表示

385: try {

386: // XML の作成

387: // DocumentBuilderFactory オブジェクトの作成 388: DocumentBuilderFactory dbf =

389: DocumentBuilderFactory.newInstance();

390: // DocumentBuilder オブジェクトの作成

391: DocumentBuilder db = dbf.newDocumentBuilder();

392: // XML の読み込み

393: Document document = db.parse(new File(XML_FILE));

394: // BBS 要素の取得

395: Element root = (Element)document.getDocumentElement();

396: // Message 要素一覧の取得

397: NodeList list = root.getChildNodes();

398: for (int i = 0; i < list.getLength(); i++) {

399: if (list.item(i).getNodeType() == Node.ELEMENT_NODE) { 400: Element message = (Element)list.item(i);

401: if (message.getAttribute("No").equals(_no)) { 402: // Subject 要素の取得

403: Node subject =

404: message.getElementsByTagName("Subject").item(0);

405: _subject = subject.getFirstChild().getNodeValue();

406: // Name 要素の取得 407: Node name =

408: message.getElementsByTagName("Name").item(0);

409: _name = name.getFirstChild().getNodeValue();

410: // Comment 要素の取得 411: Node comment =

412: message.getElementsByTagName("Comment").item(0);

413: _comment = comment.getFirstChild().getNodeValue();

414: break;

415: } 416: } 417: }

418: } catch (Exception e) {

419: // 例外処理(メッセージの出力)

420: OutputMessage(out, e.getMessage());

421: return;

422: }

423: out.println("<form action='/bbs/BBS' method='post'>");

424: out.println("<div style='margin-left:40'>");

425: out.println("<input type='hidden' name='mode' value='modify'>");

426: out.println("<input type='hidden' name='no' value='" + _no + "'>");

427: out.println("<table>");

428: out.println("<tr>");

429: out.println("<td><b>題名</b></td>");

430: out.println("<td>");

431: out.println("<input type='text' name='subject' value='" + 432: _subject + "' size='30' maxlength='100' tabindex='1'>");

433: out.println("</td>");

434: out.println("</tr>");

435: out.println("<tr>");

436: out.println("<td><b>名前</b></td>");

437: out.println("<td>");

438: out.println("<input type='text' name='name' value='" + 439: _name + "' size='30' maxlength='100' tabindex='2'>");

440: out.println("<input type='submit' value='更新する' tabindex='4'>");

441: out.println("<input type='reset' value='リセット' tabindex='5'>");

442: out.println("</td>");

443: out.println("</tr>");

444: out.println("<tr>");

445: out.println("<td colspan=2>");

446: out.println("<b>コメント</b><br>");

447: out.println("<textarea name='comment' cols='50' rows='8'"

448: + " tabindex='3'>" + _comment + "</textarea>");

449: out.println("</td>");

450: out.println("</tr>");

451: out.println("</table>");

452: out.println("</div>");

453: out.println("</form>");

⑦と同様に、NoパラメータのMessage要素を検索し、その内容を初期値として表示し ます。

⑬ 検索フォームの表示

メッセージの検索フォームの表示(mode=search_form)の処理です。検索のための HTMLフォームを表示します。

リスト8に検索フォームのHTMLを示します。実際の画面は図3のようになります。

リスト8 検索フォームのHTML

1: <form action='/bbs/BBS' method='post'>

2: <div style='margin-left:40'>

3: <input type='hidden' name='mode' value='search'>

4: <b>キーワード</b>

5: <input type='text' name='keyword' size='30' maxlength='30'>

6: <input type='submit' value='検索する'>

7: </div>

8: </form>

リスト8の内容を、そのままPrintWriterオブジェクトに出力するだけです。

454: } else if (_mode.equals("search_form")) { 455: // 検索フォームの表示

456: out.println("<form action='/bbs/BBS' method='post'>");

457: out.println("<div style='margin-left:40'>");

458: out.println("<input type='hidden' name='mode' value='search'>");

459: out.println("<b>キーワード</b>");

460: out.println("<input type='text' name='keyword' size='30'" + 461: " maxlength='30'>");

462: out.println("<input type='submit' value='検索する'>");

463: out.println("</div>");

464: out.println("</form>");

465: }

⑭ 共通フッタ

468: out.println("</body>");

469: out.println("</html>");

クライアントに表示するHTMLの全ての処理に共通なフッタを出力します。

7.2.3 メッセージ表示

473: private void OutputMessage(PrintWriter out, String msg) { 474: out.println(msg);

475: out.println("</body>");

476: out.println("</html>");

477: }

エラーが発生した場合にメッセージを表示して共通フッタを表示します。

このメソッドは、以下のように、各処理のパラメータのチェック(必要な場合)及び例 外処理で使用しています。(「処理」、「パラメータ」の部分は、それぞれ各処理により異な ります。)

1: } else if (_mode.equals(「処理」)) { 2: // パラメータのチェック

3: if (「パラメータ」== null || 「パラメータ」.length() == 0) { 4: OutputMessage(out, "「パラメータ」を入力してください");

5: return;

6: } 7: try {

8: // 通常の処理 9: } catch (Exception e) {

10: // 例外処理(メッセージの出力)

11: OutputMessage(out, e.getMessage());

12: return;

13: } 14: }

7.3 SAXイベントハンドラ

最後に検索結果表示と一覧表示のSAXイベントハンドラを作成します。

7.3.1 検索結果表示イベントハンドラ

リスト9に検索結果のHTMLを示します。実際の画面は図4のようになります。

リスト9で1~9行目と18~19行目はXMLデータと関連が無い部分ですので、それ ぞれドキュメント開始時とドキュメント終了時に表示します。

要素の開始タグ読み込み時にNo、Delete属性を保存します。そして、要素の終了タグ読 み込み時にテキストデータから Subject、Name、Contribution、Comment 要素を取得し てキーワード検索を行い、マッチした場合に、10~17行目を表示します。

リスト9 検索結果のHTML(太字はXMLデータ)

1: <div align='center'>

2: <table width='80%' border='2'>

3: <tr>

4: <th>番号</th>

5: <th>題名</th>

6: <th>名前</th>

7: <th>日時</th>

8: <th>コメント</th>

9: </tr>

10: <tr>

11: <td>1</td>

12: <td>面白いです。</td>

13: <td>山田太郎</td>

14: <td>2004-11-29 15:28:59</td>

15: <td>タイトル1はとても面白かったです。

16:ぜひ聞いてみてください。</td>

17: </tr>

18: </table>

19: </div>

① クラス定義

480: class SearchHandler extends DefaultHandler { 481:

482: // 出力先を保存するオブジェクト 483: private PrintWriter out;

484: // キーワードを保存する文字列 485: private String keyword;

486: // No 属性値を保存する文字列 487: private String no;

488: // Delete 属性値を保存する文字列 489: private String delete;

490: // テキストデータを保存する文字列 491: private String text;

492: // Subject 要素のデータを保存する文字列 493: private String subject;

494: // Name 要素のデータを保存する文字列 495: private String name;

496: // Contribution 要素のデータを保存する文字列 497: private String contribution;

498: // Comment 要素のデータを保存する文字列 499: private String comment;

500:

501: SearchHandler(PrintWriter pw, String s) { 502: out = pw;

503: keyword = s;

504: }

検 索 結 果 表 示 イ ベ ン ト ハ ン ド ラ を SearchHandler と い う 名 称 で 作 成 し ま す 。

PrintWriterオブジェクトと検索キーワードを受け取るために、コンストラクタを定義し

ています。

② ドキュメント開始時

507: public void startDocument() { 508: // テーブルのヘッダを表示

509: out.println("<div align='center'>");

510: out.println("<table width='80%' border='2'>");

511: out.println("<tr>");

512: out.println("<th>番号</th>");

513: out.println("<th>題名</th>");

514: out.println("<th>名前</th>");

515: out.println("<th>日時</th>");

516: out.println("<th>コメント</th>");

517: out.println("</tr>");

518: }

検索結果をテーブルにするためのヘッダを表示します。

③ 要素の開始タグ読み込み時

521: public void startElement(String uri, 522: String localName, 523: String qName,

524: Attributes attributes) { 525: if (qName.equals("Message")) { 526: // No 属性を保存

527: no = attributes.getValue("No");

528: // Delete 属性を保存

529: delete = attributes.getValue("Delete");

530: if (delete == null) delete = "false";

531: }

532: text = "";

533: }

Message 要素の処理をします。属性を検索し、No属性とDelete属性の内容を保存し

ます。Delete 属性が無い場合には"false"にしておきます。又、全ての要素で、テキスト データの読み込みのために文字列を初期化します。

③ テキストデータ読み込み時

536: public void characters(char[] ch, int offset, int length) { 537: text += new String(ch, offset, length);

538: }

String クラスで文字列を取り出し、テキストデータを保存しておきます。要素の内容

に改行がある場合、複数回呼び出されますので、文字列を連結しています。

④ 要素の終了タグ読み込み時

541: public void endElement(String uri, String localName, String qName) { 542: if (qName.equals("Subject")) {

543: // Subject 要素を保存 544: subject = text;

545: } else if (qName.equals("Name")) { 546: // Name 要素を保存

547: name = text;

548: } else if (qName.equals("Contribution")) { 549: // Contribution 要素を保存

550: contribution = text.substring(0, 10) + " " + text.substring(11, 19);

551: } else if (qName.equals("Comment")) { 552: // Comment 要素を保存

553: comment = text;

554: } else if (qName.equals("Message") && delete.equals("false")) { 555: // 削除されていない場合はキーワードを検索

556: if (subject.indexOf(keyword) != -1 ||

557: comment.indexOf(keyword) != -1) { 558: out.println("<tr>");

559: out.println("<td>" + no + "</td>");

560: out.println("<td>" + subject + "</td>");

561: out.println("<td>" + name + "</td>");

562: out.println("<td>" + contribution + "</td>");

563: out.println("<td>" + comment + "</td>");

564: out.println("</tr>");

565: } 566: } 567: }

それぞれの要素の内容を保存しておきます。Message 要素の終了タグの場合、削除され ていなければキーワード検索を行い、マッチしたメッセージを表示します。

⑤ ドキュメント終了時

570: public void endDocument() { 571: // テーブルを閉じる 572: out.println("</table>");

573: out.println("</div>");

574: }

テーブルを終了します。

7.3.2 一覧表示イベントハンドラ

以下の点を除き、検索結果表示イベントハンドラと同様です。

① イベントハンドラの名称がListHandlerである

② コンストラクタにキーワードが渡されない

③ Message要素の終了タグの場合での処理でキーワードとの比較を行わない

8.プログラムのコンパイルと実行

最後に、プログラムのコンパイルと実行です。(プログラムをコンパイルするための環境 設定については、付録を参照してください。)

リスト10 クラス定義とプログラムのコンパイル(太字はコマンド入力)

C:¥java¥bbs¥WEB-INF¥classes> xjc BBS.xsd

C:¥java¥bbs¥WEB-INF¥classes> javac BBSServlet.java

Tomcatを使用してServletを実行するためには、以下のようなディレクトリ構成が必要

です。ルートディレクトリの名前は任意です。ここでは「C:¥java¥bbs」とします。

図8 プログラム実行のためのディレクトリ構成 スキーマ定義の作成

XSLTの作成

プログラムを作成

(Javaプログラミング)

プログラムの実行 (Tomcatによる実行)

classes

web.xml WEB-INF

lib

Servletと関連プログラムのコンパイル済みファイル 必要なjarファイル

アプリケーションの設定ファイル

ルートディレクトリ(C:¥java¥bbs) アプリケーションのルートディレクトリ

通常表示XSLT

(BBS.xsl)

掲示板XMLファイル

(BBS.xml)

掲示板スキーマ定義

(BBS.xsd)

今回は、それぞれのフォルダに以下のファイルを置き、classesフォルダでコンパイルし ます。尚、他のフォルダでコンパイルしてclassesフォルダにclassファイルをコピーして も問題ありませんが、スキーマ定義のコンパイルで出来た階層構造のclassファイルも全て コピーする必要があります。

・ルート BBS.xml、BBS.xsl

・WEB-INF web.xml

・classes BBSServlet.java、BBS.xsd

・lib jaxb-api.jar、jaxb-impl.jar、jaxb-libs.jar、jaxb-xjc.jar、

jax-qname.jar、 namespace.jar、relaxngDatatype.jar、xsdlib.jar

web.xmlの内容をリスト6に示します。

内容は、<servlet>タグの<servlet-class>タグにServletファイル名、<servlet-name>タ グに、キーワードを指定します。<servlet-mapping>タグの<servlet-name>タグは同じキ ーワードを指定して、<url-pattern>タグにアクセスするURLを指定します。

リスト11 web.xml(太字は任意設定値)

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app

PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<servlet>

<servlet-name>BBS</servlet-name>

<servlet-class>BBSServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>BBS</servlet-name>

<url-pattern>/BBS</url-pattern>

</servlet-mapping>

</web-app>

最後に「Tomcat Manager」から図7のように設定して、配備ボタンを押下すれば

「http://localhost:8080(Tomcatのポート番号)/bbs/BBS」で実行出来ます。ここで「WAR ファイル又はディレクトリのURL」には先程のルートディレクトリを指定します。

図9 Tomcat Managerの設定

9.コーディングリスト

コーディングリストをリスト12に示します。

リスト12 BBSServlet.java 1: import java.io.*;

2: import java.math.*;

3: import java.text.*;

4: import java.util.*;

5: import javax.servlet.*;

6: import javax.servlet.http.*;

7: import javax.xml.bind.JAXBContext;

8: import javax.xml.bind.Marshaller;

9: import javax.xml.bind.Unmarshaller;

10: import javax.xml.bind.Validator;

11: import javax.xml.parsers.*;

12: import javax.xml.transform.*;

13: import javax.xml.transform.dom.*;

14: import javax.xml.transform.stream.*;

15: import org.w3c.dom.*;

16: import org.xml.sax.*;

17: import org.xml.sax.helpers.*;

18:

19: // スキーマコンパイラが生成したクラスのインポート

20: import educationproject.bbs.*;

21:

22: public class BBSServlet extends HttpServlet { 23:

24: // XML ファイル名

25: final String XML_FILE = "C:¥¥java¥¥bbs¥¥BBS.xml";

26: // XSLT スタイルシートファイル名

27: final String XSL_FILE = "C:¥¥java¥¥bbs¥¥BBS.xsl";

28:

29: // GET リクエストの処理

30: public void doGet(HttpServletRequest request, 31: HttpServletResponse response)

32: throws IOException, ServletException { 33: // POST リクエストの処理を呼び出す 34: doPost(request, response);

35: } 36:

37: // POST リクエストの処理

38: public void doPost(HttpServletRequest request, 39: HttpServletResponse response)

40: throws IOException, ServletException { 41:

42: // ファイルに保存するためのストリーム 43: FileOutputStream fos = null;

44:

45: // 入力文字コードの指定

46: request.setCharacterEncoding("Shift_JIS");

47: // 出力文字コードの指定

48: response.setContentType("text/html;charset=Shift_JIS");

49: // PrintWriter オブジェクトを取得 50: PrintWriter out = response.getWriter();

51:

52: // XML ファイルが無ければ作成 53: File file = new File(XML_FILE);

54: if (!file.exists()) { 55: try {

56: // JAXBContext オブジェクトの作成 57: JAXBContext jc =

58: JAXBContext.newInstance("educationproject.bbs");

59: // ObjectFactory オブジェクトの作成 60: ObjectFactory of = new ObjectFactory();

61: // BBS 要素の作成

62: BBS bbs = of.createBBS();

63: // ファイルへ書き出し

64: Marshaller m = jc.createMarshaller();

65: m.setProperty(Marshaller.JAXB_ENCODING, "Shift_JIS");

66: m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, 67: Boolean.TRUE);

68: fos = new FileOutputStream(XML_FILE);

69: m.marshal(bbs, fos);

70: fos.close();

71: } catch (Exception e) {

72: // 例外処理(メッセージの出力)

73: OutputMessage(out, e.getMessage());

74: return;

75: } 76: } 77:

78: // リクエストパラメータを取得 79: // 処理モード

80: String _mode = request.getParameter("mode");

81: if (_mode == null) _mode = "normal";

82: // メッセージ番号

83: String _no = request.getParameter("no");

84: // 題名

85: String _subject = request.getParameter("subject");

86: // 名前

87: String _name = request.getParameter("name");

88: // コメント

89: String _comment = request.getParameter("comment");

90: // 検索キーワード

91: String _keyword = request.getParameter("keyword");

92:

93: // 共通ヘッダ

94: out.println("<html>");

95: out.println("<head>");

96: out.println("<title>掲示板</title>");

97: out.println("</head>");

98: out.println("<body>");

99: out.println("<div align='center'><h3>掲示板</h3></div>");

100: out.println("<div align='center'>"

101: + "[ <a href='/bbs/BBS?mode=normal'>通常表示</a> ] "

ドキュメント内 Microsoft Word - 3部.doc (ページ 37-64)

関連したドキュメント