• 締切済み

PerlでXMLのフィルタリング

いつもお世話になっております。Perl初心者です。 以下のサイトを参考に、XML::Parser::PerlSAX を使用して、XMLファイルをフィルタリングするプログラムを作成しようと考えています。 http://mkweb.bcgsc.ca/intranet/perlbook/pxml/ch05_01.htm ここで、ある要素のある属性の、異なる属性値ごとに、文字データイベントを処理する方法を変えたいのですが、どのようにすればよいでしょうか。 各種SAXイベントハンドラも、XML::Handler::Subs も考えましたが、何を使えばよいか検討がつきません。よろしくお願いします。

  • Perl
  • 回答数1
  • ありがとう数9

みんなの回答

回答No.1

適当。表示がくずれるので空白2文字を全角空白にしていることに注意。 use strict; use warnings; use feature 'say'; use XML::SAX; my $xml = << "END"; <?xml version="1.0" encoding="utf-8" ?> <pets>  <pet>   <type>dog</type>   <name pos="1">Yamada</name>   <name pos="2">Taro</name>   <age>3.5</age>  </pet>  <pet>   <type>cat</type>   <name pos="1">Yamada</name>   <name pos="2">tama</name>   <age>1</age>  </pet> </pets> END my @target_hierarchy = qw(pets pet name); my @work_hierarchy  = (); my $call_back    = undef; my $parser = XML::SAX::ParserFactory->parser( Handler => MySAXHandler->new ); $parser->parse_string($xml); {   package MySAXHandler;   use base qw(XML::SAX::Base);   sub start_element {     my ( $self, $el ) = @_;     push @work_hierarchy, $el->{LocalName};     $call_back = undef;     if ( _check_hierarchy() ) {       if (  exists( $el->{Attributes} )         and exists( $el->{Attributes}->{'{}pos'} )         and $el->{Attributes}->{'{}pos'}->{Value} )       {         my $posision = $el->{Attributes}->{'{}pos'}->{Value};         if ($posision eq '1') {           $call_back = \&_say_first;         }         elsif ($posision eq '2') {           $call_back = \&_say_second;         }         else {           warn 'Unknown ', $posision;         }       }     }   }   sub end_element {     my ( $self, $el ) = @_;     $call_back = undef;     pop @work_hierarchy;   }   sub characters {     my ($self, $data) = @_;     if ( defined $call_back ) {       $call_back->( $data->{Data} );     }   }   sub _check_hierarchy {     if ( $#target_hierarchy != $#work_hierarchy ) {       return 0;     }     else {       for ( my $i = 0; $i <= $#target_hierarchy; $i++ ) {         return 0 if ( $target_hierarchy[$i] ne $work_hierarchy[$i] );       }       return 1;     }   }   sub _say_first {     my $name = shift;     say "1: $name";   }   sub _say_second {     my $name = shift;     say "2: $name";     say '---';   }   1; } ------ $ perl -w foo.pl 1: Yamada 2: Taro --- 1: Yamada 2: tama ---

cat-rice
質問者

お礼

ご回答ありがとうございました。 スクリプト全体をご提供いただきありがとうございます。 早期にご回答いただいたにも関わらず、メールの連絡がされず、気がついていませんでした。 自分でも無事、自己解決しました。 いただいたスクリプトも今後、研究させていただきます。

関連するQ&A

  • [Perl]XML::SimpleでSJIS

    Windows7、ActivePerl v5.24.1を使っています。 use XML::Simple; use Data::Dumper; my $data = XMLin('test.xml'); print Dumper($data); というコードで、以下のXMLファイルを読み込むと、 <?xml version="1.0" encoding="shift_jis"?> <root> <top id="1234"> <second>値</second> <third> <fourth>1234</fourth> <fifth>myvalue</fifth> </third> </top> </root> Couldn't open encmap shift_jis.enc: No such file or directory at C:/Perl/lib/XML/Parser.pm line 187. XML::Simple called at read_xml_test.pl line 10. というエラーがでます。 ググると、以下のサイトで解決できたという記事がヒットしますが このサイトはもう存在しません。 Perl XMLでencoding=’Shift_JIS’や’euc-jp’を使う http://homepage3.nifty.com/hippo2000/perltips/xml/xmlenc.htm なにかコード間のマップファイルと思われますが、 どなたかお持ちじゃないでしょうか?

  • PerlによるXMLからCSVへの変換について

    Perl初心者です。 下記のようなXMLファイル(test.xml)を、CSVに変換したいと考えています。 <MODESMESSAGE> <DATETIME>20121129045500</DATETIME> <MODES>8515C4</MODES> <CALLSIGN>JAL1406</CALLSIGN> <ALTITUDE>03075</ALTITUDE> <GROUNDSPEED>177</GROUNDSPEED> <TRACK>330</TRACK> <VRATE>-832</VRATE> <AIRSPEED>000</AIRSPEED> <LATITUDE>35.4003</LATITUDE> <LONGITUDE>139.8822</LONGITUDE> <SQUAWK>3341</SQUAWK> </MODESMESSAGE> <MODESMESSAGE> <DATETIME>20121129045500</DATETIME> <MODES>86CF11</MODES> <ALTITUDE>20100</ALTITUDE> <VRATE>0</VRATE> <AIRSPEED>000</AIRSPEED> <LATITUDE>0</LATITUDE> <LONGITUDE>0</LONGITUDE> </MODESMESSAGE> データによって、要素が欠けている場合もありますが、最大で11個の要素が並んでいます。 これをCSVに変換するため、書籍を参考にしながら以下のスクリプトxml2csv.plを作りました。 使用している環境はLinuxです。 use encoding "utf8", STDOUT=>"Shift_JIS"; use XML::Parser; $parser = new XML::Parser( Handlers => {Start=>\&element_start, Char => \&cdata, End => \&element_end}); $element_name = ''; %records = {}; eval ( "\$parser->parsefile( \@ARGV[0] );"); if ($@) { chomp($@); $@ =~ s/^\n//; $@ =~ s/ at (?:[A-Z]:)?\/.*//; print @ARGV[0] . " :Error $@ \n"; } sub element_start { my ($expat, $name, %attributes) = @_; $element_name = $name; $records = {} if ( $name eq 'MODESMESSAGE' ); } sub element_end { my ($expat, $name) = @_; if ( $name eq 'MODESMESSAGE' ) { print $records{'DATETIME'} . "," . $records{'MODES'} . "," . $records{'CALLSIGN'} . "," . $records{'ALTITUDE'} . "," . $records{'GROUNDSPEED'} . "," . $records{'TRACK'} . "," . $records{'VRATE'} . "," . $records{'AIRSPEED'} . "," . $records{'LATITUDE'} . "," . $records{'LONGITUDE'} . "," . $records{'SQUAWK'} . "\n"; } $element_name = ''; } sub cdata { my ($expat, $context) = @_; $records{$element_name} = $context if ($element_name); } 実行すると、 > perl xml2csv.pl test.xml 20121129045500,8515C4,JAL1406,03075,177,330,-832,000,35.4003,139.8822,3341 test.xml :Error junk after document element at line 14, column 0, byte 345 > 上記の通り1つ目のデータについてはCSVに変換できているようなのですが、2つ目以降が変換されずエラーとなってしまいます。 お気づきの点がありましたら教えていただけないでしょうか。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • Java ファイルオブジェクトでなく文字列オブジェクト?

    JavaでXMLをパースするプログラムを初めて試しています。 parseメソッドの第一引数がファイルオブジェクトなのですが、これをメモリ(文字列)オブジェクトを与えて同じ動作させるものはあるのでしょうか? // SAXパーサーファクトリを生成 SAXParserFactory spfactory = SAXParserFactory.newInstance(); // SAXパーサーを生成 SAXParser parser = spfactory.newSAXParser(); // XMLファイルを指定されたデフォルトハンドラーで処理します parser.parse(new File("helloworld.xml"), new InsXMLParser()); ※このように String str = "<xml? ......"; parser.XXXXXX(str, new InsXMLParser

    • ベストアンサー
    • XML
  • JavaでのXMLパーサの使用について

    javaでパーサを使ってDOMツリーを作成したいのですが、パーサインスタンスが作成できずにエラーがでてしまいます。ちなみにコンパイルは通ります。 以下にソースとエラー内容を記述しますので、もしよろしかったらどなたか教えて下さい。 import java.io.*; import com.ibm.xml.parsers.*; import org.xml.sax.*; import org.w3c.dom.*; public static void main(String[] args){ try{      //XML文書作成 String xml = "<sample>Hello Java World</sample>"; //DOMパーサ作成 DOMParser parser = new DOMParser(); //入力ストリーム作成      StringReader sr = new StringReader(xml); InputSource is = new InputSource(sr); //パースする parser.parse(is); //ドキュメントを得る Document doc = parser.getDocument(); //トップレベル要素を得る Element el = doc.getDocumentElement(); System.out.println("Top Level Element: " + el.getTagName()); } catch(Exception e){ e.printStackTrace(); } } エラー内容: java.lang.NoClassDefFoundError: com.ibm.xml.parsers.DOMParser java.lang.Throwable(java.lang.String) java.lang.Error(java.lang.String) java.lang.LinkageError(java.lang.String) java.lang.NoClassDefFoundError(java.lang.String) void pkxml.dom.PsDomBean.makedom() void pkxml.dom.PsDomBean.makedom() void pkxmlsutabu.Sutabu.main(java.lang.String [])

  • [Perl]Shift-JISのXMLを解析する場

    行き詰まってしまったので教えて下さい。 <やりたいこと> とあるAPIからXMLファイルを取得し、解析して出力する、ということをやっているのですが、元のXMLがShift-JISでエンコーディングされており、これをUTF-8に変換して出力しようとしています。 <問題> XMLを取得して解析、取り出したいパラメータが出力できるようにはなったのですが、文字のエンコーディングが上手く行っていないためか、文字化けしてしまいます。 <元のXML> <?xml version="1.0" encoding="Shift_JIS"?>  <test>   <prod count=3>    <record>     <code>アイウエ</code>    </record>    <record>     <code>カキクケ-</code>    </record>    <record>     <code>ABC</code>    </record>   </prod>  </test> <XML解析用のコード> #!usr/bin/perl use utf8; use Encode qw/ from_to encode decode /; use Encode::Guess qw/ euc-jp shiftjis 7bit-jis /; use LWP::UserAgent; use XML::Simple; use Data::Dumper; #--XML取得部分省略 #--XMLはgetで$xmlに格納 $from = guess_encoding($xml)->name; &from_to($xml,$from,"utf8"); $XML::Simple::PREFFERRED_PARSER = 'XML::SAX::PurePerl'; $xs = new XML::Simple(); $ref = $xs->XMLin($xml); $xml =~ s/<\?.*\?>//; for($i=0;$i<=$#{$ref->{'test'}->{'prod'}->{'record'}};$i++){  $name = $ref->{'test'}->{'prod'}->{'record'}[$i]->{'code'}; $name = encode('utf-8',$name); print "$i : $name\n"; } <結果> 黒ダイヤに?文字で文字化けして出力される。 どなたか原因がお分かりになりますでしょうか。 よろしくお願いいたします。

  • PerlのSAX利用中にXSL変換するには?

    お世話になります。 Windows7上のActivePerlで、 use XML::SAX; use XML::LibXSLT; モジュールを利用中に、 start_elementイベント時のタイミングで、 取得したタグ文字を、 そのタイミングで、XSL変換することは可能なのでしょうか? 今回の目的は、 XSL変換した後の各値を、 配列などにセットできればOKという状況ですので、 もしSAXで無理でしたら、 たとえばDOMやXPathなどで、 use XML::LibXML; use XML::LibXSLT; モジュールを利用中に、 随時取得したタグ文字を対象として、 そのタイミングで、XSL変換して配列にセットできれば、 それでもOKという状況です。 PS: (ちなみに、  XSLファイル内で、  <xsl:output method="xml">  を指定してから、  XSL変換を実施すると、  まとめてXSL変換自体は、  一通り正常に行われているのですが、  なぜか、出力されたファイルは、  XML形式ではなくて、  text形式でファイルが出力されてしまう為、  (タグ文字が全て空白文字に置換されています)  XMLパーサが一切利用出来なくなってしまい、困っています) 以上になります。 もしご存じの方がいらっしゃいましたら、 よろしくお願いします。

    • ベストアンサー
    • Perl
  • tomcatコマンドプロンプトのエラーメッセージ。

    D:\tomcat\webapps\netjv\Web-infの中にWeb.xmlを配置したところ、tomcat再起動時に下記のエラーメッセージが出てきました。意味がわかるかたお願いします。 略 ・ ・ 2003-02-08 13:37:20 - Ctx(/netjv) : Validating web.xml 2003-02-08 13:37:20 - Ctx(/netjv) : web.xml: Error org.xml.sax.SAXParseException : 要素 "servlet" ではここに "servlet-class" を指定することを許可されません。 ERROR reading D:\tomcat\webapps\netjv\WEB-INF\web.xml2003-02-08 13:37:20 - Ctx(/ netjv) : Line 9 /web-app/servlet/ 2003-02-08 13:37:20 - Ctx(/netjv) : web.xml: Error org.xml.sax.SAXParseException : 要素 "servlet" ではここに "init-param" を指定することを許可されません。 2003-02-08 13:37:20 - Ctx(/netjv) : Line 10 /web-app/servlet/ 2003-02-08 13:37:20 - Ctx(/netjv) : web.xml: Error org.xml.sax.SAXParseException : 要素 "servlet" ではここに "init-param" を指定することを許可されません。 2003-02-08 13:37:20 - Ctx(/netjv) : Line 14 /web-app/servlet/ 2003-02-08 13:37:20 - Ctx(/netjv) : web.xml: Error org.xml.sax.SAXParseException : 要素 "servlet" ではここに "init-param" を指定することを許可されません。 2003-02-08 13:37:20 - Ctx(/netjv) : Line 18 /web-app/servlet/ 2003-02-08 13:37:20 - Ctx(/netjv) : web.xml: Error org.xml.sax.SAXParseException : 要素 "servlet" には追加属性が必要です。 ・ ・ ・ 略

  • JavaによるXMLの読み込みについて

    現在、JavaでXMLを読みたく色々なサイト様を参考にさせて頂き プログラムを作成しております。 その結果、下記のようなプログラムで要素名を取得することは出来たのですが、 「属性名」と「属性の値」を読み込み表示することが中々上手くいきません。 どこに何を追加したらよいでしょうか。宜しければ教えて下さい。 -- sample.java -- sample.xml -------------------------------------- import javax.xml.parsers.*; import org.w3c.dom.*; import org.xml.sax.*; import java.io.*; public class sample { public static void main(String[] argv) { sample a = new sample(); a.runner(); } final static String file = "sample.xml"; public void runner() { DocumentBuilderFactory factory; DocumentBuilder builder; Node root; try { factory = DocumentBuilderFactory.newInstance(); builder = factory.newDocumentBuilder(); factory.setIgnoringElementContentWhitespace(true); factory.setIgnoringComments(true); factory.setValidating(true); root = builder.parse(file); showNodes(root, " "); } catch (ParserConfigurationException e0) { System.out.println(e0.getMessage()); } catch (SAXException e1){ System.out.println(e1.getMessage()); } catch (IOException e2) { System.out.println(e2.getMessage()); } } public void showNodes(Node node, String space) { NodeList nodes = node.getChildNodes(); for (int i=0; i<nodes.getLength(); i++) { Node node2 = nodes.item(i); if(!node2.getNodeName().equals("#text")){ System.out.println(space + "<" + node2.getNodeName() + ">"); showNodes(node2, space + " "); } } } }

    • ベストアンサー
    • Java
  • JSのイベントターゲット が難しい

    JSのイベントターゲット (EventTarget)が難しくてよくわからないのですが初心者にもわかるように解説していただけるとありがたいです。 https://developer.mozilla.org/en-US/docs/Web/API/EventTarget イベントターゲット(EventTarget)は、DOMイベントを受け取り、それらへのリスナーを持つことが出来るオブジェクトによって実装されるDOMインターフェースです。 Elementと、 documentと、 windowは、ほとんどの共通イベントターゲットですが、 例えば、XMLHttpRequest、AudioNode、AudioContextなど、 他のオブジェクトもエベントターゲットになることが可能です。 多くのイベントターゲット(Element、document、windowを含む)は、 onXXXプロパティと属性を介して、 イベントハンドラの設定もサポートします。 メソッド .addEventListener() 要素にイベントハンドラを登録します。 .dispatchEvent() DOM内のノードのイベントを実行します。 .removeEventListener() EventTarget.addEventListenerを使用して登録されたイベントリスナーを削除します。 イベントを発動させる要素につけるイベントファンクションのようなものなのでしょうか?

  • Data::XLSX::Parser について

    perlにて.xlsxフォーマットのExcelファイルを読む場合、1万行以上の場合、Spreadsheet::XLSX->new(ファイル名) を用いると1分以上の時間がかかります。 それでより読み込み速度の速い他のCPANモジュールを探していたら、Data::XLSX::Parser を見つけたので、それをインストールして試用することにしました。 それで、このモジュールのドキュメントにあったSYNOPSISの、以下のソースを作成し実行してみました。 use Data::Dumper; use Data::XLSX::Parser; my $parser = Data::XLSX::Parser->new; $parser->add_row_event_handler(sub { my ($row) = @_; print Dumper $row; }); $parser->parse(ファイル名); 実行した結果、 Can't locate object method "parse" via package "Data::XLSX::Parser" at xlsx.pl line "$parser->parse(ファイル名);"の行番 となり実行不可となります。即ち、このモジュールにはparseというメソッドは無いと言っているようです。 この原因は何で、どう対処したら実行可能になるかを教えて頂きたいと思います。 また、このモジュール全般に関する詳細なドキュメントを見つけられていないので、どこにアクセスすればその情報が得られるかも教えて頂きたいと思います。

専門家に質問してみよう