これまで、このカラムではXMLの代替物、つまりXMLの目的の多くを同じように満たす文書フォーマットを調べてきました。reStructuredText はその続きです。データ・フォーマットに適したYAMLとは対照的に、reStructuredTextは文書化用に設計されています。スマートASCIIとは対照的に、reStructuredTextはより重厚で、強力で、形式的に指定されています。これらのすべてのフォーマットは、XMLとは対照的に、標準的なテキスト・エディターで容易かつ自然に読み取って編集できます。XMLの処理には、多かれ少なかれ、これまで検討したような特殊なXMLエディターが必要です (参考文献を参照)。
reStructuredText (しばしばreSTと略される) はPython Docutilsプロジェクトの一部です。このプロジェクトの目標は、プレーン・テキスト文書の操作 (HTML、XML、およびTeXなどの構造化フォーマットにエクスポートすることを含む) を行うためのツールを作成することです。このプロジェクトはPythonコミュニティーから発していますが、その要件はPythonの範囲を超えています。どのタイプのプログラマーやライターも、README、HOWTO、FAQ、アプリケーション・マニュアル、およびPythonの場合はPEP (Python Enhancement Proposals) といった文書をしばしば作成します。これらのタイプの文書では、XMLやLaTeXなどの冗長で難解なフォーマットの処理をユーザーに要求することは、ユーザーがプログラマーであったとしても、一般に妥当ではありません。それでも、単純な表示以上 (索引付け、コンパイル、見栄えの良い印刷、フィルター操作など) のことを行いたいため、これらのタイプの文書を使用することが望ましいこともしばしばあります。
Docutilsツールは、JavaDocがJavaプログラマーを助けたりPODがPerlプログラマーを助けたりするのとほとんど同じように、Pythonプログラマーが必要とすることを行います。Pythonモジュール内の資料をDocutils文書ツリーに変換し、次いでさまざまな出力フォーマットに変換できます (通常は単一のスクリプトで)。しかしこの記事の場合、より興味深い用途は一般的な文書化です。私は、本記事や私の次の本を、スマートASCIIを使って作成しています。しかし、reStructuredTextの形式性を利用したほうがよいように感じ始めています (そして、既存の文書を変換するツールを開発するかもしれません)。
この記事の執筆の時点で、Docutilsプロジェクトは開発中であり、安定したバージョンがリリースされていません。既存のツールも優れていますが、プロジェクト全体は、期待、善意、部分的な資料、いくつかの実際の作業ツールの混合物となっています。ただし、進行は着実であり、今の時点で行えることでも非常に役立ちます。
reStructuredTextがどのようなものであるかは、簡潔な例を見ればより良く理解できます。以下のテキストはPEP 287 (まだ正式にはなっていないPEPの1つです) の例です。
リスト1. プレーン・テキスト・バージョンのPEP
Abstract
This PEP proposes adding frungible doodads [1] to the
core. It extends PEP 9876 [2] via the BCA [3] mechanism.
...
References and Footnotes
[1] http://www.example.org/
[2] PEP 9876, Let's Hope We Never Get Here
http://www.python.org/peps/pep-9876.html
[3] "Bogus Complexity Addition"
|
リスト1 のフォーマットは、PEPが287の前に持っていたフォーマットそのものです。reStructuredTextを使って同じPEPをマークアップすると、以下のようになります。
リスト2. reSTバージョンのPEP
Abstract
========
This PEP proposes adding `frungible doodads`_ to the core.
It *extends* PEP 9876 [#pep9876]_ via the BCA [#]_ mechanism.
...
References & Footnotes
======================
.. _frungible doodads: http://www.example.org/
.. [#pep9876] PEP 9876, Let's Hope We Never Get Here
.. [#] "Bogus Complexity Addition"
|
いくらかの詳細がプレーン・テキストと異なっています。特殊文字がほんの少し用いられていますが、実際の読み易さは害を受けていません。テキスト・エディターや印刷ページで見るときに、2回見る必要はないでしょう。
リスト2 のreSTフォーマットの文書は、Docutils Generic DTDによって定義されているようなXML方言に自動的に変換できます。
リスト3. Docutils XMLバージョンのPEP
<?xml version="1.0" encoding="UTF-8"?>
<document source="test">
<section id="abstract" name="abstract">
<title>Abstract</title>
<paragraph>This PEP proposes adding <reference
refname="frungible doodads">Frungible doodads</reference>
to the core. It<emphasis>extends</emphasis><reference
refuri="http://www.python.org/peps/pep-9876.html">
PEP 9876</reference><footnote_reference auto="1" id="id1"
refname="pep9876"/> via the BCA <footnote_reference
auto="1" id="id2"/> mechanism.</paragraph>
<paragraph>...</paragraph>
</section>
<section id="references-footnotes"
name="references & footnotes">
<title>References & Footnotes</title>
<target id="frungible-doodads" name="frungible doodads"
refuri="http://www.example.org/"/>
<footnote auto="1" id="pep9876" name="pep9876">
<paragraph><reference
refuri="http://www.python.org/peps/pep-9876.html">PEP
9876</reference>, Let's Hope We Never Get Here
</paragraph>
</footnote>
<footnote auto="1" id="id3">
<paragraph>"Bogus Complexity Addition"
</paragraph>
</footnote>
</section>
</document>
|
これらの3つのフォーマットを対比すると、いくつかのことが分かります。最も劇的な違いは、XMLバージョンの読みにくさです。同時に、reStructuredTextツールがreST文書から読み取った情報の多さが注目に値します。複数のタイプの参照が適切に突き合わされ、文書セクションが識別され、文字レベルの活版印刷マークアップが追加されています。他の例では、リンクされたTOCが他の特殊ディレクティブとともに生成されます。
docutils
パッケージは、かなり複雑に関係し合ったいくつかのサブパッケージで構成されています。PEP 258 (Docutils Design Specification) には、全体のパターンを理解するのに役立つ図表が含まれています。
図1. Docutilsプロジェクト・モデル
このPEPにはコンポーネント・サブパッケージのより完全な説明が含まれていますが、ここでは簡潔な説明を繰り返すだけで十分です。
reSTテキストをノードのツリーに変換する大変な作業は、
docutils.parsers.rst
サブパッケージによって行われます。reStructuredTextパーサーはソースを行単位で扱い、各行で状態遷移を探します。他の遷移パターンが見付からなければ、text 遷移がその行を獲得します。遷移は、インデントの変化や特殊な先頭シンボルなどの特性で構成されます。デフォルトでは、現行ノードのテキストとして次の行だけが含まれます。
この構造は、スマートASCIIパーサーのtxt2dw およびtxt2html で使用されているものと似ています。他のパーサーは
docutils.parsers
階層の下に存在することになりますが、現在提供されているものはありません。ただし、Pythonソース・ファイルを文書ツリーとして扱う実験的なPythonソース・コード・パーサーが存在します。
docutils.transforms
サブパッケージが文書用のノードのツリーを生成すると、そのツリーをさまざまな仕方で操作できます。たとえば、目次を組み込むディレクティブを指定すると、リストされている項目を識別するように文書ツリーが走査されます。また、変換により、この段階で参照とリンクのクリーンアップがいくらか実行されます。最初のパスでは、未解決のエレメントが置かれるツリー内の位置には、後で変換の必要性があることをマークするプレースホルダーが埋められます。
さまざまな
docutils.writers
モジュールは、この記事のほとんどの読者にとっておそらく主な関心事でしょう。この記事の執筆時点で、より興味深いライターの一部は依然として実験的な "サンドボックス" 領域に保持されています (参考文献のDocutils Webサイトを参照) が、いずれの場合も原則は同じです。ライター・モジュールは、docutils.writers.Writer から継承するWriter クラスを定義する必要があります。このWriter クラスはいくつかの設定を定義しますが、たいていの場合は次のような.translate() メソッドを定義します。
リスト4. 典型的なカスタムWriter.translate() メソッド
def translate(self):
visitor = DocBookTranslator(self.document)
self.document.walkabout(visitor)
self.output = visitor.astext()
|
見て分かるように、ライターは、各タイプのノードをどのように扱うかを知っているビジター (visitor) に依存します。ビジターは一般に、docutils.nodes.NodeVisitor から継承します。ビジターのプログラミングは、SAX、expat、REXML、または他のイベント指向のXMLパーサーのプログラミングとよく似ています。ただし、ビジターは、Pythonのxmllib モジュールのプログラミング・スタイルにさらに似ています。つまり、ビジターは、大きな.startElement() およびendElement() メソッドの内部でタイプによって処理を切り替える代わりに、各タイプのノードごとに.visit_FOO() および.depart_FOO() メソッドを持ちます。OOPの純血主義者にはこのスタイルは好まれるでしょう。Docbook/XMLライターの単純な例は以下のとおりです。
class DocBookTranslator(nodes.NodeVisitor):
[...lots of methods...]
def visit_block_quote(self, node):
self.body.append(self.starttag(node, 'blockquote'))
def depart_block_quote(self, node):
self.body.append('</blockquote>
\n')
[...lots more methods...]
|
カスタムのライター / ビジターのプログラミングはそれほど難しくなく、Docutils/XML、HTML、PEP-HTML、PseudoXML (開始タグとインデントを組み合わせ、終了タグを持たない、軽量XMLの一種)、LaTeX、DocBook/XML、PDF、OpenOffice/XML、およびWiki-HTML用のライターが存在しています。
reStructuredText文書は、DOMのような仕方で操作できるノードのツリーに変換できます。以下は、リスト2 で示したreST PEPの例を使用する例です。
リスト5. reSTノード・ツリーの作成
>>> txt = open('pep.txt').read()
>>> def rst2tree(txt):
... import docutils.parsers.rst
... parser = docutils.parsers.rst.Parser()
... document = docutils.utils.new_document("test")
... document.settings.tab_width = 4
... document.settings.pep_references = 1
... document.settings.rfc_references = 1
... parser.parse(txt, document)
... return document
...
>>> doc = rst2tree(txt)
>>> doc.children
[<section "abstract": <title...><paragraph...><paragraph...>,
<section "references & footnotes": <title...>
<target "frungible doodads"...><footnote "pep9 ...>]
>>> print doc.autofootnotes
[<footnote "pep9876": <paragraph...>, <footnote: <paragraph...>]
>>> print doc.autofootnotes[0].rawsource
PEP 9876, Let's Hope We Never Get Here
|
DOMと対比して注目できる点は、reStructuredTextはすでに固定された文書方言であるということです。したがって、汎用のメソッドを使用して一致するノードを検索する代わりに、意味に応じた名前を持つ属性を使用してノードを検索できます。.children 属性は一般に階層型ですが、ほとんどの属性は特定のタイプのノードを収集します。
reSTノードの便利なメソッドの1つは.pformat() で、見栄えの良い印刷のためにリスト6 のような文書ツリーの疑似XML表現を生成します。
リスト6. reSTノードの疑似XML表現
>>> print doc.autofootnotes[0].pformat(' ')
<footnote auto="1" id="pep9876" name="pep9876">
<paragraph>
<reference refuri="http://www.python.org/peps/pep-9876.html">
PEP 9876,
Let's Hope We Never Get Here
|
.remove()、.copy()、.append()、および.insert() などのノード・メソッドは、ツリーの枝取りや操作を行うのに役立ちます。
XMLプログラマーにとって、より望ましいAPIはDOMそのものかもしれません。幸い、このDOM APIを使うには単一のメソッド呼び出しするだけです。
リスト7. reSTツリーからDOMツリーへの変換
>>> dom = doc.asdom()
>>> foot0 = dom.getElementsByTagName('footnote')[0]
>>> print foot0.toprettyxml(' ')
<footnote auto="1" id="pep9876" name="pep9876">
<paragraph>
<reference refuri="http://www.python.org/peps/pep-9876.html">
PEP 9876
</reference>
, Let's Hope We Never Get Here
</paragraph>
</footnote>
|
残念ながら、この記事の執筆時点で、DOMツリーやXML文書をreStructuredTextに戻す ツールや機能はありません。Docutils Generic DTD用のリーダーがあれば特に良いでしょう。これがあれば、対応するXML用のreST文書ツリーを作成できます。そのツリーを.astext() ノード・メソッドによってreSTとして書き出すこともできます。そのようなリーダーの作成は大変ではなく、(おそらく私か読者の1人によって) そのうち行われると確信しています。
-
Docutils Webサイトをチェックしてください。reStructuredTextフォーマットそのもの、およびdocutilsパッケージに関する詳細な参照情報があります。また、Docutils Generic XML DTDをダウンロードできます。
- Pythonコードのインライン文書化でreStructuredTextの使用を推奨している、Python Enhancement Proposal 287 を参照してください。このPEPはまた、reSTを同じ目的を持つ他の文書化フォーマット (XML、TeX、HTML、POD、SETextなど) と対比しています。
- スマートASCIIフォーマットと、このフォーマットをdeveloperWorks で使用されるXMLフォーマットに変換する方法について、David Mertz著、txt2dwユーティリティー (developerWorks、2002年1月) を参照してください。
- 以前の『XMLの論考』で、DavidはYAML を紹介しました。これは、人間が容易に読むことができ、動的プログラム言語で使用されるデータ・タイプをエンコードするのに適した、データ・シリアライゼーション・フォーマットです (developerWorks、2002年10月)。
- XMLエディターに関するDavidのコメントを、最近の2回から成る記事で参照してください。第1回ではJavaおよびMacOSアプリケーションについて調べ、第2回ではWindowsベースの製品について調べています (developerWorks、2002年8月および9月)。
- 『XMLの論考』のコラムすべては、以下のとおりです。
- XML文書をオブジェクトとして'Python 的に'取り組む
- XML文書をオブジェクトとして "Python 風" に処理する方法 (II)
- XMLの派生語であるDocBookの紹介
- DocBookのXML版を楽しむ
- XSLTを使ってDocBook文書を変換する方法
- さまざまなエディター
- W3C XML SchemaとDocument Type Definitions (DTD) の比較
- XMLを階層モデル、リレーショナル・モデル、オブジェクト指向モデルに適応させる
- SQL照会からのDTDおよびXML文書の生成
- XML文書を索引付けする
- xml_pickleおよびxml_objectifyの再考: オープン・ソースのレッスンと常識
- Pythonモジュールxml2sqlおよびdtd2sqlの使用: DTDおよびXML文書からのSQLステートメントの生成
- XMLと圧縮: 文書のエントロピーの調査
- DOM、SAX、およびXSLTの限界を超える: XML用のHaXml関数型プログラミング
- オブジェクト・モデルとしてのXML-RPC: 大衆のためのデータ・バンドルか
- もう1つのPython/XMLツール・セット4Suite: 体重400キロのゴリラのようなPython XMLツールの紹介
- PYX入門: 行指向のXML
- REXMLライブラリー: Rubyプログラミング言語におけるXML処理
- 続・XMLと圧縮: ブロック・レベルのアルゴリズムとリソース負荷
- gnosis.xml.validityライブラリーによって妥当性を確保する: OOPデータをXMLの規則に押し込む
- XMLエディターの総まとめ: 第1回: JavaおよびMacOS用の製品を再び取り上げる
- XMLエディターの総まとめ: 第2回: Windows用エディターを再び取り上げる
- YAMLはXMLに改良を加える: YAML Ain't Markup Language (YAMLはマークアップ言語ではない)
- XMLに関するその他の参考文献は、developerWorks XMLゾーンを参照してください。
-
IBM WebSphere Studio(日本語サイト) は、Javaおよび他の言語でのXML開発を自動化するツールのスイートを提供しています。これはWebSphere Application Server
に密接に統合されていますが、他のJ2EEサーバーでも使用できます。
-
XMLおよび関連テクノロジーのIBM Certified Developer になる方法を調べてください。
