0

私は初めてXML::Twigです。

子タグを子タグに移動する必要があります。

これどうやってするの?

notes親タグと子タグを一致させると、セクションの前に移動します。

私のXMLは次のようになります。

<book>
  <sec>
    <p>The indicated something</p>
    <p>The something</p>
  </sec>
  <sec>
    <notes>note</notes>
    <p>text</p>
  </sec>

  <sec>
    <p>The indicated</p>
    <p>The something</p>
  </sec>
  <sec>
    <notes>note</notes>
    <p>text1</p>
  </sec>

</book>

私は試した:

use XML::Twig;

open(my $output, ">output.xml") || die "can't open the output.xml$!\n";

my $story_file = XML::Twig->new(
    keep_encoding => 1,
    twig_handlers => { 'book' => \&book, },
    pretty_print  => 'indented',
);
$story_file->parse("sample.xml");
$story_file->print($output);
$story_file->purge;

sub book {
    my ($stroy_file, $book) = @_;
    my @sub_elmt = $book->children;
    Get_children(\@sub_elmt) if ($#sub_elmt >= 0);
}

sub Get_children {
    my ($ref) = @_;
    foreach my $tagg (@$ref) {
        my @children = $tagg->children;
        my $tagName  = $tagg->name;
        if ($tagName =~ /^sec$/) {
            my $f = $tagg->first_child;
            if ($f->name =~ /^notes$/) {
                $tagg->move('last_child', $tagg);
            }
        }
        Get_children(\@children) if ($#children >= 0);
    }
}

うまくいかない、どうすればいいの?

次のような出力が必要です。

<book>
  <sec>
    <p>The indicated something</p>
    <p>The something</p>
    <sec>
      <notes>note</notes>
      <p>text</p>
    </sec>
  </sec>
  <sec>
    <p>The indicated</p>
    <p>The something</p>
    <sec>
      <notes>note</notes>
      <p>text1</p>
    </sec>
  </sec>
</book>

どうすればいいですか?

4

2 に答える 2

1

XML::Twigを使用して非常に大きな XML ドキュメントを 1 つずつ処理するのに非常に便利ですがtwig_handlers、そのように使用する必要はありませ。完全な XML ドキュメント ツリーを構築し、他のほとんどの XML モジュールと同様に、そのツリーを操作して出力できます。

このプログラムは、 からドキュメント全体を読み取り、要素内にあるsample.xmlすべての要素を検索します。包含要素は を使用して検出され、前の要素 (これが挿入される) は を使用して検出されます。次に、要素を前の の最後の子として再配置するために使用されます。notessecsecparentsecprev_siblingmovesecsec

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new;
$twig->parsefile('sample.xml');

for my $notes ( $twig->findnodes('//sec/notes') ) {
  my $sec = $notes->parent;
  my $prev_sec = $sec->prev_sibling('sec');
  $sec->move(last_child => $prev_sec);
}

$twig->print_to_file('output.xml', pretty_print => 'indented');

出力

<book>
  <sec>
    <p>The indicated something</p>
    <p>The something</p>
    <sec>
      <notes>note</notes>
      <p>text</p>
    </sec>
  </sec>
  <sec>
    <p>The indicated</p>
    <p>The something</p>
    <sec>
      <notes>note</notes>
      <p>text1</p>
    </sec>
  </sec>
</book>
于 2013-03-21T22:01:38.983 に答える
0

XML と Perl スクリプトの両方にタイプミスがあります。注意。XML の例を修正および整理しました (ノートタグを参照)。

あなたの主な問題は、それ$tagg->moveが(つまり、それ自体!)に移動して$taggいるため、機能しません:(

以下は、必要なことを行う単純化されたバージョンです (つまりbook/sec、最初の子を持つタグが表示されると、これを前の末尾にnotes移動します)、どのように機能するかを示します。secsec->move

use strict;
use warnings;
use XML::Twig; 

my $book_sec = do {
    my $last_sec;
    sub {
        my ($twig, $sec) = @_;

        # if <sec> has first child <notes> then this needs
        # to be moved to end of previous <sec>

        $sec->move( 'last_child', $last_sec ) 
            if $sec->first_child('notes') && $last_sec;

        $last_sec = $sec;   # cache that last <sec>
    };
};

XML::Twig->new(
    twig_handlers => { 'book/sec' => $book_sec },
    pretty_print  => 'indented',
)->parsefile( 'sample.xml' )->print_to_file( 'output.xml' );
于 2013-03-21T15:26:26.693 に答える