有没有办法让 XML::Twig 理解 UTF-16 编码的 XML 文件?

Is there a way to get XML::Twig to understand a UTF-16-encoded XML file?

有没有办法让 XML::Twig 理解 UTF-16 编码的 XML 文件?

读取文件的代码就是教程里说的:

use warnings;
use strict;

use XML::Twig;

# ...

my $twig=XML::Twig->new(
  twig_handlers => { ... },
  prety_print => 'indented',
  keep_encoding => 1,
};

# ...

$twig->parsefile('myXmlFile.xml');  # <= line 71

错误是:

error parsing tag '<RIBBON>' at /usr/lib/perl5/vendor_perl/5.14/x86_64-cygwin-threads/XML/Parser/Expat.pm line 470
 at ../../cv32/res/convert-xml-string2.pl line 71
 at ../../cv32/res/convert-xml-string2.pl line 71

XML 是这样开始的:

<?xml version="1.0" encoding="utf-16"?>

按照 Borodin 的建议更改我的打开代码,它仍然不起作用:

# parse the XML file
open(my $xmlIn, '<:encoding(UTF-16)', $xmlFile) or die "Couldn't open xml file '$xmlFile'. $!";
$twig->parse($xmlIn); # <= line 72

错误变为:

encoding specified in XML declaration is incorrect at line 1, column 30, byte 30 at /usr/lib/perl5/vendor_perl/5.14/x86_64-cygwin-threads/XML/Parser.pm line 187
 at ../../cv32/res/convert-xml-string2.pl line 72

您的问题很不清楚,并且您没有显示 为您工作的 Perl 代码示例。所以我不得不做出很多猜测,而且真的是在黑暗中工作;但我希望这会有所帮助。

XML::Twig subclasses XML::Parser,提供了parse方法。文档说这个

parse(SOURCE [, OPT => OPT_VALUE [...]])
    The SOURCE parameter should either be a string containing the whole
    XML document, or it should be an open IO::Handle.

这意味着您可以按自己的方式调用 open,并将文件句柄传递给 XML::Twig->parse 方法。您的代码应如下所示

my $file_name = 'my_file.xml';

open my $xml_fh, '<:encoding(UTF-16)', $file_name
    or die qq{Unable to open "$file_name" for input: $!};

my $twig = XML::Twig->new;
$twig->parse($xml_fh);

显然,XML::Twig (XML::Parser) 使用的 XML 解析器不支持 UTF-16。您需要先将 XML 文档转换为支持的编码(例如 UTF-8)。

例如,

use XML::LibXML qw( );

my $xml;
{
   open(my $fh, '<:raw', $qfn)
      or die $!;
   local $/;
   $xml = <$fh>;
}

{
   my $doc = XML::LibXML->new()->parse_string($xml);
   $doc->setEncoding('UTF-8');
   $xml = $doc->toString();
}

$twig->parse($xml);

一个更简单的解决方案是 detect/expect UTF-16,解码文档(使用 Encode 的 decode),使用正则表达式调整编码声明,然后编码文档(使用 Encodes encode).