一日以上の長
JavaはJ2SE6から(正確にはJava Web Services Developer Packから)XML用のAPIとしてStAXと呼ばれる新しいパーサ(プルパーサ)を提供したが、これはC#で既に実装されている同様のパーサと非常に良く似たものである。
以下はプルパーサを使ってhoge.xmlを読み込む簡易コードだが、とてもよく似ているのが解るだろう。
XmlReader reader = XmlReader.Createnew FileStream("hoge.xml", FileMode.Open, FileAccess.Read)); while (reader.Read()) { if (reader.IsStartElement()) { if (reader.LocalName.Equals("hoge")) { hogeエレメントに対する処理 } } } reader.Close();
XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader reader = factory.createXMLStreamReader(new FileStream("hoge.xml")); for (; reader.hasNext(); reader.next()) { if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) { if (reader.getLocalName().equals("hoge")) { hogeエレメントに対する処理 } } } reader.close();
リーダオブジェクトの属性を設定する場合も同様で、C#ではXmlReaderSettingsオブジェクトを使い、Javaの場合はfactoryの属性として設定する。
XmlReaderSettings settings = new XmlReaderSettings(); settings.ProhibitDtd = false; settings.ValidationType = ValidationType.DTD; settings.XmlResolver = new HogeResolver();
XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setProperty(XMLInputFactory.IS_VALIDATING, true); factory.setProperty(XMLInputFactory.SUPPORT_DTD, true); factory.setProperty(XMLInputFactory.RESOLVER, new HogeResolver());
と、このように使い方も酷似しているのでC#->
XmlReader reader = XmlReader.Createnew FileStream("hoge.xml", FileMode.Open, FileAccess.Read)); while (reader.Read()) { if (reader.IsStartElement()) { if (reader.LocalName.Equals("hoge")) { //hoge要素を基点としたツリーを処理するためのリーダを作れる XmlReader subReader = reader.ReadSubtree(); while (subReader.Read()) { hoge要素内を走査するのに特化した処理を書ける } } } }
通常、プルパーサは先頭の要素から順に取り出すことしかできないので、このように任意の要素内だけを走査するAPIがあると、ネストした要素の処理や再帰を書くのがとても楽になるのだ。
対してJavaは上記のようなカーソルAPIの他に、XML要素に対応して発生するイベントを補足しながら処理するためのAPI(XMLEventReader)も用意されているが、できればC#同様にサブツリーを処理するAPIが欲しかった。この辺は最初からプルパーサに拘ってきた.NETに一日の長があるように感じる。