[PHP] 「Failed to parse QName 'xmlns:'」エラーが出た時の原因と対処方法

2018年11月7日

PHP テクノロジー 日記

XMLって世の中で至る所で使われていますが、個人的に非常に扱いづらいデータフォーマットであると感じています。 確かに柔軟なフォーマットで、どんなデータ形式も格納できるという守備範囲の広さはわかりますが、柔軟が故にフォーマットリファレンスが存在しないと、読み取る側は深い迷路のように感じてしまうというデメリットを強く感じます。 今回はPHPでXML作成をする作業の時に発生したエラーで、明確な解決方法があったので、備忘録として記録しておきます。

エラーの内容

PHPでのコーディングをしている時に、僕は個人的な作業確認として、エラーログをダンプしながら作業しています。 ダンプのやり方は、phpを実行しているサーバーのapacheかnginxのerror.logをターミナルを開いて下記コマンドを実行しておくだけです。 $ tail -f /var/log/nginx/error.log 僕の環境がDocker + Nginxなのですが、Apacheの場合は、nginxをapacheのログフォルダにするだけでいいはずです。 ※ファイル名が任意設定してある場合はそちらに置き換えて実行してください。 普段からコマンドを使っている人はよくあるフレーズだと思いますが、初心者の人の為にこのコマンドの解説をしておくと、 tailはファイルの末尾を表示するコマンドで"-f"オプションをつけることで、リアルタイム監視状態になり、ログデータなどの追記型ファイルであれば、データが追記されたらそのままターミナルに表示してくれる便利オプションです。 この状態でWEBページを表示した際に、error.logにデータが追記されなければ問題ないのですが、追記される場合は、エラー内容のプログラムファイルの行数を確認するという事です。 今回は名前空間付きのXMLのデータを子階層を再利用する為に個別にXMLパースする際に下記のようなエラーが表示されていました。 PHP message: PHP Warning: simplexml_load_string(): namespace error : Failed to parse QName 'xmlns:' in /var/www/html/xmlparse.php on line 100 simplexmlでnamespaceエラーが出ているようです。

原因と解決方法

QNameってなんじゃらほいと思って調べてみたら、どうやら、xmlns:の指定する文字列フォーマットがおかしいことがわかりました。 そもそも、このxml操作は何をやっていたのかというと、XBRLのデータを解析する時に、到底のタグ毎に階層を取得して、その内部でxpath検索を行う必要があり、xmlヘッダを再セットしてparseしなければいけなかったので、もともとあるxmlのnamespaceを新たにパースするxmlデータに追記する処理で起きていました。 具体的には、xmlns:***="url"という名前空間を作るのですが、一番最初にベースnsを記述する箇所はxmlns="url"となります。 元データの名前空間をkey=valueで取得して保持していたものをforeachで回して、"xmlns:". $key. "=''". $value .""; という風に記述していたため、"xmlns:='***';" という風にkey値がブランクになっている箇所でのエラーだったようです。 この場合はforeach文の中でif(!$key){"xmlns='URL';"} という条件文を追加して、elseと出力を切り分ける事でエラー回避することができました。 そのほかにも、xmlのお作法として、xmlns:%keyの文字の中にスペース文字列が入ってはいけないようです。 プログラムの癖で、"xmlns : %key"という風に、スペースをいれてしまうと、同いエラーが出てしまいます。

XMLとJSONの違い

ところで、XMLデータは名前空間などの仕様で複雑化する傾向がありますが、今時のWEB-APIの仕様はJSONも増えてきています。 一昔前は、CSVファイルでのやりとりが当たり前だった事もありますが、最近では、一部の基幹システム系や、システム構築でエンジニアがやっつけでやるシステムぐらいしかCSVは使われていないようです。 そもそもCSVフォーマットがShift-JIS文字列フォーマットが基本なのが、UTF-8標準のWEB事情と見合わなくなってきているんでしょう。 CSVはともかく、XMLとJSONって、一体どういう違いがあるんでしょう? その昔会社のエンジニア部門で後輩たちに「XMLとJSONの違いを簡単に説明せよ」という指令を出したことがあったのですが、その時に一番納得のいった答えが、
JSONはkey値の重複は許されず、全てユニーク(または連番)でなければいけませんが、XMLはkey値にあたるタグが重複しても問題ないという事から、これをJSONで表すと、全ての階層に配列->連想配列という二重階層にしなければいけない。
このように聞くとXMLの方が優れたデータフォーマットのように聞こえますが、実際にエンジニアは、「jsonフォーマットの方がありがたい」という方が10人中10人でした・・・orz いっそ世の中全てのxmlデータがjsonデータになればいいのに・・・

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。