use strict; my $text=q| <table > <column a = "1" g='"ab"' b = "2" > <type t="long"> long</type> mixed feeling a="b" last line </column> <column/> </table> |; parse($text); sub parse { my $line=shift; my $level=0; my $ai=0; #0- not inside the element start, 1 - inside element start while(1) { #/> if ($line =~ /\G\s*\/\s*>\s*/gc) { print "/>"; $ai=0; $level--; #print "\nLevel=$level\n"; next; } #> if ($line =~ /\G\s*>\s*/gc) { print ">"; $ai=0; next; } #<element if ($line =~ /\G\s*<\s*(\w+)\s*/gc) { margin($level); print "<$1"; $level++; #print "\nLevel=$level\n"; $ai=1; next; } #</element> if ($line =~ /\G\s*<\s*\/\s*(\w+)\s*>\s*/gc) { $level--; margin($level); print "</$1>"; # print "\nLevel=$level\n"; $ai=0; next; } if ($ai) { #a="value" if ($line =~ /\G(\w+)\s*=\s*(\"[^\"]+\")\s*/gc) { print " $1=$2"; next; } #a='value' if ($line =~ /\G(\w+)\s*=\s*(\'[^\']+\')\s*/gc) { print " $1=$2"; next; } print "Nothing should be here\n"; } #newline if ($line =~ /\G\n/gc) { print "\n"; next; } #everything else if ($line =~ /\G(.)/gc) { print "$1"; next; } last; } } sub seeLevel { my $level=shift; print "\nLevel=$level\n"; } sub margin { my $level=shift; print "\n"; if ($level <0) { return; } else { print " " x $level; } }