- ベストアンサー
JSPでXMLのデータ表示がしたいです
XMLについてわからないことが多くて、困っています。 質問したいのですが、 JSPの画面でXMLのデータを表示させたいと思っています。 全部のデータを表示という場合、getDocumentElement()メソッドが あると思うのですが、例えばテキストノードのみを表示させたい場合、 <タグ>などのノードから、全テキストノードを一気に拾い出す方法は あるのでしょうか?メソッドとか。 ただ表示させるだけではなくて、データの削除とか変更などのデータ加工 もしていきたいので、最適なデータの表示がしたいんです。なので、操作 をしやすい取り出し方というか。。。 漠然とした質問で申し訳ありませんが、詳しい方がいましたら教えてもらえ ないでしょうか?お願いします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
#1です。 >この方法だと、例えば「ルート要素の2番目の子ノードのそのまた子ノードの情報を全て取り出す」とか指定したりできるのでしょうか?? Beanにしているから簡単にできます。 Beanでしなければ、毎回、長々とコーディングしなければならなくなり、後から見れば、何をさせているかわからなくなります。 JSPでBeanを使う場合、ディレクティブの次に、 <jsp:useBean id="lbn" class="jp.co.sei.system.izumi.bean_list" scope="page" /> のような、Beanが使えるように記述を行います。 この例の場合、簡単に言えば、jp.co.sei.system.izumi.bean_listを、このJSPでは、lbnと省略?させる事を唄っています。 で、、 DOMParser prs = new DOMParser(); FileReader fr = new FileReader(application.getRealPath(xml_path)); BufferedReader br = new BufferedReader(fr); InputSource src = new InputSource(br); prs.parse(src); Document objDoc = prs.getDocument(); と、Rootになる、Documentオブジェクトだけを先にJSPに処理させておけば、 後は、Beanを呼び出して、「何階層目の、Nodeのさらに次のNodeの情報がほしい」と簡潔に指定するようにします。 例えば、 <?xml version="1.0" encoding="Shift_JIS"?> <listsadm> <member id="1"> <subject>システムXXXX</subject> <path>/section/sysgi/listsinf.xml</path> <cmt>XXXX技術部 CSVファイルリスト</cmt> <usr>listsadm</usr> <datapath>D:/WEBDATA/zikkenn</datapath> </member> <member id="2"> <subject>XXXXXグループ</subject> <path>/section/zikai/listsinf.xml</path> (1)→ <cmt>TEST</cmt> <usr>listsadm</usr> <datapath>D:/WEBDATA/zikkenn</datapath> </member> </listsadm> のようなファイルから、(1)のTESTを呼び出すには、 Beanの public Node xmlObjNod2(Document objDoc, int intItem0, int intItem1){ Node objNod2 = xmlClnNod2(objDoc, intItem0).item(intItem1); return objNod2; } をJSPから、 lbn.nmlObjNod2(objDoc,1,2).getValue() (ご存知とは思いますが、カウントは0から始まります。) で、StringでTESTを返してきますよ。 全てほしいなら、 for(int n=0, n<lbn.xmlClnNod2(objDoc, iln).getLength(); n++ ){ out.println(lbn.nmlObjNod2(objDoc,1,n).getValue()); } のようにすれば、lbn.xmlClnNod2がNodeListを返すように成っているので、このgetlength()分くるくる回せば、取得できますよ。
その他の回答 (3)
- a-kuma
- ベストアンサー率50% (1122/2211)
> >この処理をして、結果を貯めておくようなクラスを作って、 > >それを JSP から呼び出すような感じになるかな。 > > というのは、別のクラスでノードを拾い出すメソッドを作って、それをjspで > 必要な時に活用するということですか?それとも拾い出したノードを格納するクラス(Beanのような)を作るといいということでしょうか?? どっちでも良いと思いますよ。自分がどういう使い方をするかで決まってくると思います。 ただ、XML を扱う処理は、それなりにコードを書かなければいけないので、その処理を請け負ってくれる クラスを作っておく方が、何かと便利か、と。 そのクラスは、Servlet に関係なく(HttpSession などを使わない)ように作っておくと コマンドプロンプトレベルで動作確認ができるので、デバッグをする際には有効です。 そういった XML を処理するロジックを持ったクラスが解析したノードを保持するのでも良いですし、 解析したノードを保持するクラスが別にあっても良いですし。 # 私なら、別にしておきます
お礼
やっぱりある程度決まった処理なら、別クラスを作って必要な時に 呼び出すのが一番ということですね。 XMLは結構奥が深くて、勉強してもあまり前に進めません。。 別クラスを作ってちゃんと活用できるようになりたいと思います。 参考になりました。ありがとうございました。
- a-kuma
- ベストアンサー率50% (1122/2211)
確かに、漠然としてますね。テキストノードを一気に拾い出すことと、データの削除や加工をするということは、 それぞれのノードを区別するということですから、相反していますよね。 まずは、落ち着いて、使用を考え直してみた方が良いのでは? で、テキストノードをがさっと取り出す方法は、ぱっと二つほど思いつきます。 まず DOM でたどってゆくなら、こんな感じ。 Document doc = 適当な方法で DOM を Node n = doc.getDocumentElement(); while (n != null) { if (n instanceof Text) { // なにか、テキストを使う処理。例えば… System.out.println(n.getNodeValue() + "\n"); } if (n.hasChildNodes()) { n = n.getFirstChild(); } else { Node next; while ((next = n.getNextSibling()) == null) { n = n.getParentNode(); if (n == null) { break; } } n = next; } } もうひとつは SAX を使う処理。 class TextDump extends DefaultHandler { TestDump() {} public void characters(char[] ch, int start, int length) throws SAXException { // テキストノードの内容が ch に入ってくるので、例えば… String s = new String(ch, start, length); System.out.print(s); } public void endElement(String namespaceURI, String localName, String qName) throws SAXException { System.out.println(""); } } SAXParser sp = SAXParserFactory.newInstance().newSAXParser(); TextDump td = new TextDump(); File f = new File(ファイル名); sp.parse(f, td); どちらも処理としてはたいしたこと無いけど、やりたい処理次第で JSP に埋め込むのは 煩雑だから、この処理をして、結果を貯めておくようなクラスを作って、 それを JSP から呼び出すような感じになるかな。 この程度のことは、sun のチュートリアル(→参考URL)を読めば、一日で作れるようになりますよ。 # どちらのコードも、リファレンスを見ながら、ざっざっと書いただけなので、 # 動作の保証はありません (^^;
補足
確かに、ノードを一気に拾い出すことと、データを加工していくことはノードの処理も違ってきますよねー。自分でも混乱していて、質問内容もめちゃくちゃだったかも。 それなのに教えてくれてありがとうございました。 テキストノードの拾い方、とてもわかりやすかったです。これだと簡単にできるし、他のノードなどでも、すぐできますね。 ひとつ教えてもらえるとありがたいのですが >この処理をして、結果を貯めておくようなクラスを作って、 >それを JSP から呼び出すような感じになるかな。 というのは、別のクラスでノードを拾い出すメソッドを作って、それをjspで 必要な時に活用するということですか?それとも拾い出したノードを格納するクラス(Beanのような)を作るといいということでしょうか?? よろしければ教えてください、お願いします。
- COOKY2
- ベストアンサー率28% (2/7)
例えば、こんな、Beanを作っておいて、、 (XMLファイルが、5階層必要ならば、こんなかんじ、、) package XX.XXX.xxx.system.izumi; import java.io.*; import java.util.*; import java.util.regex.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.xerces.parsers.*; import org.apache.xerces.dom.*; import org.apache.xml.serialize.*; import org.xml.sax.*; import org.w3c.dom.*; import java.text.*; public class bean_list extends HttpServlet implements Serializable{ public void bean_list(){} //XML public Element xmlObjRoot(Document objDoc){ Element objRoot = objDoc.getDocumentElement(); return objRoot; } public NodeList xmlClnNod(Document objDoc){ NodeList clnNod = xmlObjRoot(objDoc).getChildNodes(); return clnNod; } public Node xmlObjNod(Document objDoc, int intItem0){ Node objNod = xmlClnNod(objDoc).item(intItem0); return objNod; } public NamedNodeMap xmlClnNnm1(Document objDoc, int intItem0){ NamedNodeMap clnNnm1=xmlObjNod(objDoc, intItem0).getAttributes(); return clnNnm1; } public Attr xmlAtr1(Document objDoc, int intItem0, int intAtrItem1){ Attr atr1 = (Attr)xmlClnNnm1(objDoc, intItem0).item(intAtrItem1); return atr1; } public NodeList xmlClnNod2(Document objDoc, int intItem0){ NodeList clnNod2 = xmlObjNod(objDoc, intItem0).getChildNodes(); return clnNod2; } public Node xmlObjNod2(Document objDoc, int intItem0, int intItem1){ Node objNod2 = xmlClnNod2(objDoc, intItem0).item(intItem1); return objNod2; } public Node xmlObjNod2L(Document objDoc, int intItem0){ Node objNod2L = xmlObjNod(objDoc, intItem0).getLastChild(); return objNod2L; } public NodeList xmlClnNod3(Document objDoc, int intItem0){ NodeList clnNod3 = xmlObjNod2L(objDoc, intItem0).getChildNodes(); return clnNod3; } public Node xmlObjNod3(Document objDoc, int intItem0, int intItem1){ Node objNod3 = xmlClnNod3(objDoc, intItem0).item(intItem1); return objNod3; } public NamedNodeMap xmlClnNnm3(Document objDoc, int intItem0, int intItem1){ NamedNodeMap clnNnm3=xmlObjNod3(objDoc, intItem0, intItem1).getAttributes(); return clnNnm3; } public Attr xmlAtr3(Document objDoc, int intItem0, int intItem1, int intAtrItem3){ Attr atr3 = (Attr)xmlClnNnm3(objDoc, intItem0, intItem1).item(intAtrItem3); return atr3; } //正しくは、、 public NodeList xmlClnNod20(Document objDoc, int intItem0){ NodeList clnNod2 = xmlObjNod(objDoc, intItem0).getChildNodes(); return clnNod2; } public Node xmlObjNod20(Document objDoc, int intItem0, int intItem1){ Node objNod2 = xmlClnNod20(objDoc, intItem0).item(intItem1); return objNod2; } public NamedNodeMap xmlClnNnm20(Document objDoc, int intItem0, int intItem1){ NamedNodeMap clnNnm2 = xmlObjNod20(objDoc, intItem0, intItem1).getAttributes(); return clnNnm2; } public Attr xmlAtr20(Document objDoc, int intItem0, int intItem1, int intAtrItem2){ Attr atr2 = (Attr)xmlClnNnm20(objDoc, intItem0, intItem1).item(intAtrItem2); return atr2; } public NodeList xmlClnNod30(Document objDoc, int intItem0, int intItem1){ NodeList clnNod3 = xmlObjNod20(objDoc, intItem0, intItem1).getChildNodes(); return clnNod3; } public Node xmlObjNod30(Document objDoc, int intItem0, int intItem1, int intItem2){ Node objNod3 = xmlClnNod30(objDoc, intItem0, intItem1).item(intItem2); return objNod3; } public NamedNodeMap xmlClnNnm30(Document objDoc, int intItem0, int intItem1, int intItem2){ NamedNodeMap clnNnm3 = xmlObjNod30(objDoc, intItem0, intItem1, intItem2).getAttributes(); return clnNnm3; } public Attr xmlAtr30(Document objDoc, int intItem0, int intItem1, int intItem2, int intAtrItem3){ Attr atr3 = (Attr)xmlClnNnm30(objDoc, intItem0, intItem1, intItem2).item(intAtrItem3); return atr3; } public NodeList xmlClnNod40(Document objDoc, int intItem0, int intItem1, int intItem2){ NodeList clnNod4 = xmlObjNod30(objDoc, intItem0, intItem1, intItem2).getChildNodes(); return clnNod4; } public Node xmlObjNod40(Document objDoc, int intItem0, int intItem1, int intItem2, int intItem3){ Node objNod4 = xmlClnNod40(objDoc, intItem0, intItem1, intItem2).item(intItem3); return objNod4; } public NamedNodeMap xmlClnNnm40(Document objDoc, int intItem0, int intItem1, int intItem2, int intItem3){ NamedNodeMap clnNnm4 = xmlObjNod40(objDoc, intItem0, intItem1, intItem2, intItem3).getAttributes(); return clnNnm4; } public Attr xmlAtr40(Document objDoc, int intItem0, int intItem1, int intItem2, int intItem3, int intAtrItem4){ Attr atr4 = (Attr)xmlClnNnm40(objDoc, intItem0, intItem1, intItem2, intItem3).item(intAtrItem4); return atr4; } public NodeList xmlClnNod50(Document objDoc, int intItem0, int intItem1, int intItem2, int intItem3){ NodeList clnNod5 = xmlObjNod40(objDoc, intItem0, intItem1, intItem2, intItem3).getChildNodes(); return clnNod5; } public Node xmlObjNod50(Document objDoc, int intItem0, int intItem1, int intItem2, int intItem3, int intItem4){ Node objNod5 = xmlClnNod50(objDoc, intItem0, intItem1, intItem2, intItem3).item(intItem4); return objNod5; } public NamedNodeMap xmlClnNnm50(Document objDoc, int intItem0, int intItem1, int intItem2, int intItem3, int intItem4){ NamedNodeMap clnNnm5 = xmlObjNod50(objDoc, intItem0, intItem1, intItem2, intItem3, intItem4).getAttributes(); return clnNnm5; } public Attr xmlAtr50(Document objDoc, int intItem0, int intItem1, int intItem2, int intItem3, int intItem4, int intAtrItem5){ Attr atr5 = (Attr)xmlClnNnm50(objDoc, intItem0, intItem1, intItem2, intItem3, intItem4).item(intAtrItem5); return atr5; } } ●で、JSPに、XMLファイルのROOTのDOCUMENTオブジェクトだけ作成させておいて、、BeanにRootおbじぇctと、順番に、幾つ目のElementの情報かを引数に渡せば、For文なんかで、必要な、TextNodeを取り出すとか、Attributeを取り出すとかだけの記述をすれば、簡潔に成ると思いますが、、 <%@page contentType="text/html;charset=Shift_JIS"%> <%@page import="java.io.*,org.apache.xerces.parsers.*,org.apache.xerces.dom.*,org.apache.xml.serialize.*,org.xml.sax.*,org.w3c.dom.*,java.util.*,java.util.regex.*"%> <jsp:useBean id="lbn" class="jp.co.sei.system.izumi.bean_list" scope="page" /> <% //XMLファイル取り扱い用 DOMParser prs = new DOMParser(); FileReader fr = new FileReader(application.getRealPath(xml_path)); BufferedReader br = new BufferedReader(fr); InputSource src = new InputSource(br); prs.parse(src); Document objDoc = prs.getDocument(); %> <% //DATA表示 int j_chk = 0; for(int j=0;tkn.hasMoreTokens(); j++){ if(j<lbn.xmlClnNod3(objDoc, iln).getLength()){ if(lbn.xmlAtr3(objDoc, iln, j, 1).getValue().equals("ON")){ %> ・・・・・・以下省略・・・・・
お礼
Beanで取り出す方法も使えるんですね、でも私はjavaも初心者なので、Beanといってもsetterとgetterを使ったものしかプログラムに取り入れたことがないんですよね。。 この方法だと、例えば「ルート要素の2番目の子ノードのそのまた子ノードの情報を全て取り出す」とか指定したりできるのでしょうか?? あと取り出し側の処理が難しそう... 方法がたくさんあるみたいなので、いろいろ試してみたいと思います。 教えていただいてありがとうございました。
お礼
わかりやすく回答していただいてありがとうございました。 Beanで取得方法を指定しておけば、jsp側の処理もらくちんなんですね。 最初はどのBeanを使うか迷って時間かかりそうだけど、このやり方に慣れて おいたほうが良いかも?と思いました。 どうもありがとうございました。