オントロジー(OWLファイル)のクラス数を数えてみようと思ったが,SimpleXMLだと読み込まれなくて困った.
代替案として,PHP5以降で使えるXMLReaderクラスを使ってみることにした.
本エントリーでは,XMLReader初体験の自分用メモとして,使い方などを書き残しておく.
- -
オントロジー例(onto.owl)
<?xml version="1.0"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns="http://www.owl-ontologies.com/Ontology1000000000.owl#" xml:base="http://www.owl-ontologies.com/Ontology1000000000.owl"> <owl:Class rdf:ID="Class_B"> <rdfs:subClassOf> <owl:Class rdf:ID="Class_A"/> </rdfs:subClassOf> </owl:Class> <owl:Class rdf:ID="Class_D"> <rdfs:subClassOf> <owl:Class rdf:ID="Class_C"/> </rdfs:subClassOf> </owl:Class> </rdf:RDF>
RDF Gravityで可視化するとこんな感じ.
- -
まず,SimpleXMLで読み込めなかった状況のみを載せておく.
下のように,普通に出来ると思いきや,何も出力されなかったので,諦めたって話w
<?php $xml = simplexml_load_file("./onto.owl"); print_r($xml); ?>
(2008.09.16追記)
SimpleXMLでも読み込めることが判明.
SimpleXMLでもオントロジーを読み込めた!(childrenで解決) - kakku blog
SimpleXMLで名前空間付きタグの一覧を取得する - 肉とご飯と甘いもの @ sotarok
- -
ここからXMLReaderの話.
とりあえず,使ってみる.
読み込む.owlファイルは上に載せたものとする.
<?php $reader = new XMLReader(); $reader->open("./onto.owl"); while ($reader->read()){ echo $reader->name; echo "<br />"; } $reader->close(); ?>
こんな感じに出力される.
rdf:RDF #text owl:Class #text rdfs:subClassOf #text owl:Class #text rdfs:subClassOf #text owl:Class #text owl:Class #text rdfs:subClassOf #text owl:Class #text rdfs:subClassOf #text owl:Class #text rdf:RDF
この「#text」っていうのは,改行やらタブやらを表す.
この#textを除去するには,以下のように「XMLReader::SIGNIFICANT_WHITESPACE」の判定をすればOK.
<?php $reader = new XMLReader(); $reader->open("./onto.owl"); while ($reader->read()){ if($reader->nodeType == XMLReader::SIGNIFICANT_WHITESPACE){ continue; }else{ echo $reader->name; echo "<br />"; } } $reader->close(); ?>
綺麗になった.
rdf:RDF owl:Class rdfs:subClassOf owl:Class rdfs:subClassOf owl:Class owl:Class rdfs:subClassOf owl:Class rdfs:subClassOf owl:Class rdf:RDF
- -
次は「XMLReader::getAttribute」を使って,要素内容を抽出してみる.
getAttributeの引数に,抽出したい要素内容の要素名を指定する.接頭辞ありでもそのまま記述可能(XMLReader::getAttributeNsを使ってもOK).
<?php $reader = new XMLReader(); $reader->open("./onto.owl"); while($reader->read()){ if($reader->nodeType == XMLReader::SIGNIFICANT_WHITESPACE){ continue; }else{ echo $reader->getAttribute("rdf:ID"); echo "<br />"; } } $reader->close(); ?>
以下の感じに出力される(改行が入るがここでは省略).
Class_B Class_A Class_B Class_D Class_C Class_D
- -
onto.owlの総クラス数は4なのに,上の出力では6になっている.
見たところ,閉じの要素名でも要素内容が抽出されてしまっているのが原因のよう.
閉じの要素名では,カウントしないようにするためには,「XMLReader::END_ELEMENT」を判定する.
<?php $reader = new XMLReader(); $reader->open("./onto.owl"); while($reader->read()){ if($reader->nodeType == XMLReader::SIGNIFICANT_WHITESPACE || $reader->nodeType == XMLReader::END_ELEMENT){ continue; }else{ echo $reader->getAttribute("rdf:ID"); echo "<br />"; } } $reader->close(); ?>
これで正しいクラスの総数が抽出できた(改行が入るがここでは省略).
Class_B Class_A Class_D Class_C
- -
後はこの出力の総数を数えればいいだけなので,簡単に.
<?php $reader = new XMLReader(); $reader->open("./onto.owl"); while($reader->read()){ if($reader->nodeType == XMLReader::SIGNIFICANT_WHITESPACE || $reader->nodeType == XMLReader::END_ELEMENT){ continue; }else{ if($reader->getAttribute("rdf:ID")){ $num++; } } } $reader->close(); echo $num; ?>
できたー!
- -
そんなことで,オントロジーのクラス数を数えるために,XMLReaderを初めて使ってみた.
XMLReaderは,まずデータの階層を全て読み込むSimpleXMLとは違って,イテレータのような感じで1行1行処理をしていくことが出来る点が特徴.
なのでファイルが大きくてメモリを食いすぎる場合などに有効.
今回読み込むオントロジーファイルは結構大きいので,XMLReaderで良かったと思う.
- -
関連エントリー:
PHP: XMLReader - Manual
PHP で XML をプル型構文解析する - IBM developerWorks Japan
SimpleXMLとXMLReaderのまとめ(PHP勉強会で話してきたコード) - 肉とご飯と甘いもの @ sotarok
第34回PHP勉強会で話してきました - maru.cc@はてな