【问题标题】:Identifying XML declaration in a Perl IF statement识别 Perl IF 语句中的 XML 声明
【发布时间】:2013-08-08 18:38:40
【问题描述】:

我正在尝试将样式表声明添加到我的脚本处理的任何 XML 文件的第二行。我的脚本在循环中将文件逐行读取到 $inputline 字符串中。

我有以下写得很糟糕的 Perl 代码:

while(<INPUT>) {

$inputline = $_;

if ($inputline =~ m/\<\?xml\ version\=\"1\.0\"\ encoding\=\"UTF-8\"\?\>/){

print OUTPUT "\<\?xml version\=\"1.0\" encoding\=\"UTF-8\"\?\>\n";
print OUTPUT "\<\?xml\-stylesheet type\=\"text\/xsl\" href\=\"askaway_transcript_stylesheet\.xsl\"\?\>\n";
}

#lots of other processing stuff
}

我认为这曾经有效,但不再有效。测试不同的输出并进行调整告诉我 IF 语句失败了,我可能在那里做错了。

有什么建议吗?

【问题讨论】:

  • 任何 xml文件?如果是这样,这将只匹配一个 specific xml 标头。关于 XML 的匹配,我推荐你:stackoverflow.com/a/1732454/179216
  • 如果您的输入与此模式有任何偏差,例如,不同的标点符号或中间的空白,您的正则表达式将不匹配。你确定你的输入没有变化吗?
  • U 前面有一个\ 。 Perl 将任何转义的标点视为文字标点字符,并将任何转义的字母视为特殊的正则表达式命令。 \U 将字符串中的以下字符大写。 (实际上,\U 不是正则表达式转义序列,而是双引号字符串转义序列)
  • 现在,标题应该都是一样的。我知道它很死板,但我可以稍后解决。
  • Adrian - 感谢您指出逃脱的 U... 愚蠢的错误。

标签: xml perl


【解决方案1】:

您有一个非常严格的正则表达式来查找 XML 标头。如果有多余的空格怎么办?如果编码不同,或者xml版本不同怎么办?正则表达式不是解析 XML/HTML 的正确工具(请参阅 this answer),但是您可以理解为什么要使用正则表达式,尤其是考虑到您尝试做的事情范围有限。

话虽如此,如果您为了简单起见,并且愿意接受一些可能的失败,我会选择 更简单 正则表达式,并且只替换一次:

my $replaced = 0;
if ($inputline =~ m/\<\?xml\b.*\>/ && !$replaced) {

    print OUTPUT $inputline;
    print OUTPUT '<?xml-stylesheet type="text/xsl" href="askaway_transcript_stylesheet.xsl"?>'."\n";

    $replaced = 1;
}

或者,您可以退出解析循环,假设这是您在循环中所做的一切。

警告:

  • 如果您的 XML 都写在一行上,或者即使在同一行上还有另一个标签(这是合法的),这很可能会破坏您的 XML。

编辑:

您的整个while 循环可能如下所示:

while($inputline = <MYXML>) {
    my $replaced = 0;
    if ($inputline =~ m/\<\?xml\b.*\>/ && !$replaced) {

        print OUTPUT $inputline;
        print OUTPUT '<?xml-stylesheet type="text/xsl" href="askaway_transcript_stylesheet.xsl"?>'."\n";

        $replaced = 1;
    } else {
        print OUTPUT $inputline;
    }
}

或者:

while($inputline = <MYXML>) {
    my $replaced = 0;

    print OUTPUT $inputline;

    if ($inputline =~ m/\<\?xml\b.*\>/ && !$replaced) {
        print OUTPUT '<?xml-stylesheet type="text/xsl" href="askaway_transcript_stylesheet.xsl"?>'."\n";

        $replaced = 1;
    }
}

【讨论】:

  • 谢谢!这种方法似乎有效,但由于某种原因,它仍然在 IF 语句中打印的两个字符串下方打印原始声明。有什么想法吗?
  • 如果你注意到了,我print OUTPUT $inputline;,而不是明确地打印出来。您是否删除了 print OUTPUT "\&lt;\?xml v.... 行?
  • 或者您是否在if 声明之外使用print OUTPUT $inputline;?如果是这样,您需要将其放在 else 块中,或重新排列您的代码。请参阅上面的编辑。
  • 我已经编辑了我的问题以添加更多细节。这一切都发生在一个循环中,在这个循环中我对文本进行了许多不同的处理。 (其他处理工作正常。)没有“print OUTPUT $inputline;”在 IF 语句之外。我已经按照建议尝试了那些修改过的代码,但我仍然在替换后打印了原始声明。
  • 所以你没有在任何地方输出文件的其余部分?你在做print OUTPUT;吗?
猜你喜欢
  • 2022-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-21
  • 2018-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多