xmlのお勉強(PHPで解析)

※以前別の場所で書いた文章を備忘的に書き記しておきます。

【投稿年月日】2010-12-17 【ジャンル】PHP/MySQL

 EDINETのxbrl解析をしている最中、xmlの基礎が分かっていないことに気付き、遅ればせながら勉強中。備忘的にブログに書き残しておくことにする。

 PHPのSimpleXMLを使うのでマニュアルを押さえておく。

PHP: SimpleXML - Manual
www.php.net/manual/ja/book.simplexml.php
 

sample.xml

<?xml version="1.0" encoding="utf-8"?>
<xbrli:xbrl xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xbrli="http://www.xbrl.org/2003/instance" type="base">
 <link:schemaRef xlink:type="simple" xlink:href="2009-06-24.xsd" />
 <link:roleRef xlink:type="simple" xlink:href="2009-03-09.xsd#bs" />
 <link:roleRef xlink:type="simple" xlink:href="2009-03-09.xsd#pl" />
 <link:roleRef xlink:type="simple" xlink:href="2009-03-09.xsd#cf" />
 <xbrli:context id="Prior1YearNonConsolidatedInstant">
  <xbrli:entity>
   <xbrli:identifier scheme="http://info.edinet-fsa.go.jp">E02144-000</xbrli:identifier>
  </xbrli:entity>
  <xbrli:period>
   <xbrli:instant>2008-03-31</xbrli:instant>
  </xbrli:period>
 </xbrli:context>
 <xbrli:context id="CurrentYearNonConsolidatedInstant">
  <xbrli:entity>
   <xbrli:identifier scheme="http://info.edinet-fsa.go.jp">E02144-000</xbrli:identifier>
  </xbrli:entity>
  <xbrli:period>
   <xbrli:instant>2009-03-31</xbrli:instant>
  </xbrli:period>
 </xbrli:context>
</xbrli:xbrl>
 まずはサンプル。この「sample.xml」を使ってxmlの名前空間について確認していく。

getDocNamespaces — ドキュメントで宣言されている名前空間を返す

<?php
 $file = "sample.xml";
 try {
  $doc = simplexml_load_file($file);
 }catch (Exception $e) {
  echo "bad xml. ".$e->getMessage()."\n";
 }
 foreach($doc->getDocNamespaces() as $key=>$val) {
  $name_space[$key] = $val;
 }
 var_dump($name_space);
?>
 これ、とても重要。getDocNamespaces()で抽出される名前空間は、要素内、及び、子要素全てで使われる。なお、getDocNamespaces(true)とすると、子要素や孫要素で宣言されているものも含めて名前空間が抽出される。

 xml文書では、文頭の親要素において「xmlns:link="http://www.xbrl.org/2003/linkbase"」などのように宣言されるが、「:」の後の「link="http://www.xbrl.org/2003/linkbase"」が名前空間そのもの。「link」という名前は、「http://www.xbrl.org/2003/linkbase」というユニーク(単一)な空間において定義されている、ということ。
 ただし、このURL(空間)に名前空間の定義ファイルが設置されていると言うわけではない。URLは識別するためのユニークな記号と考えておいた方が無難みたい。

 「sample.xml」では
<?xml version="1.0" encoding="utf-8"?>
の後に
<xbrli:xbrl xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xbrli="http://www.xbrl.org/2003/instance" type="base">
と宣言されているので、「sample.xml」全体では
名前:link = 空間:http://www.xbrl.org/2003/linkbase
名前:xlink = 空間:http://www.w3.org/1999/xlink
名前:xbrli = 空間:http://www.xbrl.org/2003/instance
といった名前空間が使われていることを意味する。

 xml文書において名前空間を使うときは、必ず親要素や要素内において「この名前空間を使うよ!」と宣言しなければならない。例えばxml文書内で
<div:text id="abc1" />
<div id:type="abc1"">DDK-111<div>
<div:text id:type="abc1"">DDK-111</div>
のように名前(「:」が付加した「text」と「type」)を使う場合、例えば親要素<xbrli>において
<xbrli:xbrl xmlns:text ="http://www.xbrl.org/2003/text " xmlns:type="http://www.xbrl.org/2003/type">
のように、あるいは、要素内において
<div:text id:type="abc1" xmlns:text ="http://www.xbrl.org/2003/text " xmlns:type="http://www.xbrl.org/2003/type">DDK-111</div>
のように、「xmlns」で名前空間を宣言する必要がある。(さもなければxmlをパースする際に文法違反のためにエラーが出る)

 一度名前空間を宣言すれば、要素内、及び、子要素や孫要素内で自由にその名前を使うことができる。
 なお、名前空間を使わない(「:」を付加しない)ような場合、例えば
<div class="text" id="abc1">DDK-111</div>
などは、名前空間を宣言する必要がない。。

getNamespaces — ドキュメントで使用している名前空間を返す

<?php
 $file = "sample.xml";
 try {
  $doc = simplexml_load_file($file);
 }catch (Exception $e) {
  echo "bad xml. ".$e->getMessage()."\n";
 }
 foreach($doc->getNamespaces () as $key=>$val) {
  $name_space[$key] = $val;
 }
 var_dump($name_space);
?>
 getNamespaces()で抽出される名前空間は、各要素で実際に使用されているものだけ。getNamespaces(true)とすると、子要素や孫要素などで使用されているものも含めて抽出される。

 「sample.xml」における
<xbrli:xbrl xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xbrli="http://www.xbrl.org/2003/instance" type="base">
<xbrli>要素内では
名前:xbrli = 空間:http://www.xbrl.org/2003/instance
が使われていることを意味する。

 名前空間の分りにくいところは、同じものが、名前空間になったり、タグや要素になったりすること。いわば変幻自在。HTMLにおけるタグやclass、idの関係とは大きく異なるので、なかなか理解しにくかも。

getName — XML要素の名前を取得する

<?php
 $file = "sample.xml";
 try {
  $doc = simplexml_load_file($file);
 }catch (Exception $e) {
  echo "bad xml. ".$e->getMessage()."\n";
 }
 $name = $doc->getName();
 var_dump($name);
?>
 getName()は、XMLタグの名前を抽出する。

 「sample.xml」における
<xbrli:xbrl xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xbrli="http://www.xbrl.org/2003/instance" type="base">
<xbrli>要素のタグの名前は「xbrl」である。
 ちなみに「<xbrli:xbrl」でなく、単に「<xbrli」であるならば、この<xbrli>要素のタグの名前は「xbrli」である。(当たり前か)


 長くなったので「attributes 」や「children」については、また別の機会に(書くかも)。

EDIUNET | PHP/MySQL | 独り言 | 提供サービス | JavaScript