レベル: 中級 Uche Ogbuji (uche@ogbuji.net), Consultant, Fourthought, Inc.
2005年 8月 30日 少し前の記事で、Uche OgbujiはWordNet 2.0を取り上げました。これは、プリンストン大学のプロジェクトであり、英単語とそれらの間の語彙的関係のデータベースを構築することを目的としています。彼は、ワード・データベースからXML直列化を抽出する方法を解説しました。今回の記事では、引き続き、これらのWordNet/XMLドキュメントをWebのプロトコルを介して提供するコード例を示し、XSLTからこれらにアクセスする方法を解説します。
XMLは、Web上のSGMLであり、これは、いかなる意味でもWebとの接点が見られない珍しいXMLプロジェクトです。少し前に、私はこのコラムで「Querying WordNet as XML」を書き、その中でWordNet 2.0とXMLおよびRDFテクノロジーでの使い方を説明しました。この記事を読んでいない方は、今回の記事を読む前に読んでください。今回は、WordNetの語彙情報をXML形式で抽出する基本的なコードを書き込みます。Web上の単語情報をHTMLおよびXML形式で提供する方法を示します。
Webサーバー・コード
今回の記事では、コードにPythonとXSLTを使用しますが、コンセプトは他のほとんどのプログラミング言語でも同様です。Pythonコードの説明では、この言語の基本的な理解に必要なことをわかりやすく説明するつもりです。Pythonは、標準ライブラリーにある非常に簡単なBaseHTTPServerモジュールから、Zopeのようなサードパーティ製の大規模システムまで、さまざまなWebアプリケーション作成方法をサポートしています。その中間には、Python Webフレームワーク用の無数の選択肢があります。非常に人気があり、私のお気に入りでもあるのは、CherryPyです(「参考文献」を参照)。シンプルで、Pythonのイディオムに適しています。リスト1(wnserver.py)は、CherryPyを使用して、非常に簡単なURL方式に基づいて単語に関する情報を提供するプログラムです。
リスト1.WordNet情報を提供するCherryPyサーバー・コード(wnserver.py)
import cherrypy
from picket import Picket, PicketFilter
from wnxmllib import *
class root:
_cpFilterList = [ PicketFilter(defaultStylesheet="viewword.xslt") ]
class wordform_handler:
def __init__(self, applyxslt=False):
self.applyxslt = applyxslt
return
@cherrypy.expose
def default(self, word):
synsets = serialized_synsets_for_word(word)
result = ''.join(synsets) #Concatenate strings in result list
#Wrap up the XML fragments into a full document
wordxml = '<word-senses text="'+word+'">'+result+'</word-senses>'
if self.applyxslt:
picket = Picket()
picket.document = wordxml
return picket #apply the XSLT and return the result
return wordxml
class pointer_handler:
@cherrypy.expose
def default(self, pos, target):
synset = getSynset(pos, int(target))
synsetxml = serialize_synset(synset)
picket = Picket()
picket.document = synsetxml
return picket #apply the XSLT and return the result
cherrypy.root = root()
cherrypy.root.view = wordform_handler(applyxslt=True)
cherrypy.root.raw = wordform_handler()
cherrypy.root.pointer = pointer_handler()
#Disable debugging messages in Web responses
cherrypy.config.update({'logDebugInfoFilter.on': False})
cherrypy.server.start()
|
コードは非常にシンプルですが、後で説明するように、かなりの量の仕事をします。Python 2.4以上が必要です。このバージョンの新機能であるデコレーターを使用するからです。まず、必要なものを見てみましょう。インポートの1つは、wnxmllib.pyからです。これは基本的には、WordNetに関する前回のコラムで示したコードですが、1つのファイルにまとめられ、よりシンプルな4Suite APIを使用するために少しアップデートされています。下記の必要条件以外のコードは、この記事のダウンロード・ファイルに含まれています。
-
CherryPy (import cherrypy):CherryPy 2.1(現在はベータ版)以上
-
Picket (from picket import Picket, PicketFilter):これは、CherryPyサーバーからXSLTを起動するためのAPIを単純化するわかりやすいツールです。Picket 0.5以上。
-
4Suite(wnxmllib.pyからインポート):コアXMLライブラリー。4Suite 1.0b1以上。
-
PyWordNet(wnxmllib.pyからインポート):WordNet処理ライブラリー。PyWord Net 2.0.1以上。
-
WordNet:実際の語彙データベース・ファイル。WordNet 2.0以上。
リストwnserver.pyには3つのクラスが含まれ、それぞれサイトのURL空間の異なる部分を処理します。これは、ファイルの末尾のコードによって制御されます。ほとんど空のクラスrootは、実際には、サイトのルートURLのプレースホルダーです。テスト用マシンでは、http://localhost:8080/などになります。実際のアクションはすべて、より具体的なURLで始まります。下記のリストに、URLステムからクラスへのマッピングを示します。
- http://localhost:8080/view/で始まるURLは、wordform_handlerのインスタンスによって処理され、WordNet XML結果にXSLTを適用します。これは、一般的なWebブラウザーでの表示のためです。
- http://localhost:8080/raw/で始まるURLは、wordform_handlerのインスタンスによって処理され、WordNet XML結果を直接返します。これは、XMLを処理できるアプリケーションでの使用を目的としています。
- http://localhost:8080/pointer/で始まるURLは、pointer_handlerクラスのインスタンスによって処理されます。これは、前回のWordNetの記事の最後の方で述べたように、単語の意味から別の意味へのリンクを解釈するためのものです。また、XSLTを使用して、XMLをブラウザー用のHTMLに変換します。
rootクラスはフィルターをセットアップします。これは、HTTPリクエストの結果であるデータと、HTTPレスポンスとして送り出されるデータにも何らかのアクションを実行するCherryPy構成体です。この特定のフィルターPicketFileterでは、必要な場合に、出力にXSLT変換を適用することができます。CherryPyは、ルート・ハンドラー上のこのフィルターがcherrypy.rootからのチェーン上の他のハンドラー・オブジェクトにも適用されるようになっています。フィルターのアクションについては、もう少し後で詳しく述べます。
wordform_handlerクラスにはイニシャライザーがあり、渡されたパラメーターを管理して、XML結果にXSLTを適用するかどうかを決めます。特殊なメソッドdefaultは、@cherrypy.exposeデコレーターによってCherryPyハンドラー関数としてマークされます。これはURLから語句をパラメーターとして取り、wnxmllib.serialized_synsets_for_wordを呼び出して、結果としてのXMLチャンクを入手します。次に、文字列連結を使用して、完全な整形式のXML文書を作成します。単純な文字列連結は、一般に、XMLドキュメントを構築するには危険な方法であることに注意してください(この点を詳しく説明している記事については、「参考文献」を参照してください)。私がこの方法を用いるのは、WordNet 2.0のデータを非常に明瞭に理解していて、XML直列化問題についても専門知識があるからです。自分のやることにあまり自信がない場合は、このようなショートカットは避けて、適切なXML出力ツールキット(4SuiteのMarkupWriterなど)を使用してください。
変換
wordform_handlerは、XSLTを適用するようにセットアップされた場合、Picketオブジェクトを作成します。このようなオブジェクトは前述のフィルターによってキャッチされて、XSLT変換を適用して実際の出力を生成するために使用されます。ソース・ドキュメントは、WordNet類語セット情報から作られたXMLです。リスト2(viewword.xslt)は、XSLT変換です。
リスト2.WordNet XMLをHTMLとして表示するXSLT(viewword.xslt)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="word-senses/@text"/></title>
</head>
<body bgcolor="#ffffff">
<h1><xsl:value-of select="word-senses/@text"/></h1>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="noun">
<p>
<xsl:text/>[<xsl:apply-templates select="word-form"/>] <xsl:text/>
<em>n. </em><xsl:apply-templates select="gloss"/>
<div> ‡ <xsl:apply-templates mode="synset-body"/></div>
</p>
</xsl:template>
<xsl:template match="verb">
<p>
<xsl:text/>[<xsl:apply-templates select="word-form"/>] <xsl:text/>
<em>v. </em><xsl:apply-templates select="gloss"/>
<div> ‡ <xsl:apply-templates mode="synset-body"/></div>
</p>
</xsl:template>
<xsl:template match="adjective">
<p>
<xsl:text/>[<xsl:apply-templates select="word-form"/>] <xsl:text/>
<em>adj. </em><xsl:apply-templates select="gloss"/>
<div> ‡ <xsl:apply-templates mode="synset-body"/></div>
</p>
</xsl:template>
<xsl:template match="adverb">
<p>
<xsl:text/>[<xsl:apply-templates select="word-form"/>] <xsl:text/>
<em>adv. </em><xsl:apply-templates select="gloss"/>
<div> ‡ <xsl:apply-templates mode="synset-body"/></div>
</p>
</xsl:template>
<xsl:template match="word-form">
<!-- construct a link to this word form -->
<a href="/view/{.}">
<xsl:apply-templates/>
</a>
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:template>
<xsl:template match="gloss">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*" mode="synset-body">
<xsl:if test="@target">
<!-- then it's a pointer: construct a link to it -->
<a href="/pointer/{@part-of-speech}/{@target}">
<xsl:value-of select="name()"/>
</a><xsl:text> </xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
|
このXSLTは単語の意味情報を取り、それぞれの意味の用語解説(短い定義)を表示します。また、WordNetのポインターに基づいて、他の意味へのリンクのセットも表示します。このXSLTの結果を見ると、操作がわかりやすくなるでしょう。図1は、リスト1のWebサーバーを実行して、codeという単語のページを開いたときに表示される内容です。このスクリーンショットに使用したWebブラウザーは、Mozilla Firefoxです。これを見るとわかるように、私が表示したURLはhttp://localhost:8080/view/codeです。
図1.単語"code"のページのブラウザー表示
リンクをクリックすると、単語ではなく類語セットを参照するポインターにジャンプします。この場合、角括弧に囲まれた類語セット、用語解説、他の類語セットへのリンクについて、すべての語形を含んだシンプルな表示にすることにしました。リスト2のXSLTでは、完全な語形情報と個々の類語セットの情報を表示するようにしました。WebサーバーのポインターURLを処理するコードは、リスト1のpointer_handler.defaultクラスです。示されているように、これはURLから2つの値を取ります。http://localhost:8080/pointer/noun/5955443などのURLは、pointer_handler.defaultの呼び出しとなり、品詞nounとWordNetオフセット5955443を含んでいます。非常に重要な点として、それぞれの用語解説の前に表示される語形をリンクとして表示することにしました。これは、英単語の間の多くの関係をクリックしていくことによって、WordNetデータベースを深く、広くナビゲートできることを意味します。
XMLでございます、奥様
このWordNet Webサーバーの例では、http://localhost:8080/raw/....という形式のURLを使用して、単語の生のXMLを取得することもできます。XMLを使用するWebアプリケーションにとって、Webブラウザー用に作成されたHTMLだけでなく、このXMLをWebに直接公開するのは非常に重要なことだと思います。こうすると、HTMLから掬い取るのではなく、このXMLを直接処理して、機能を拡張する他のアプリケーションを容易に作成することができます。これがいかに便利かを示す例として、リスト3はサーバーに生のXMLを問い合わせて、それを処理する単純なXSLTコードを示しています。これは単語リストを取り、同じリストを各単語の可能な定義の1つでアップデートしたものを出力します。
リスト3.WordNetメイン・サーバーへのクエリーに基づくXSLTの例
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="word-list">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="word">
<!-- The word form to look up is the element content -->
<xsl:variable name="wordform" select="."/>
<!-- Use the word form to construct the query URL -->
<xsl:variable name="wordnet-url"
select="concat('http://localhost:8080/raw/', $wordform)"/>
<!-- Query the WordNet server, retrieving an XML document -->
<xsl:variable name="wordnet-info" select="document($wordnet-url)"/>
<!-- Grab the first gloss from the retrieved WordNet document -->
<xsl:variable name="gloss" select="$wordnet-info//gloss[1]"/>
<xsl:copy>
<form><xsl:value-of select="."/></form>
<sample-gloss><xsl:value-of select="$gloss"/></sample-gloss>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
|
このXSLTをリスト4のテスト・ドキュメント(wordlist.xml)に対して実行すると、リスト5の結果になります。
リスト4.リスト3での変換用の単語リスト・ドキュメントの例(wordlist.xml)
<word-list>
<word>animal</word>
<word>vegetable</word>
<word>mineral</word>
</word-list>
|
リスト5.リスト3のXSLTをリスト4のテスト用XMLに適用した結果
<?xml version="1.0" encoding="UTF-8"?>
<word-list>
<word><form>animal</form><sample-gloss>a living organism characterized
by voluntary movement</sample-gloss></word>
<word><form>vegetable</form><sample-gloss>edible seeds or roots or
stems or leaves or bulbs or tubers or nonsweet fruits of any of
numerous herbaceous plant</sample-gloss></word>
<word><form>mineral</form><sample-gloss>solid homogeneous inorganic
substances occurring in nature having a definite chemical
composition</sample-gloss></word>
</word-list>
|
リスト5では、書式設定目的で空白類を追加しました。サンプルの用語解説の内容は、WordNetサーバーへの動的クエリーで得たものです。これは、WordNetとXMLを組み合わせた場合のパワーのもう1つの例にすぎません。
まとめ
私は今後も、XML形式で使用可能になったWordNetの実用化を続けるつもりです。今後のトピックとしては、RDFデータベースとしてのWordNetの公開や、それによる検索強化などがあります。それまでの間に、「XML的思索」ディスカッション・フォーラムにご感想をお寄せください。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| Sample code for WordNet as XML | x-think33-code.zip | 6KB | FTP |
|---|
参考文献 学ぶために
製品や技術を入手するために
著者について  | 
|  | Uche Ogbuji氏は、Fourthought, Inc. のコンサルタント兼共同設立者です。この会社は、企業のナレッジ・マネジメントのためのXMLソリューションを専門とするソフトウェア・ベンダー兼コンサルタント会社です。Fourthoughtでは、XML、RDF、およびナレッジ・マネジメント・アプリケーション用のオープン・ソース・プラットフォームである4Suiteを開発しています。Ogbuji氏は、ナイジェリア出身のコンピューター・エンジニア兼ライターで、現在は、米国コロラド州ボールダーに住み、そこで働いています。Ogbuji氏の連絡先はuche.ogbuji@fourthought.com です。 |
記事の評価
|