1

我有以下Perl脚本用于XML正确缩进文件:

@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 defined($4) and ($4 eq "</") ? "\n" . ("  " x $indent) : 
$4                                   ? "\n" . ("  " x $indent) :
                                       ""
        )
    # /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: $!";
}

首先,它缩进了 my tabs,我想要两个空格。此外,它在同一缩进中生成标签,使其位于同一行,而不是下一行,但具有相同的缩进:

<?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE kit SYSTEM "tc.dtd"><kit><contact/><description>

它应该在哪里:

  <?xml version="1.0" encoding="iso-8859-1"?>
  <!DOCTYPE kit SYSTEM "tc.dtd">
  <kit>
      <contact/>
      <description>

...

我承认有用于缩进的 Perl 工具XML,例如XML-Tidy但由于tc.dtd标记,我总是收到一个错误,抱怨tc.dtd文件上无法解决的依赖关系,而我只关心相同(格式)的缩进,而不是依赖关系本身。我的Perl正则表达式有什么问题?

4

2 回答 2

2

您可以使用不一定验证的工具xmllint 。例子:

输入(格式错误):

<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE kit SYSTEM "tc.dtd"> <kit>
  <contact/>      <description>chunky bacon</description> </kit>

运行xmllint --format file.xml,你会得到:

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE kit SYSTEM "tc.dtd">
<kit>
  <contact/>
  <description>chunky bacon</description>
</kit>
于 2012-08-27T13:40:15.223 回答
2

您必须始终 处于每个程序use strict的顶部。这尤其适用于您在代码方面寻求帮助的情况,因为这些措施可以捕捉到原本会被忽略的简单错误use warnings

也请使用词法文件句柄,你有太多的注释让你的代码变得清晰

您的代码可能会失败,因为它没有考虑标签已经缩进的深度:它只是在任何两个连续标签之前添加空格。请特别注意这" " x -1不起作用,具有 PCDATA(文本)内容的元素将被简单地忽略并保留在其当前缩进处

格式化 XML 并不像您希望的那么简单。您应该听取每个人的建议并使用现有模块来格式化您的数据。两者XML::LibXML都有XML::Twig格式选项。是的,他们需要访问相应的 DTD,但这是一件好事

于 2012-08-27T14:14:14.343 回答