1
3
この記事誰得? 私しか得しないニッチな技術で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

PerlでおてがるXML(2つのライブラリを合せ技にしてみた)

Last updated at Posted at 2024-06-14

今更Perlと思うかも…ですが、XML解析や処理などにおいては大いに役立ち、過去にも書籍が出ていたりします。そして、世間で使用されているXMLライブラリですが、以下の2つがあります。

  • XML::Simple
  • XML::LibXML

XML::Simpleは操作がすごいシンプルなのですが、色々と問題があります。一つはnameで紐づけたXMLタグに対し、出力される順序が保証されないことです。なので、順番を整えるためにXML::XSLTを使用するなどして対応します。

pl
$xslt_file = "change.xslt"; #変更予定の形式
my $xslt = XML::XSLT -> new($xslt_file);
$xslt -> transform($xml); #抽出したXML
$output = $xslt -> toString;

ところが、XML::XSLTだと出力結果に対し改行コードが全部消えてしまうので、XSLT上で逐一改行コード制御が必要になり、相当手間がかかります。

対するXML::LibXSLTの場合は、改行コードがしっかりと保持されます。ですが、その場合はXML::LibXMLでないとうまくデータを読み込めません。しかも、LibXMLはかなり使用に癖があり、使いづらさがあります。

なので、一長一短の2つのライブラリを合体させてみます。

実際にやってみた

結論からいえば、libXMLでの入力を、ファイルからではなくて、XML::Simpleで出力されたXMLオブジェクトで取り込むようにします。

また、LibXMLは世間で紹介されている方法だとうまくいかないことが多いので、海外サイトや公式チュートリアルなどを参考に、構築してみたのが以下のプログラムです。

※各種ライブラリはCPANなどからインストールしておいてください。

pl
use XML::Simple;
use XML::LibXSLT;
use XML::LibXML;

$xslt = "test.xslt"; #XSLTファイル
#まずはXML::SimpleでデータをXMLにする
my $x = new XML::Simple; 
my $xml = qq(<?xml version="1.0" encoding="UTF-8" ?>\n);
$Val = {
		'result' => $result  #任意のXMLデータ群
	};
$xml .= $x -> XMLout($Val, RootName => 'root', NoAttr=>1); #XMLデータの抽出
my $xml = XML::LibXML -> load_xml(string => $xml); #データとして取り込む(string設定必須)
my $xslt = XML::LibXSLT->new()->parse_stylesheet_file($xslt_file); #XSLTの取り込み
my $result = $xslt->transform($xml); #変換
$output.= $xslt -> output_as_chars($result); #出力
$output =~ s/(version=\"1.0\")/$1 encode=\"utf-8\"/g; #ヘッダ情報にエンコード情報を付与

ポイントとしては、load_xmlのときにキー設定をstringにしておくこと(こうしないと、オブジェクトを読み込めない)、それから出力時にはoutput_as_charsとしておくことです。あと、ヘッダ情報にエンコードが付与されないようなので、あとでヘッダ情報だけ挿入しておきます。

これで、各種ファイルで取り込んだXMLの値を自在に変形でき、改行コードを保持したXMLファイルが簡単に作れます。

XSLTファイルについて

XSLTファイルでの制御も簡潔になります。データソースをXML::Simpleで作成してあるので、XSLTファイルもデータを紐づけるnameプロパティと階層化制御のループ処理以外のこまごまとした関数は、ほとんど使用しなくて済むようになります(フォームのvalueプロパティの要領で、適切な位置にはめこんでいくだけ)。

XML::Parserを使ってみた結果

XML::Simpleはそのままだと動作が遅いとのことで、XML::Parserを導入してみたのですが、制御タイムは変わりませんでした。XML::Simpleで制御しているのはEXCELからのデータエクスポートとルート情報の紐づけだけなので、干渉してこないのだと思います。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3