レベル: 初級 David Mertz, Ph.D (mertz@gnosis.cx), Author, Gnosis Software, Inc.
2002年 3月 01日 このヒントでDavidは、重いXML APIはいつ使用すべきでないか を述べています。SAX、DOM、およびXSLTなどの標準XML APIは、XML文書を変換して取り扱う精巧な方法を備えています。ただしそれらはすべて複雑であり、数百ページの仕様書と、さまざまな出版社の無数の解説書が必要になることは間違いありません。簡単なタスクの場合、XMLの作業を実行するもっと簡単な方法があります。Davidはいくつかの軽量XMLライブラリーへのリンクも記載しており、プログラマーがいつそれを使用すべきかに関する参考文献にもリンクされています。
XMLは「簡単であること」をその目標としています。それが約束するのは、さまざまなプラットフォームとプログラム言語の間で、簡単、直接的、かつ普遍的なデータ交換の手段を備えることです。不幸なことに、XMLを操作するために登場した最も一般的ないくつかのAPIは、お世辞にも簡単とはいえないものでした。それぞれには数百ページの仕様書があり、学習曲線はかなり険しいものです。実際、XMLそのものも、その当初の約束よりもいくらか複雑なものになっています。もっと簡単な方法があるはずです。そして実際に、いくつかのもっと簡単な方法があるのです。
このヒントで取り上げているほとんどの軽量APIは、内部的にはSAX (ライクな) ライブラリーの高水準ラッパーとして構築されています。高水準APIを使用するために、プログラマーは下層のパーサーについてほとんど知らなくても構いません。いくつかの点で、単純化されたAPIは、XMLプログラマーにとって扱いやすいものを提示します。
軽量XMLライブラリーには、一般的な2つのアプローチがあります。1つのアプローチは、XMLを行指向の形式にし、wc、tail、head、uniq、grep、sed、awkなどのおなじみのツールや、さらに高度な方法であるperlや他のスクリプト言語によって扱われてきた形式にすることです。もう1つのアプローチは、特定のプログラム言語の "ネイティブな" データ構造に従ってXML文書を表すことのできるライブラリーを使用することです。このようなライブラリーは多数のプログラム言語について存在しており、一般にはDOM、XSLT、またはSAXを起動するよりも簡単 (および特定の言語のプログラマーにとってはさらに直感的) です。
行指向のXML
PYX形式は、XML文書の行指向の表現です。PYXそのものはXMLではありませんが、XML文書内の情報を表現することができます。さらに、PYX文書そのものは、必要に応じてXMLに変換し直すことができます。PYXでは、各行の最初の文字によって行のコンテンツ・タイプが識別されます。接頭部文字は以下のとおりです。
PYX接頭部文字
( 開始タグ
) 終了タグ
A 属性
- 文字データ
? 処理手順
|
PYXの考え方の根底にあるのは、行指向のテキスト処理ツールおよび技法が、広く使用されており、簡易で、親しみやすいということです。このようなツールは一般に、改行で区切られたレコードを予期し、テキストの部分の識別は正規表現パターンに依存しています (PYXの場合は非ペアのマッチング、ただしXMLの場合はそうではない)。
いくつかのプログラム言語ではPYXライブラリーがありますが、たいていの場合は、単にコマンド行ツールxmln (non-validating (非妥当性検査)) およびxmlv (validating (妥当性検査)) を使用することが最も役立ちます。
PYX形式は、XMLとは対照的に、文書についてのさまざまな特定の質問を簡単に提示できます。たとえばこんな質問です。「 サンプル文書内に存在するすべての属性値を知りたい」PYXを使用していれば、簡単に以下のように尋ねることができます。
[PYX]# ./xmln test.xml | grep "^A" | awk '{print $2}'
|
あるいは、以下のようにしてXML文書の空でないコンテンツ行をダンプしてみることもできます。
[PYX]# ./xmln test.xml | grep '^-[^\n ]' | sed s/^-// |
SAXまたはDOMを使用してこれらを実行するカスタム・アプリケーションを作成することもできますが、このような照会は1行で表現するのがまさにうってつけ です。
ネイティブにする
DOMのAPIメソッドによって、XML文書を表す特定のデータ構造にアクセスできます。問題は、このデータ構造は、プログラム言語の組み込みデータ型とほとんど類似していないということです。多くのライブラリーは、"ネイティブ" バージョンのXML文書に移行しました。
Pythonのxml_objectify
私個人のPythonモジュールxml_objectifyをXML文書の読み取りに使用すると、その結果は非常に簡単なPythonオブジェクトとなり、このオブジェクト属性はルート文書エレメントのサブエレメントと属性とに対応するものになります。サブエレメントとタグ属性との唯一の違いは、それらにさらにオブジェクトが含まれているか、またはプレーン・テキストが含まれているかです。(Python) 属性に入っているもののタイプを調べることによって、サブエレメントまたはXML属性のどちらとして開始したかを十分判別できます。
まずDOMを使用してXML文書内のデータを見る以下の方法を覚えてください。
Python DOMによるXMLデータ構造へのアクセス
from xml.domimport minidom
dom = minidom.parse('test.xml')
print'flavor='+dom.childNodes[1].getAttribute('flavor')
print'PCDATA='+dom.childNodes[1].childNodes[5].childNodes[0].nodeValue
|
これとは対照的に、xml_objectifyを使用すると、XML文書データを、以下のようにはるかに直感的でPython的な方法で参照できます。
xml_objectifyによるXMLデータ構造へのアクセス
from xml_objectify import XML_Objectify
py_obj = XML_Objectify('test.xml').make_instance()
print 'flavor=' + py_obj.flavor
print 'PCDATA=' + py_obj.MoreSpam.PCDATA
|
RubyのREXML
REXMLライブラリーは、Rubyプログラム言語用のライブラリーで、複数のモードで操作されます。ストリーム・パーサーは、SAXと似た方法で動作しますが、よりRuby向けの構文を処理します。ツリー・モードは最も興味深いものです。基本的にこのモードは、xml_objectifyまたはPerlのXML::Parserの "Tree" スタイルで得られるデータ表現とかなり似ています。REXMLライブラリーの1つの利点は、そのXPathライクな領域指定子の構文が組み込まれていることです。たとえば、REXMLチュートリアルでは以下の行が示されています。
REXMLツリー・モードの構文解析およびデータ構造
require "rexml/document"
include REXML
doc = Document.new File.new("mydoc.xml")
doc.elements.each("inventory/section")
{ |element| puts element.attributes["name"] }
|
JavaのJDOM
Javaもこのネイティブの問題にかかわってきます。DOMそのものは主としてJavaを中心に設計されましたが、それでもDOMの、プログラム言語に中立なメソッドは不必要に複雑です (これはJavaにおいてもです)。JDOMは、XML処理のさらにJavaネイティブなバージョンです。これを強調するために、JDOMミッション・ステートメントを見てみましょう。
Java APIでのXMLの操作が、複雑、面倒、非直感的、または頭を痛めるものであるのはやむを得ない、という理由はありません。JDOMは、Javaセントリックであり、Java最適化済みでもあります。これはJavaのように振る舞い、Javaコレクションを使用し、現在のJava開発者にはまったく自然なAPIであり、XMLを使用するための低コストのエントリー・ポイントとなります。
PerlのTMTOWTDI
Perlプログラム言語の文化において、プログラマーによって掲げられているモットーがあります。それは「There's more than one way to do it (やり方は何とおりもある)」というものです。このスローガンはかなり知られており、たいていは単にTMTOWTDIと短縮されています。お分かりだと思いますが、Perl開発者はXMLを扱ういくつものさまざまな方法を見つけ出してきました。DOMやSAXなどの標準をサポートするPerlモジュールは実際に 存在するのですが、たいていのPerlプログラマーは、Perl的な基本道徳 - たるんでいて、うぬぼれていて、せっかちである - を体現しているモジュールを好みます。Perlプログラマーというのは、厳格で複雑な規格に従うよりも、自分たちのやり方のほうがさらに優れた、より速い、そしてより少ない作業量で仕事ができるのだと考えるようなタイプの人たちです。
他のプログラミング言語のスタイルに合わせて、ツリー・スタイルのXML::GroveおよびXML::Parserのどちらも、XML文書を構文解析して、非常にPerl的なネイティブ・データ構造にします。
HaskellのHaXml
HaXmlはHaskellそのものによく似ています。これは必ずしも簡易ではありませんが、目を見張るほどエレガントです。HaXmlは、関数プログラミング・スタイルをXMLの操作に持ち込む点でよい働きをしています。ここで論じた他のモジュールと同じく、HaXmlはXML文書をネイティブ・データ構造にかなり似た構造で表示します。
簡単な例によって、XSLTライクなHTMLへの変換方法を示します。
I Ching HTMLテーブルを出力するHaXmlプログラム
module Main whereimport XmlLibmain = processXmlWith module Main where
import XmlLib
main = processXmlWith (hexagrams `o` tag "IChing")
hexagrams =
html [
hhead [htitle [keep /> tag "title" /> txt] ],
hbody [htableBorder [rows `o` children `with` tag "hexagram"] ]
]
htableBorder = mkElemAttr "TABLE" [("BORDER",("1"!))]
rows f = hrow [hcol [num], hcol [nam], hcol [jdg]] f
where num = keep /> tag "number" /> txt
nam = keep /> tag "name" /> txt
jdg = keep /> tag "judgement" /> txt
|
結論
これらの軽量ライブラリーを試してみることをお勧めします。XMLを扱う大半の通常作業において、これらのライブラリーを使用すると作業速度は上がり、学習曲線はなだらかになります。ここで論じていない言語を使用している場合でも、言語ライブラリーが置かれているいつものロケーションを調べてみてください。そこには役立つ何かがあるかもしれません。
参考文献
著者について  | 
|  | David Mertz氏は多くの分野で活躍しています。ソフトウェア開発や、それについて著述もしています。その他、学術政策理念について分野を問わず、関係する雑誌に記事も書いています。かなり以前には、超限集合論、ロジック、モデル理論などを研究していました。その後、労働組合組織者として活動していました。そして、David Mertz氏自身は人生の半ばにもまだ達していないと思っているので、これから何かほかの仕事をするかもしれません。David Mertz氏の連絡先はmertz@gnosis.cxです。 |
記事の評価
|