【问题标题】:Automatically detecting XML or plain text input with file and STDIN with Perl使用 Perl 自动检测带有文件和 STDIN 的 XML 或纯文本输入
【发布时间】:2017-01-21 17:39:34
【问题描述】:

用 Perl(5.18 或更高版本)检测 XML(使用 XML::LibXML / libxml2)或纯文本输入的最 Perly 方法是什么?

我有一个程序可以接受纯文本输入或 XML 输入,并且 XML 输入可以是任意编码。输入来自文件 (ARGV) 或 STDIN。当只考虑纯文本时,下面的代码就足够了:

local $/ = undef;
my $text = <> || die;

这将使用默认编码设置获取整个输入文件或 STDIN 作为文本。

仅考虑 XML 时,以下代码可用(用于文件):

my $parser = XML::LibXML->new();
my $xml = $parser->load_xml(location => $ARGV[0]);

但是将两者结合起来的最佳方法是什么?我希望 libxml2 对输入进行第一次破解,如果失败则回退到纯文本。如果我直接传递 IO => *STDIN,libxml2 将使用输入,如果 libxml2 确定输入不是 XML,程序稍后将需要它。

(注意:如果 libxml2 确定输入是某种 XML 但格式不正确,那么程序应该终止而不是回退。)

【问题讨论】:

  • 如何知道包含&lt;doc/&gt;的文件是XML文件还是纯文本文件?两者都可以。
  • nwellnhof,这是一个很好的观点。我的回答是您设计代码以一种或另一种方式回答问题。特别是:&lt;doc/&gt; 是一个 XML 文件,因为 XML 不必以 &lt;?xml version="1.0"?&gt; 开头:您可以直接进入第一个元素。您还可以将字节顺序标记作为第一个字符。更一般的一点是,我希望 libxml2 对输入进行第一次破解,然后在(libxml2 解析)失败时回退到纯文本。根据一些测试,libxml2 也会接受根元素前后的空格。

标签: perl stdin libxml2


【解决方案1】:
use XML::LibXML;

my $schema_file = 'test.xsd';
my $document    = 'test.xml';

my $schema = XML::LibXML::Schema->new(location => $schema_file);

my $parser = XML::LibXML->new;
my $doc    = $parser->parse_file($document); #Or handle STDIN

eval { $schema->validate($doc) };
if ($@){
    #file failed to validate, handle as text below
}

或者,您可以使用Text::XMLis_xmlis_well_formed_xml 方法并基于这些方法创建条件。

【讨论】:

  • 对不起,但实际上不是我要找的。我不想验证 XML;我正在寻找确定输入是否为 XML(任何编码)。例如,它可以以 &lt;?xml version="1.0"?&gt; 开头,或者 UTF-8 BOM 0xEF,0xBB,0xBF 后跟 ,或者带有或不带有 BOM 的 UTF-16BE,甚至是 EBCDIC。我想将字节从 STDIN 直接传递到 libxml2,但是如果 libxml2 说它不是 XML,则保留字节以尝试将流作为纯文本处理。
猜你喜欢
  • 2012-04-24
  • 2011-07-25
  • 2015-01-20
  • 2015-02-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多