2

たとえば、入力は

    root
    ^^aa
    ^^^^bb
    ^^cc
    ^^dd

2 つの ^^ はインデントを表すため、aa はルートの子、bb は aa の子です。
aa、cc、および dd は兄弟であり、すべて root の子です。

出力はxmlファイルで、その内容は

<?xml version='1.0'?>
<dir name="root">
  <dir name="aa">
    <dir name="bb" />
  </dir>
  <dir name="cc" />
  <dir name="dd" />
</dir>

しかし、この問題を解決する適切な perl スクリプトが見つかりません。
ヘルプを検索してください。どうもありがとうございました。

4

2 に答える 2

1

このタスクにXML::LibXMLを使用することもできます。次のように、前のレベルと前の要素についてのみ知る必要があります。

use XML::LibXML;

my $doc = XML::LibXML::Document->new();
my $previousLevel = 0;
my $previousElement;

foreach my $line (@data) {
    if($line =~ m/^(\^*)(.+)$/) {
        my $level = (length $1) / 2;
        my $name = $2;

        my $dir = $doc->createElement('dir');
        $dir->setAttribute('name', $name);

        if($level == 0) {
            $doc->setDocumentElement($dir);
        }
        elsif($level > $previousLevel) {
            $previousElement->addChild($dir);
        }
        elsif($level < $previousLevel) {
            $previousElement = $previousElement->parentNode()
               for ($level .. $previousLevel -1);
            $previousElement->addSibling($dir);
        }
        elsif($level == $previousLevel) {
            $previousElement->addSibling($dir);
        }

        $previousElement = $dir;
        $previousLevel = $level;
    }
}

print $doc->toString(2);
于 2012-06-29T20:06:50.883 に答える
-1

現在のノードの深さと前のノードの深さを比較することで、必要なすべての情報が得られます。

my $last_depth = -1;
while (@input) {
   my $name = shift(@input);

   my $depth = 0;
   ++$depth while $name =~ s/^\^\^//;

   while ($depth <= $last_depth) {
      end_dir($last_depth);
      --$last_depth;
   }

   die if $depth != $last_depth + 1;

   start_dir($depth, $name);
   ++$last_depth;
}

while ($last_depth > -1) {
   end_dir($last_depth);
   --$last_depth;
}

プログラムの残り

my %escapes = (
   '&' => '&amp;',
   '<' => '&lt;',
   '>' => '&gt;',
   '"' => '&quot;',
   "'" => '&apos;',
);

sub text_to_xml {
   my ($s) = @_;
   $s =~ s/([&<>'"])/$escapes{$1}/g;
   return $s;
}

sub start_dir { print(('  ' x $_[0]) . qq{<dir name="}.text_to_xml($_[1]).qq{">\n}); }
sub end_dir   { print(('  ' x $_[0]) . qq{</dir>\n}); }

my @input = split /\n/, <<'__EOI__';
root
^^aa
^^^^bb
^^cc
^^dd
__EOI__

binmode(STDOUT, ':encoding(UTF-8)');
print(qq{<?xml version="1.0"?>\n});
于 2012-06-29T18:30:24.093 に答える