@files = glob "*.xml";
undef $/;
for $file (@files) {
$indent = 0;
open FILE, $file or die "Couldn't open $file for reading: $!";
$_ = readline *FILE;
close FILE or die "Couldn't close $file: $!";
# Remove whitespace between > and < if that is the only thing separating them
s/(?<=>)\s+(?=<)//g;
# Indent
s{ # Capture a tag <$1$2$3>,
# a potential closing slash $1
# the contents $2
# a potential closing slash $3
<(/?)([^/>]+)(/?)>
# Optional white space
\s*
# Optional tag.
# $4 contains either undef, "<" or "</"
(?=(</?))?
}
{
# Adjust the indentation level.
# $3: A <foo/> tag. No alteration to indentation.
# $1: A closing </foo> tag. Drop one indentation level
# else: An opening <foo> tag. Increase one indentation level
$indent +=
$3 ? 0 :
$1 ? -1 :
1;
# Put the captured tag back into place
"<$1$2$3>" .
# Two closing tags in a row. Add a newline and indent the next line
($1 and ($4 eq "</") ?
"\n" . (" " x $indent) :
# This isn't a closing tag but the next tag is. Add a newline and
# indent the next line.
$4 ?
"\n" . (" " x $indent) :
# This isn't a closing tag - no special indentation. I forget why
# this works.
""
)
# /g repeat as necessary
# /e Execute the block of perl code to create replacement text
# /x Allow whitespace and comments in the regex
}gex;
open FILE, ">", $file or die "Couldn't open $file for writing: $!";
print FILE or die "Couldn't write to $file: $!";
close FILE or die "Couldn't close $file: $!";
}
I’m using this code to indent a bunch of xml files correctly. However, when I execute I get:
Use of uninitialized value $4 in string eq at C:/Users/souzamor/workspace/Parser/xmlreformat.pl line 25.
and line 25 is:
# $4 contains either undef, "<" or "</"
I don’t know why is it, and I’m new to Perl. Could someone please help me?
The
$4refers to the fourth capturing parenthesis in your regular expression, in this case:(?=(</?))?. As the comment states this may be undefined because of the?at the very end which means “this thing may be there, but it also might not be”.If you use an undefined value (signalled via the special value
undefin Perl) in certain ways, including in a string comparison witheq, you get a warning from Perl. You can easily check whether or not a variable is defined withdefined($var).In your particular case
$4is used in this phrase:Fixing the warning is as easy as replacing those tests with this:
Note that you don’t have to check for
defined($4)in the second line in this particular case, but it wouldn’t hurt either.