プロが教えるわが家の防犯対策術!

XMLについてわからないことが多くて、困っています。
質問したいのですが、

JSPの画面でXMLのデータを表示させたいと思っています。
全部のデータを表示という場合、getDocumentElement()メソッドが
あると思うのですが、例えばテキストノードのみを表示させたい場合、
<タグ>などのノードから、全テキストノードを一気に拾い出す方法は
あるのでしょうか?メソッドとか。

ただ表示させるだけではなくて、データの削除とか変更などのデータ加工
もしていきたいので、最適なデータの表示がしたいんです。なので、操作
をしやすい取り出し方というか。。。

漠然とした質問で申し訳ありませんが、詳しい方がいましたら教えてもらえ
ないでしょうか?お願いします。

A 回答 (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()分くるくる回せば、取得できますよ。
    • good
    • 0
この回答へのお礼

わかりやすく回答していただいてありがとうございました。
Beanで取得方法を指定しておけば、jsp側の処理もらくちんなんですね。
最初はどのBeanを使うか迷って時間かかりそうだけど、このやり方に慣れて
おいたほうが良いかも?と思いました。
どうもありがとうございました。

お礼日時:2002/12/10 01:07

> >この処理をして、結果を貯めておくようなクラスを作って、


> >それを JSP から呼び出すような感じになるかな。
>
> というのは、別のクラスでノードを拾い出すメソッドを作って、それをjspで
> 必要な時に活用するということですか?それとも拾い出したノードを格納するクラス(Beanのような)を作るといいということでしょうか??

どっちでも良いと思いますよ。自分がどういう使い方をするかで決まってくると思います。

ただ、XML を扱う処理は、それなりにコードを書かなければいけないので、その処理を請け負ってくれる
クラスを作っておく方が、何かと便利か、と。

そのクラスは、Servlet に関係なく(HttpSession などを使わない)ように作っておくと
コマンドプロンプトレベルで動作確認ができるので、デバッグをする際には有効です。

そういった XML を処理するロジックを持ったクラスが解析したノードを保持するのでも良いですし、
解析したノードを保持するクラスが別にあっても良いですし。

# 私なら、別にしておきます
    • good
    • 0
この回答へのお礼

やっぱりある程度決まった処理なら、別クラスを作って必要な時に
呼び出すのが一番ということですね。
XMLは結構奥が深くて、勉強してもあまり前に進めません。。
別クラスを作ってちゃんと活用できるようになりたいと思います。
参考になりました。ありがとうございました。

お礼日時:2002/12/10 01:13

確かに、漠然としてますね。

テキストノードを一気に拾い出すことと、データの削除や加工をするということは、
それぞれのノードを区別するということですから、相反していますよね。

まずは、落ち着いて、使用を考え直してみた方が良いのでは?

で、テキストノードをがさっと取り出す方法は、ぱっと二つほど思いつきます。

まず 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)を読めば、一日で作れるようになりますよ。

# どちらのコードも、リファレンスを見ながら、ざっざっと書いただけなので、
# 動作の保証はありません (^^;

参考URL:http://java.sun.com/xml/jaxp/dist/1.1/docs/tutor …

この回答への補足

確かに、ノードを一気に拾い出すことと、データを加工していくことはノードの処理も違ってきますよねー。自分でも混乱していて、質問内容もめちゃくちゃだったかも。
それなのに教えてくれてありがとうございました。

テキストノードの拾い方、とてもわかりやすかったです。これだと簡単にできるし、他のノードなどでも、すぐできますね。

ひとつ教えてもらえるとありがたいのですが

>この処理をして、結果を貯めておくようなクラスを作って、
>それを JSP から呼び出すような感じになるかな。

というのは、別のクラスでノードを拾い出すメソッドを作って、それをjspで
必要な時に活用するということですか?それとも拾い出したノードを格納するクラス(Beanのような)を作るといいということでしょうか??

よろしければ教えてください、お願いします。

補足日時:2002/12/07 23:50
    • good
    • 0

例えば、こんな、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")){
%>

・・・・・・以下省略・・・・・
    • good
    • 0
この回答へのお礼

Beanで取り出す方法も使えるんですね、でも私はjavaも初心者なので、Beanといってもsetterとgetterを使ったものしかプログラムに取り入れたことがないんですよね。。

この方法だと、例えば「ルート要素の2番目の子ノードのそのまた子ノードの情報を全て取り出す」とか指定したりできるのでしょうか??
あと取り出し側の処理が難しそう...
方法がたくさんあるみたいなので、いろいろ試してみたいと思います。
教えていただいてありがとうございました。

お礼日時:2002/12/07 23:49

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