質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

1783閲覧

繁雑な属性を持つXML要素を起点としてgetFirstChild()の読むもの

onoko

総合スコア41

XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2021/10/10 05:28

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>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2021/10/10 19:26

> NullPointerExceptionが出ます。 まずそのメッセージをご提示頂いて、発生行はどこなのか教えて下さい。 >dcNodeがnullであることが考えられます。 表示してみれば確認出来ることと思いますが、なぜ推測になっているのでしょうか。 また、お使いのパーサは何でしょう。
onoko

2021/10/11 01:27

NullPointerExceptionの発生行:  System.out.println("dcNode.getTextContent()"+dcNode.getNodeType()); このデバッグ行です。getNodeType()メソッドを働かせようとしてこの例外が発生したことから、dcNodeがnullであると推測しました。  直接値をとらなかったのは、まだXMLのノードの扱いに慣れずどうも普通とは勝手の違うところもあったので、それができない気がしていたためです。  パーサは javax.xml.parsers.DocumentBuilder; javax.xml.parsers.DocumentBuilderFactory; これでいいでしょうか。
jimbe

2021/10/11 03:42 編集

> どうも普通とは勝手の違うところもあったので 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 はそれらをテキストとして返しています。
jimbe

2021/10/11 03:46

察するところ、srw_dc:dc に含まれるタグは全て srw_dc 名前空間では無いので、 getFirstChild() が null を返しているのではないでしょうか。 DocumentBuilderFactory に対し名前空間を有効にする setNamespaceAware(true) 等されていませんか? (昔はデフォルト false でしたが、最近は true なのかもしれませんが。) setNamespaceAware(false) としたら如何でしょうか。
onoko

2021/10/11 06:38

setNamespaceAwareをtrueにはしていません。また調べたところデフォルト値はfalseですので何もしないままでいいと思います。 また空白を1つ1つ読んでいってnuiiじゃないときに子ノードに出る方法はないかとか思うのですが、初心者でメソッドを知らないものですから、実現できません。
jimbe

2021/10/11 12:14 編集

[getElementsByTagNameの正しい使いかた](https://teratail.com/questions/363771 ) のほうの xml を見まして、少し状況が見えた気がします。 cx20 さんがご提示された xml によれば、 recordData の中身は「xml ではありません」。 ですので、ご提示のコードでは srwdcdcNode はテキストノードであり、テキストノードは子ノードは持っていない・・・ということではないでしょうか。 srwdcdcNode.getNodeType() が何になっているか確認してみてください。
onoko

2021/10/12 07:35 編集

srwdcdcNode.getNodeType()=3です。テキストノードですね。するとNcNodeにどうやってアクセスしたらいいでしょう。
jimbe

2021/10/12 08:43 編集

363771 で cx20 さんが回答として指摘された > 一旦、recordData の中を取り出した後、再度、XML を parse する必要がありそう が必要です。これを踏まえた上で XPath という DOM の中身を検索する API を使用して動作を確認したコードを 363771 のほうに回答として書かせて頂きましたので、参照して頂けますでしょうか。
onoko

2021/10/22 03:01

返事が遅くなって申し訳ありません。XPathのような高度な知識は私には未知のもので、基礎を勉強してから取り入れさせていただきます。ありがとうございました。
jimbe

2021/10/22 04:01 編集

> 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 を取り出せるという感じです。
guest

回答1

0

ベストアンサー

以下のコードで試したみたのですが、null になりませんでした。
factory.setNamespaceAware(true) で child=null になるかと思ったのですが、ハズレだったようです。
ご提示以外の何か設定があるのでしょうか。

java

1package teratail_java.q363713; 2 3import java.io.File; 4import java.io.IOException; 5 6import javax.xml.parsers.*; 7 8import org.w3c.dom.Document; 9import org.w3c.dom.Node; 10import org.xml.sax.SAXException; 11 12public class Q363713 { 13 public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { 14 DocumentBuilderFactory factory = DocumentBuilderFactory.newDefaultInstance(); 15 factory.setNamespaceAware(true); 16 17 DocumentBuilder builder = factory.newDocumentBuilder(); 18 System.out.println("builder.isNamespaceAware="+builder.isNamespaceAware()); 19 20 Document document = builder.parse(new File("Q363713.xml")); 21 Node parent = document.getFirstChild(); 22 System.out.println("parent="+parent); 23 for(Node child=parent.getFirstChild(); child!=null; child=child.getNextSibling()) { 24 if(child.getNodeType() != Node.TEXT_NODE) System.out.println("child="+child); 25 } 26 } 27}

Q363713.xml (ご提示頂いている xml をコピペ)

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>

実行結果

plain

1builder.isNamespaceAware=true 2parent=[srw_dc:dc: null] 3child=[dc:title: null] 4child=[dc:creator: null] 5child=[dc:description: null] 6child=[dc:description: null] 7child=[dc:publisher: null] 8child=[dc:language: null]

投稿2021/10/11 05:00

jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問