xml ファイルに含まれる要素と属性の一覧を知りたい


ある xml ファイルには、「おそらく」要素が A、B、C、D の 4 種類あり、要素 A には、A1、A2、A3、A4 の属性、要素 B には、B1、B2、B3、B4 の属性、要素 C と要素 D にはそれぞれ、属性 C1 と D1 がある、と「思われます」。

しかし、これ以外にも要素や属性があるかもしれません。
そこで、何かしらの方法を使って、XML ファイルから要素と属性の一覧を取得したいと思います。
重複するものは無視して、一意のものだけを一覧にしたものがほしいと思っています。

こうした XML ファイルは合計で 20 ファイルくらいあり、サイズはまちまちで数百 KB から 150 MB までです。
ただし、含まれている主要な要素と属性は同じだと思います。
150 MB が流石に大きすぎるのであれば、何らかの方法で分割は可能です。

PHP 5.3.0、秀丸、EXCEL 2007、XMLEDITOR.NET を使っています。
そのほかフリーソフトや簡単なスクリプトでこの一覧を取得する方法を教えてください。

回答の条件
  • 1人1回まで
  • 登録:
  • 終了:2010/02/09 20:05:11
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:t-wata No.1

回答回数82ベストアンサー獲得回数13

ポイント80pt

phpマニュアルにあるSAXのサンプルコードをベースに、1つのxmlを読み込み、単純に要素とそれに対する属性を一意になるように取得し、最後に"要素,属性1,属性2...."のようなCSVを出力するサンプルを作ってみました。

phpはほぼ初めてなんで、変な部分があるかもしれませんが、これを適当にいじって複数ファイルに対応させたりすれば何とかなるんじゃないですか?

<?php
$file = "test.xml";
$map_array = array();

function startElement($parser, $name, $attrs) 
{
    global $map_array;
    if (isset($map_array[$name])) {
        $tmp_attrs = $map_array[$name];
        foreach(array_keys($attrs) as $aname){
            if (!isset($tmp_attrs[$aname])) {
                $tmp_attrs[$aname] = $attrs[$aname];
            }
        }
        $map_array[$name] = $tmp_attrs;
    } else {
        $map_array[$name] = $attrs;
    }
}
function endElement($parser, $name) {}

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_set_element_handler($xml_parser, "startElement", "endElement");
if (!($fp = fopen($file, "r"))) {
    die("could not open XML input");
}

while ($data = fread($fp, 4096)) {
    if (!xml_parse($xml_parser, $data, feof($fp))) {
        die(sprintf("XML error: %s at line %d",
                    xml_error_string(xml_get_error_code($xml_parser)),
                    xml_get_current_line_number($xml_parser)));
    }
}
xml_parser_free($xml_parser);

foreach (array_keys($map_array) as $name) {
    $list = "";
    $attrs = $map_array[$name];
    foreach(array_keys($attrs) as $aname) {
        $list = "$list,$aname";
    }
    print "$name$list\n";
}
?>
id:Nigitama

ありがとうございます。

求めているような形になりました。

今回の質問とは異なりますが、ちょっといじって、違うことにも役立ちました。

2010/02/09 19:59:35
  • id:infograve
    コードの提示とかではないので、こちらで。

    時間があるなら、
    http://jp2.php.net/manual/ja/book.xml.php
    XMLパーサで解析し、重複しない要素を抜けばいいと思うんですが。
  • id:t-wata
    目的とはずれますが、その予想されるXMLのDTDを作って、それに対してvalidateかけて確認すれば、予想外の要素や属性を拾うことはできます。

    もし一覧を取得するなら、xmlネームスペースや、同一要素名を異なる目的で使っている場合(たとえば、CD要素の子要素であるTITLEとBOOK要素の子要素であるTITLEは同じTITLEでも意味が違うので属性なども必然的に異なる可能性がある)を考慮する必要があり結構面倒ですよ。
    これらを考慮せず単純にリストだけ取りたいなら、SAX使える言語を使えば割と簡単にできると思います。


  • id:Nigitama
    コメントありがとうございます。
    パーサ、ですね、今回初めてさわりました。。。

    今回、特に疑わしかった (予想外のものがあるかもしれない) 部分を見つけるために、コメントに書いていただいた t-wata さんの DTD の発想が役立ちました。

    ある特定要素の type 属性には、5 種類の値しか確認できていませんでしたが、
    ひょっとしたらほかの属性値があるのではないかと疑っていたので、
    単純にその要素の type 属性の数と、5 種類の値の数を比較してみました。
    結果、いくつか予想外のものが発見でき、取りこぼしなしになりました。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません