1#!/usr/bin/perl 2# 4.9.2009, Sampo Kellomaki (sampo@iki.fi) 3# $Id: xml-pretty.pl,v 1.1 2009-09-05 02:23:41 sampo Exp $ 4# 5# Pretty Print XML -- Make XML almost human readable 6# 7# Usage: cat foo.saml | ./zxdecode | ./xml-pretty.pl 8# tailf /var/zxid/log/xml.dbg | ./xml-pretty.pl 9use Data::Dumper; 10 11$ascii = 2; 12 13# See https://wiki.archlinux.org/index.php/Color_Bash_Prompt 14sub red { $ascii > 1 ? "\e[1;31m$_[0]\e[0m" : $_[0]; } # red text 15#sub green { $ascii > 1 ? "\e[1;32m$_[0]\e[0m" : $_[0]; } 16#sub red { $ascii > 1 ? "\e[1;41m$_[0]\e[0m" : $_[0]; } # red background, black bold text 17sub green { $ascii > 1 ? "\e[1;42m$_[0]\e[0m" : $_[0]; } 18sub redy { $ascii > 1 ? "\e[41m$_[0]\e[0m" : $_[0]; } # red background, black text (no bold) 19sub greeny { $ascii > 1 ? "\e[42m$_[0]\e[0m" : $_[0]; } 20sub yely { $ascii > 1 ? "\e[43m$_[0]\e[0m" : $_[0]; } 21sub bluy { $ascii > 1 ? "\e[46m$_[0]\e[0m" : $_[0]; } 22 23$indent = ''; 24 25sub xml_pretty { 26 my $res = ''; 27 my ($x,$at,$noindent); 28 #warn "start res($res) indent($indent) data($_[0])"; # tail dup seems perl error 29 for $x (split /(<\/?\w.*?>)/, $_[0]) { 30 next if !length $x; 31 #print "*"; 32 if ($x !~ /^</) { 33 $last_tag = undef; 34 if (length $x < 40) { 35 if ($x =~ /^\s*$/s) { 36 #$res .= "\n"; 37 #warn "HERE1($x)"; 38 } else { 39 #warn "HERE3($x)"; 40 chomp $res; 41 $res .= green($x); 42 } 43 $noindent = 1; 44 } else { 45 my $xx = $x; 46 chomp $xx; 47 if ($xx =~ /^\s*$/s) { 48 $res .= "\n"; 49 #warn "HERE($xx)"; 50 } else { 51 #warn "HERE2($xx)"; 52 $res .= $indent.greeny($xx)."\n"; 53 } 54 } 55 next; 56 } 57 if ($x =~ /^<!--/) { 58 $last_tag = undef; 59 $x =~ s/\e\[\d+m//g; 60 $res .= bluy($x)."\n"; 61 $indent = ''; 62 next; 63 } 64 if ($x =~ /^<\?/) { 65 $last_tag = undef; 66 $res .= "$indent$x\n"; 67 next; 68 } 69 if ($x =~ /^<\//) { # close tag 70 substr($indent,-2) = ''; 71 $rx = red($x); 72 if ($noindent) { 73 $res .= "</>"; 74 } else { 75 $xx = substr($x,2,-1); 76 #warn " x($xx) indent($indent)\nlast_tag($last_tag) last_indent($last_indent)"; 77 if ($xx eq $last_tag && $indent eq $last_indent) { 78 die "Res does not end in > res($res)" if substr($res,-2) ne ">\n"; 79 chop $res; 80 chop $res; 81 $res .= "/>\n"; 82 } else { 83 $res .= "$indent$rx\n"; 84 } 85 } 86 $last_tag = undef; 87 next; 88 } 89 if ($noindent) { 90 $noindent = 0; 91 $res .= "\n"; 92 } 93 # 1 12 3 32 4 4 94 if ($x =~ /^<([A-Za-z0-9_:-]+)(\s+(.*?))?(\/)?>$/) { 95 $last_tag = $1; 96 $last_indent = $indent; 97 $res .= "$indent<".red($1); 98 my @ats = split / /, $3; 99 if ($#ats == 0) { 100 my ($name,$val) = split /=/, $ats[0], 2; 101 $res .= " $name=".yely($val); 102 } else { 103 for $at (@ats) { 104 my ($name,$val) = split /=/, $at, 2; 105 $res .= "\n$indent $name=".yely($val); 106 } 107 } 108 if ($4) { 109 $res .= "/>\n"; 110 $last_tag = undef; 111 } else { 112 $res .= ">\n"; 113 $indent .= ' '; 114 } 115 } else { 116 die "unprocessable start tag($x) (tag must be completely on one line)"; 117 } 118 } 119 return $res; 120} 121 122while (defined($line = <STDIN>)) { 123 #$line =~ tr[\r][]; 124 print xml_pretty($line); 125} 126 127__END__ 128