XML初心者です。JavaでXMLを読み込もうとしていますが、途中で階層を下に降りられず目的の処理ができません。
デバッグを付けたままで失礼しますけれども、try1.61の次に進まず、NullPointerExceptionが出ます。
dcNodeがnullであることが考えられます。その原因ですがdeNodeの一つ上の<sの<srw_dc:dc ...>にあるかと推測しています。属性をたくさんつけていて、テキストノードとして扱われるらしい複数の空白も持っていて、この辺にgetFirstChild()で素直に一つ下の階層に移らないのではない理由がありそうなのですが、調べきれません。
どうかお詳しい方がいらしたら、この辺をご解説いただきたく存じます。
Java
1if (recordxxNode.getNodeName().equals("recordData")) { 2 System.out.println("try1.5"); 3 Node srwdcdcNode = recordxxNode.getFirstChild(); 4 System.out.println("srwdcdcNode.getTextContent()="+srwdcdcNode.getTextContent()); 5 System.out.println("try1.6"); 6 Node dcNode = srwdcdcNode.getFirstChild(); 7 System.out.println("try1.61"); 8 System.out.println("dcNode.getTextContent()"+dcNode.getNodeType()); 9 if(checkedElementNode(dcNode)) { 10 System.out.println("try1.7"); 11 while(dcNode != null) { 12 System.out.println("try1.8"); 13 if(dcNode.getNodeName().equals("dc:title")){ 14 data[0] = dcNode.getTextContent(); 15 } 16 if(dcNode.getNodeName().equals("dc:creator")){ 17 data[1] = dcNode.getTextContent(); 18 } 19 if(dcNode.getNodeName().equals("dc:publisher")){ 20 data[2] = dcNode.getTextContent(); 21 } 22 dcNode = dcNode.getNextSibling(); 23 24 } 25 26 } 27 else { 28 System.out.println("try3"); 29 30 } 31 } 32
XML
1<srw_dc:dc xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:srw_dc="info:srw/schema/1/dc-v1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="info:srw/schema/1/dc-v1.1 http://www.loc.gov/standards/sru/dc-schema.xsd"> 2 <dc:title>できるWindows 10</dc:title> 3 <dc:creator>法林岳之, 一ケ谷兼乃, 清水理史, できるシリーズ編集部 著</dc:creator> 4 <dc:description>Home/Pro/Enterprise対応</dc:description> 5 <dc:description>索引あり</dc:description> 6 <dc:publisher>インプレス</dc:publisher> 7 <dc:language>jpn</dc:language> 8</srw_dc:dc>
> NullPointerExceptionが出ます。
まずそのメッセージをご提示頂いて、発生行はどこなのか教えて下さい。
>dcNodeがnullであることが考えられます。
表示してみれば確認出来ることと思いますが、なぜ推測になっているのでしょうか。
また、お使いのパーサは何でしょう。
NullPointerExceptionの発生行:
System.out.println("dcNode.getTextContent()"+dcNode.getNodeType());
このデバッグ行です。getNodeType()メソッドを働かせようとしてこの例外が発生したことから、dcNodeがnullであると推測しました。
直接値をとらなかったのは、まだXMLのノードの扱いに慣れずどうも普通とは勝手の違うところもあったので、それができない気がしていたためです。
パーサは
javax.xml.parsers.DocumentBuilder;
javax.xml.parsers.DocumentBuilderFactory;
これでいいでしょうか。
> どうも普通とは勝手の違うところもあったので
java のコードに入っている時点で"普通"のオブジェクトとして扱って大丈夫です d^^
> パーサは ~
javax の DOM ですね。ありがとうございます。
> <srw_dc:dc ...>にあるかと推測しています。属性をたくさんつけていて、テキストノードとして扱われるらしい複数の空白も持っていて
srw_dc:dc タグに付いている xmlns:xxx というのは名前空間の宣言で、通常(?)の属性ではありません。
(ご提示の teratail の表示で見ても xmlns の部分に色が付いていると思います。)
名前空間というのは java でいうパッケージのようなものです。xmlns:dc="URL" とすると「この後 dc:yyy のように書くと "dc という名前空間(実際の名前は URL の方で dc はその略名?ですが)の yyy というタグ" を意味しますよ」と宣言していることになります。
Node.getTextContent() で返される文字列は、そのノードに含まれるタグ以外の全文字列です。これは xml をテキストファイルとして見た時の該当タグの開始・終了間に含まれる空白・改行文字も含みます。
ご提示の例では、<srw_dc:dc> から </srw_dc:dc> の間には、"人が見易くする為に" 改行やインデントの空白がありますが、パーサからすればそんな人の都合は関係無いので、 getTextContent はそれらをテキストとして返しています。
察するところ、srw_dc:dc に含まれるタグは全て srw_dc 名前空間では無いので、 getFirstChild() が null を返しているのではないでしょうか。
DocumentBuilderFactory に対し名前空間を有効にする setNamespaceAware(true) 等されていませんか? (昔はデフォルト false でしたが、最近は true なのかもしれませんが。)
setNamespaceAware(false) としたら如何でしょうか。
setNamespaceAwareをtrueにはしていません。また調べたところデフォルト値はfalseですので何もしないままでいいと思います。
また空白を1つ1つ読んでいってnuiiじゃないときに子ノードに出る方法はないかとか思うのですが、初心者でメソッドを知らないものですから、実現できません。
[getElementsByTagNameの正しい使いかた](https://teratail.com/questions/363771 ) のほうの xml を見まして、少し状況が見えた気がします。
cx20 さんがご提示された xml によれば、 recordData の中身は「xml ではありません」。
ですので、ご提示のコードでは srwdcdcNode はテキストノードであり、テキストノードは子ノードは持っていない・・・ということではないでしょうか。
srwdcdcNode.getNodeType() が何になっているか確認してみてください。
srwdcdcNode.getNodeType()=3です。テキストノードですね。するとNcNodeにどうやってアクセスしたらいいでしょう。
363771 で cx20 さんが回答として指摘された
> 一旦、recordData の中を取り出した後、再度、XML を parse する必要がありそう
が必要です。これを踏まえた上で XPath という DOM の中身を検索する API を使用して動作を確認したコードを 363771 のほうに回答として書かせて頂きましたので、参照して頂けますでしょうか。
返事が遅くなって申し訳ありません。XPathのような高度な知識は私には未知のもので、基礎を勉強してから取り入れさせていただきます。ありがとうございました。
> XPathのような高度な知識は~
高度と身構えるよりは、便利にしてくれるモノと気楽に使ってみては如何でしょう。
DOM はそのままでは(ご苦労されたように)データを集める為に階層内を移動するのが面倒です。
そこで、ファイルを指定するのにフォルダを "/" 等で区切って一気に指定する”パス”と同じ書き方でデータを集めようというのが XPath です。
"<A><B><C>data</C></B></A>" という xml で data を得ようとして、 DOM そのままでは A から B を取り出し、B から C を取り出し、 C から data を取り出す…とコードを書いて処理するところを、XPath を使うと "A/B/C/text()" と指定して即 data を取り出せるという感じです。
回答1件
あなたの回答
tips
プレビュー