同一文件夹外部DTD无法解析,报‘entity not defined’错误求助
本地外部DTD实体无法展开:解析报错但验证通过
问题场景
同一目录下的XML与DTD文件,XML通过相对路径引用DTD,但DTD中定义的实体&writer;无法被展开。使用xmlstarlet fo格式化XML时报错,Firefox中打开也无法正常解析实体,但xmlstarlet val -d验证XML与DTD的有效性时显示结果为有效。
相关文件
tutorials.xml
<?xml version="1.0" standalone="no"?> <!DOCTYPE tutorials SYSTEM "tutorials.dtd"> <tutorials type="web"> <tutorial> <name>XML Tutorial</name> <url>https://www.quackit.com/xml/tutorial</url> <author>&writer;</author> </tutorial> <tutorial> <name>HTML Tutorial</name> <url>https://www.quackit.com/html/tutorial</url> <author>&writer;</author> </tutorial> </tutorials>
tutorials.dtd
<!ELEMENT tutorials (tutorial)+> <!ATTLIST tutorials type CDATA #REQUIRED> <!ELEMENT tutorial (name,url,author)> <!ELEMENT name (#PCDATA)> <!ELEMENT url (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ENTITY writer "Site by Donald Duck">
错误与验证信息
- 格式化报错:
$ xmlstarlet fo tutorials.xml > tutorials.xml:7.21: Entity 'writer' not defined
- 验证结果:
$ xmlstarlet val -d tutorials.dtd tutorials.xml > tutorials.xml - valid
原因分析
- xmlstarlet
fo命令默认行为:fo(format)命令默认仅做XML语法校验和格式化,不会主动加载外部DTD来解析实体引用,因此无法识别&writer;的定义。而val -d是显式指定DTD进行有效性验证,所以能正确识别实体定义。 - Firefox安全策略:Firefox默认禁用外部实体加载,防止实体注入类的安全风险,因此无法解析外部DTD中的实体。
解决方案
1. 让xmlstarlet加载DTD展开实体
执行xmlstarlet fo时添加--dtd参数,强制加载外部DTD并解析实体:
xmlstarlet fo --dtd tutorials.xml
2. 调整Firefox配置(仅本地测试用)
若需在Firefox中查看效果,需修改浏览器安全配置(不建议在非测试环境使用):
- 地址栏输入
about:config,确认风险提示 - 找到
security.fileuri.strict_origin_policy,设置为false - 找到
xml.external_entity.enabled,设置为true
3. 将实体定义移至XML内部
如果不想依赖外部DTD,可把DTD的定义直接嵌入XML的DOCTYPE声明中:
<?xml version="1.0" standalone="no"?> <!DOCTYPE tutorials [ <!ELEMENT tutorials (tutorial)+> <!ATTLIST tutorials type CDATA #REQUIRED> <!ELEMENT tutorial (name,url,author)> <!ELEMENT name (#PCDATA)> <!ELEMENT url (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ENTITY writer "Site by Donald Duck"> ]> <tutorials type="web"> <tutorial> <name>XML Tutorial</name> <url>https://www.quackit.com/xml/tutorial</url> <author>&writer;</author> </tutorial> <tutorial> <name>HTML Tutorial</name> <url>https://www.quackit.com/html/tutorial</url> <author>&writer;</author> </tutorial> </tutorials>
内容的提问来源于stack exchange,提问作者Nils Deschrijver
相关产品推荐
相关产品推荐

