XMLで書いたテンプレートにデータを挿入してPDFの帳票を出力するプログラムを3年前に書いたんですが、利用しているPDFライブラリのiTextがバージョンアップしたのに合わせていろいろ書きなおしているところです。で、自分で書いたはずのプログラムでちょっとハマったのでメモ。
次のようなデータがdata.xmlファイルに保存されているとします。
次のようなデータがdata.xmlファイルに保存されているとします。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dataList>
<data type="string">aaa</data>
<data type="string">bbb</data>
<data type="string">ccc</data>
<data type="int">111</data>
<data type="int">222</data>
<data type="int">333</data>
</dataList>
これを次のようなプログラムで読み出します。<dataList>
<data type="string">aaa</data>
<data type="string">bbb</data>
<data type="string">ccc</data>
<data type="int">111</data>
<data type="int">222</data>
<data type="int">333</data>
</dataList>
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
public class XmlTest{
public static void main(String[] args){
try{
File file = new File("data.xml");
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.parse(file);
Element element = document.getDocumentElement();
NodeList dataList = element.getElementsByTagName("data"); //★1
for(int i=0;i<dataList.getLength();i++){
Node data = dataList.item(i); //★2
NamedNodeMap attributes = data.getAttributes();
Node nodeItem = attributes.getNamedItem("type");
String type = nodeItem.getTextContent();//★3
String dataContent = data.getTextContent();
System.out.println(type + ":" + dataContent);
}
}catch(javax.xml.parsers.ParserConfigurationException e){
e.printStackTrace();
}catch(org.xml.sax.SAXException e){
e.printStackTrace();
}catch(java.io.IOException e){
e.printStackTrace();
}
}
}
★1の行でgetElementsByTagNameを実行しているのですが、このメソッドが返すのはNodeListという型で、item(i)でi番目のNodeオブジェクトが取得できるんですが、このオブジェクトから属性(上のデータの例では"type")を取り出すには一度、NamedNodeMap を取得して、そこから更にNodeオブジェクトを取得して、やっと属性の値が取り出せる、という感じです。getElementsByTagNameメソッドが素直にElementオブジェクトを返してくれればgetAttributeメソッドで属性の値が取り出せるんですけどねぇ・・・と思っていろいろ調べたらitem(i)の戻り値をElementにキャストしている例がいくつかのページで説明されていました。上のコードの★2〜★3を次のように書くことができます。import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
public class XmlTest{
public static void main(String[] args){
try{
File file = new File("data.xml");
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.parse(file);
Element element = document.getDocumentElement();
NodeList dataList = element.getElementsByTagName("data"); //★1
for(int i=0;i<dataList.getLength();i++){
Node data = dataList.item(i); //★2
NamedNodeMap attributes = data.getAttributes();
Node nodeItem = attributes.getNamedItem("type");
String type = nodeItem.getTextContent();//★3
String dataContent = data.getTextContent();
System.out.println(type + ":" + dataContent);
}
}catch(javax.xml.parsers.ParserConfigurationException e){
e.printStackTrace();
}catch(org.xml.sax.SAXException e){
e.printStackTrace();
}catch(java.io.IOException e){
e.printStackTrace();
}
}
}
Element data = (Element)dataList.item(i);
String type = data.getAttribute("type");
4行が2行になったところで「どれだけうれしいのか?」という話ではあるのですが、どうも腑に落ちないのはJava5で導入されたジェネリクスや拡張for文がいまだにサポートされていないことなんですよね。XMLも旬が過ぎてしまったということなんでしょうか。String type = data.getAttribute("type");
投稿:竹形 誠司[takegata]/2011年 04月 15日 11時 06分
/更新:2011年 04月 15日 11時 28分