java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

org.w3c.domパッケージでアトリビュートがあるXMLを読み込む

投稿日:

最終更新日:2016年09月06日

アイキャッチ

こんにちは。「Javaを復習する初心者」です。

今回はXMLのある要素にアトリビュートが定義されている場合を扱いました。

アトリビュートは<要素名 アトリビュート名=値>の形式で記述されます。

XMLファイル

読み込むXMLは以下です。

HelloDOMattr.xml

<?xml version="1.0"?>
<students>
  <student>
    <name class="family">family name 1</name>
    <name class="first">first name 1</name>
    <age>16</age>
  </student>
  <student>
    <name class="family">family name 2</name>
    <name class="first">first name2</name>
    <age>17</age>
  </student>
</students>

前回との違いはstudent要素の直下にname要素が2つあることです。それぞれclassというアトリビュートが定義されています。値はfamilyとfirstです。

XMLファイルを読み込みstudent要素ごとに以下の形式で出力することにしました。

出力対象の要素 書式文字列 埋め字
name要素

%s(%s): %s

“name”, [アトリビュートclassの値], [要素の内容]

age

%s: %s

“age”, [要素の内容]

プログラム

以下はソースと実行結果です。

ソース

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class HelloDOMattr {

    public static void main(String[] args) {

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = null;
        try {
            builder = factory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
        Document document = null;
        try {
            document = builder.parse("resource/HelloDOMattr.xml");
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Element root = document.getDocumentElement();
        NodeList list1 = root.getChildNodes();
        for (int i = 0; i < list1.getLength(); i++) {
            if (list1.item(i).getNodeName().equals("student")) {
                NodeList list2 = list1.item(i).getChildNodes();
                for (int j = 0; j < list2.getLength(); j++) {
                    Node node = list2.item(j);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        Element element = (Element) node;
                        String attr = element.getAttribute("class");
                        switch (element.getNodeName()) {
                        case "name":
                            System.out.printf("%s(%s): %s", "name", attr, element.getTextContent().substring(attr.length() + 1));
                            break;

                        case "age":
                            System.out.printf("%s: %s", "age", element.getTextContent());
                            break;
                        }
                        System.out.println();
                    }
                }
                System.out.println();
            }
        }

    }

}

結果

name(family): name 1
name(first): name 1
age: 16

name(family): name 2
name(first): name2
age: 17

前回はNode#getTextContent()を使って、要素の内容を取得していました。今回はアトリビュートの値を取得する必要があったため、Nodeクラスのままだと都合が悪いです。このクラスにはアトリビュートの値を取得するメソッドがありません。似たような名前のgetAttributes()というメソッドがありますが、使い方が分かりませんでした。そのため、NodeクラスのインスタンスをElementクラスにキャストしています。ただし、いつでもキャストできるわけではないようです。getNodeType()がNode.ELEMENT_NODEに等しい時にキャストしています。

Element#getAttribute()メソッドでアトリビュートの値が取得できます。引数にはアトリビュート名を指定します。今回は”class”を引数に指定しました。

Element#getTextContent()で要素の内容を取得できるのですが、アトリビュートが定義されている要素の場合、その値を含む形が戻り値になるようです。実際に出力してみると「family name 1」という値が出力されました。「[アトリビュートの値] [要素の内容]」という形で出力されるようです。そのため、substring()メソッドを使って、要素の内容の部分だけを取り出しています。半角空白がある分を考慮するため、substring()の引数は「attr.length() + 1」にしました。