こんにちは。「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」にしました。