2015-12-30 36 views
0

考慮到以下兩個文件:使XML ::簡單的讀外部的DTD

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? 但更重要的是,我如何才能使用XML :: Simple來讀取外部DTD的Perl?

我累XML::Simple::DTDReader但我覺得這個模塊非常嚴格尤其是它指出specifically沒有的選項XML::Simple的無數的支持

如果我包括在doc.xml本身,它的工作的實體聲明..所以顯然XML::Simple知道如何處理DOCTYPE只有我想用外部DTD與SYSTEM,而這也正是我堅持讓它工作。

+4

爲什麼不使用一個體面的解析器呢? – ikegami

+0

@ikegami我正在處理的特定XML Configs是* simple *!我在當前設置中發現的唯一複雜性是存在許多相同基本XML的副本,並且只有一些變量正在改變。它保持簡單的精神,我希望通過使用XML ENTITY引用來介紹變量的概念,並且我希望將它們包含在「SYSTEM」中,謝謝 – lzc

+2

這與我的問題有什麼關係?如果你想簡單一些,然後運行,[遠離XML :: Simple運行](http://stackoverflow.com/q/33267765/589924)。 – ikegami

回答

1

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實現::簡單通過重寫XML ::簡單兼容性設置。

$ 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' 
     }; 
+0

不錯!它工作'perl -MData :: Dumper -MXML :: LibXML :: Simple -e'print Dumper XMLin(q {doc.xml},ParserOpts => {load_ext_dtd => 1,ext_ent_handler => undef})''謝謝 – lzc

+0

是的,除了你說你必須使用XML :: Simple ...這是可能的解決方案的更糟。您不僅不使用XML :: Simple,而且迫使另一個解析器產生與XML :: Simple相同的錯誤輸出 – ikegami

0

我還在尋找如果這可以在Perl本身內完成,但一個簡單的方法將結合我發現與xmllint並作爲文件句柄傳遞到XMLin

$ perl -MData::Dumper -MXML::Simple -e 'open my $fh, "xmllint --loaddtd --noent --dropdtd doc.xml |"; print Dumper XMLin $fh' 
$VAR1 = { 
      'COMPANY_ID' => '84500' 
     };