この記事はLibreOffice Advent Calendar 2019の10日目の記事として書かれました。昨日の記事は、baffclanさんの「LibreOffice 起動時に表示される 今日のヒント の一覧」でした。
FILTERXML関数
LibreOffice Calcには、FILTERXML関数というものがあります。WEBSERVICE関数でサーバーから貰ってきたXMLデータから値を取り出したいといった場合に使います。
パラメーターは2つあり、1つ目のパラメーターにXMLを、2つ目にXPath式というものを取ります。
次の数式をCalcのセルに入力すると、値「1」が表示されます。
=FILTERXML("<ROOT><VALUE>1</VALUE></ROOT>","//ROOT/VALUE")
実験してみる
それでは、IPA文字情報基盤データベースのMJ文字情報取得APIを使って、MJ文字図形名の情報を取り出してみましょう。文字情報基盤データベースのページの情報によると、次の様に書けば良さそうです。
A1セル
=WEBSERVICE("https://mojikiban.ipa.go.jp/mji/MJ010057.xml")
A2セル
=FILTERXML(A1,"//MJ文字情報一覧表/MJ文字情報/MJ文字図形名")
うまく動きません。
#N/A
A1セルにはXMLが表示されているので、WEBSERVICE関数はうまく動いているようです。
#EXCELで試す
Microsoft Excelにも、WEBSERVICE関数とFILTERXML関数があります。
Excel 2019で同じことをしてみます。
MJ010057
値が取れました。
XPath式が間違っている訳でもない様です。
#XML名前空間
LibreOffice Calcに戻ります。WEBSERVICE関数で取ってきたXMLの中に次の要素があると思います。
<MJ文字情報一覧表 xmlns="urn:mojikiban:ipa:go:jp:mji" version="005.02">
このxmlns=...
の部分をごっそり削除します(XMLをコピーしてから、形式を選択して貼り付け→テキスト等の操作を行った後、XMLを編集する)。
値が取れました。
MJ010057
XMLには名前空間があって、ダグの重複を避けるために名前空間を指定することができる様です。
Wikipediaによると、
XMLの名前空間は、要素名などが重複することのないように整理された空間。xmlns属性などで名前空間を宣言する。例えば、「html:p」と記述されたタグでは、「html」が名前空間接頭辞で「p」が要素名を表す。
また、ここにe_toyodaさんが書いてくれている様に、*[name()='タグ']を使えば良い様です。
次の様に書いてみました。
=FILTERXML(A1,"//*[name()='MJ文字情報一覧表']/*[name()='MJ文字情報']/*[name()='MJ文字図形名']")
値が取れました。
MJ010057
でも、これ面倒臭くないですか?
という訳で書いた誰得なパッチがこれです。1
LibreOfficeにこのパッチを当てると、FILTERXML関数の動作が変わります。名前空間ありでXPath式を評価して値が取得出来なかった場合、再度、与えられたXMLの名前空間を無視してXPath式を評価する動作になります。
先の実験では、A2セルに次の様に入力すれば、
=FILTERXML(A1,"//MJ文字情報一覧表/MJ文字情報/MJ文字図形名")
値が取れる様になります。
MJ010057
自分で使ってみて意外と便利だったので記事を書いてみました。
FILTERXML関数にも、Ignore namespaces with XPath的なオプションはあって良いかもと思った次第です。2