如何使用perl / LibXML在DOCTYPE中创建ENTITY引用

时间:2017-06-05 16:21:43

标签: xml perl entity dtd xml-libxml

我试图创建以下包含DTD的实体声明:

<!DOCTYPE LinkSet PUBLIC "-//NLM//DTD LinkOut 1.0//EN" "https://www.ncbi.nlm.nih.gov/projects/linkout/doc/LinkOut.dtd" 
[ <!ENTITY icon.url "https://example.com/icon.png"> 
<!ENTITY base.url "https://example.com/content/" > ]>

我可以成功创建没有实体引用的DOCTYPE

#!/usr/bin/perl -w
use strict;
use XML::LibXML;

my $doc = XML::LibXML::Document->new('1.0','UTF-8');
my $dtd = $doc->createInternalSubset( "LinkSet", "-//NLM//DTD LinkOut 1.0//EN", "https://www.ncbi.nlm.nih.gov/projects/linkout/doc/LinkOut.dtd" );

my $ls = $doc->createElement( "LinkSet" );
$doc->setDocumentElement($ls);

print $doc->toString;
exit;

结果:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE LinkSet PUBLIC "-//NLM//DTD LinkOut 1.0//EN" "https://www.ncbi.nlm.nih.gov/projects/linkout/doc/LinkOut.dtd">
<LinkSet/>

XML::LibXML documentation显示如何向文档添加实体引用,但不显示如何在DOCTYPE中声明实体。

A similar (but PHP-based) question指向将ENTITY引用创建为字符串并解析它。 这也是Perl中最好的方法吗?

1 个答案:

答案 0 :(得分:3)

XML::LibXML::Document的文档 说这个

  

[文档类]继承DOM中指定的XML::LibXML::Node中的所有函数   规格。这样可以访问除根元素之外的节点   在文档级别 - &#34; DTD&#34;例如。对这些节点的支持是   目前有限。

后面也明确指出,这些限制的来源本身是libxml2,而不是Perl模块。这是有道理的,因为DTD与XML(甚至是XML处理指令)的语法完全不同,即使它看起来看起来很相似。

唯一的方法似乎是使用所需的DTD解析基本文档并使用

喜欢这样

use strict;
use warnings 'all';

use XML::LibXML;

my $doc = XML::LibXML->load_xml(string => <<__END_XML__);
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE LinkSet PUBLIC "-//NLM//DTD LinkOut 1.0//EN" "https://www.ncbi.nlm.nih.gov/projects/linkout/doc/LinkOut.dtd" 
[
  <!ENTITY icon.url "https://example.com/icon.png"> 
  <!ENTITY base.url "https://example.com/content/">
]>

<LinkSet/>
__END_XML__

print $doc;

输出

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE LinkSet PUBLIC "-//NLM//DTD LinkOut 1.0//EN" "https://www.ncbi.nlm.nih.gov/projects/linkout/doc/LinkOut.dtd" [
<!ENTITY icon.url "https://example.com/icon.png">
<!ENTITY base.url "https://example.com/content/">
]>
<LinkSet/>