使 XML::Simple 读取外部 DTD
Make XML::Simple read external DTDs
给定以下两个文件:
doc.xml
<!DOCTYPE TEST [
<!ENTITY % get_em SYSTEM "entities.ent" >
%get_em;
]>
<TEST>
<COMPANY_ID>&COMPANY_ID;</COMPANY_ID>
</TEST>
entities.ent
<!ENTITY COMPANY_ID "84500">
<!ENTITY SPN_FIRM_ID "5900">
<!ENTITY SPN_CUSTD_REL_ID "40001">
<!ENTITY CUSTD_FIRM_NBR "229">
<!ENTITY CUSTD_FIRM_ID "5901">
<!ENTITY MASTERACCOUNT "TAL">
我可以成功使用xmllint
:
xmllint --loaddtd --noent --dropdtd doc.xml
<?xml version="1.0"?>
<TEST>
<COMPANY_ID>84500</COMPANY_ID>
</TEST>
我怎样才能让这个想法在 Perl 和 XML::Simple 中发挥作用?
$ perl -MData::Dumper -MXML::Simple -e 'print Dumper XMLin q{doc.xml}'
doc.xml:4: parser error : PEReference: %get_em; not found
%get_em;
^
doc.xml:9: parser error : Entity 'COMPANY_ID' not defined
<COMPANY_ID>&COMPANY_ID;</COMPANY_ID>
^
经过一些评论,我试过 XML::LibXML::Simple
它看起来确实好一点,但实体仍然没有得到解决
$ perl -MData::Dumper -MXML::LibXML::Simple -e 'print Dumper XMLin q{doc.xml}'
./doc.xml:9: parser error : Entity 'COMPANY_ID' not defined
<COMPANY_ID>&COMPANY_ID;</COMPANY_ID>
^
嗯,上面的 PEReference
很突出.. PE
是什么?
但更重要的是,如何让 Perl 使用 XML::Simple 读取外部 DTD?
我厌倦了 XML::Simple::DTDReader
但我发现这个模块非常有限制,尤其是它指出 specifically XML::Simple
的无数选项中的 none 是支持!
如果我在 doc.xml
本身中包含 ENTITY 声明,它确实有效.. 显然 XML::Simple
知道 如何处理 DOCTYPE
只有我想将外部 DTD 与 SYSTEM
一起使用,这就是我要让它工作的地方。
我仍在寻找这是否可以在 Perl 本身中完成,但一个简单的方法是将我发现的内容与 xmllint and pass as file handle to XMLin
!
结合起来
$ perl -MData::Dumper -MXML::Simple -e 'open my $fh, "xmllint --loaddtd --noent --dropdtd doc.xml |"; print Dumper XMLin $fh'
$VAR1 = {
'COMPANY_ID' => '84500'
};
XML::LibXML默认会展开实体,所以可以使用
$ perl -e'
use Data::Dumper qw( Dumper );
use XML::LibXML qw( );
use XML::Simple qw( XMLin );
my $xml = XML::LibXML->new()->parse_file("doc.xml")->toString();
my $doc = XMLin($xml);
print(Dumper($doc));
'
$VAR1 = {
'COMPANY_ID' => '84500'
};
这也可以通过 XML::LibXML::Simple 覆盖 XML::Simple 兼容性设置来实现。
$ perl -e'
use Data::Dumper qw( Dumper );
use XML::LibXML::Simple qw( XMLin );
my $doc = XMLin("doc.xml",
ParserOpts => {
load_ext_dtd => 1,
ext_ent_handler => undef,
},
);
print(Dumper($doc));
'
$VAR1 = {
'COMPANY_ID' => '84500'
};
给定以下两个文件:
doc.xml
<!DOCTYPE TEST [
<!ENTITY % get_em SYSTEM "entities.ent" >
%get_em;
]>
<TEST>
<COMPANY_ID>&COMPANY_ID;</COMPANY_ID>
</TEST>
entities.ent
<!ENTITY COMPANY_ID "84500">
<!ENTITY SPN_FIRM_ID "5900">
<!ENTITY SPN_CUSTD_REL_ID "40001">
<!ENTITY CUSTD_FIRM_NBR "229">
<!ENTITY CUSTD_FIRM_ID "5901">
<!ENTITY MASTERACCOUNT "TAL">
我可以成功使用xmllint
:
xmllint --loaddtd --noent --dropdtd doc.xml
<?xml version="1.0"?>
<TEST>
<COMPANY_ID>84500</COMPANY_ID>
</TEST>
我怎样才能让这个想法在 Perl 和 XML::Simple 中发挥作用?
$ perl -MData::Dumper -MXML::Simple -e 'print Dumper XMLin q{doc.xml}'
doc.xml:4: parser error : PEReference: %get_em; not found
%get_em;
^
doc.xml:9: parser error : Entity 'COMPANY_ID' not defined
<COMPANY_ID>&COMPANY_ID;</COMPANY_ID>
^
经过一些评论,我试过 XML::LibXML::Simple
它看起来确实好一点,但实体仍然没有得到解决
$ perl -MData::Dumper -MXML::LibXML::Simple -e 'print Dumper XMLin q{doc.xml}'
./doc.xml:9: parser error : Entity 'COMPANY_ID' not defined
<COMPANY_ID>&COMPANY_ID;</COMPANY_ID>
^
嗯,上面的 PEReference
很突出.. PE
是什么?
但更重要的是,如何让 Perl 使用 XML::Simple 读取外部 DTD?
我厌倦了 XML::Simple::DTDReader
但我发现这个模块非常有限制,尤其是它指出 specifically XML::Simple
的无数选项中的 none 是支持!
如果我在 doc.xml
本身中包含 ENTITY 声明,它确实有效.. 显然 XML::Simple
知道 如何处理 DOCTYPE
只有我想将外部 DTD 与 SYSTEM
一起使用,这就是我要让它工作的地方。
我仍在寻找这是否可以在 Perl 本身中完成,但一个简单的方法是将我发现的内容与 xmllint and pass as file handle to XMLin
!
$ perl -MData::Dumper -MXML::Simple -e 'open my $fh, "xmllint --loaddtd --noent --dropdtd doc.xml |"; print Dumper XMLin $fh'
$VAR1 = {
'COMPANY_ID' => '84500'
};
XML::LibXML默认会展开实体,所以可以使用
$ perl -e'
use Data::Dumper qw( Dumper );
use XML::LibXML qw( );
use XML::Simple qw( XMLin );
my $xml = XML::LibXML->new()->parse_file("doc.xml")->toString();
my $doc = XMLin($xml);
print(Dumper($doc));
'
$VAR1 = {
'COMPANY_ID' => '84500'
};
这也可以通过 XML::LibXML::Simple 覆盖 XML::Simple 兼容性设置来实现。
$ perl -e'
use Data::Dumper qw( Dumper );
use XML::LibXML::Simple qw( XMLin );
my $doc = XMLin("doc.xml",
ParserOpts => {
load_ext_dtd => 1,
ext_ent_handler => undef,
},
);
print(Dumper($doc));
'
$VAR1 = {
'COMPANY_ID' => '84500'
};