嘿,我尝试用官方dtd验证我的html页面:
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(MessageBody));
ms.Position = 0;
XmlReaderSettings settingsReader = new XmlReaderSettings();
settingsReader.DtdProcessing = DtdProcessing.Parse;
settingsReader.ValidationType = ValidationType.DTD;
MyUrlResolver resolver = new MyUrlResolver();
settingsReader.XmlResolver = resolver;
XmlReader reader = XmlReader.Create(ms, settingsReader);
while(reader.Read()){}
和自定义XmlUrlResolver:
class MyUrlResolver : System.Xml.XmlUrlResolver
{
public MyUrlResolver()
{ }
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
if (File.Exists(System.Web.Hosting.HostingEnvironment.MapPath("~/dtd/xhtml11.dtd")))
{
absoluteUri = new Uri(System.Web.Hosting.HostingEnvironment.MapPath("~/dtd/xhtml11.dtd"));
}
return base.GetEntity(absoluteUri, role, ofObjectToReturn);
}
public override Uri ResolveUri(Uri baseUri, string relativeUri)
{
baseUri = new Uri(System.Web.Hosting.HostingEnvironment.MapPath("~"));
relativeUri = "dtd/xhtml11.dtd";
return base.ResolveUri(baseUri, relativeUri);
}
}
Durning读取xml会发生验证,我会遇到异常:
参数实体'xhtml-inlstyle.mod'引用自身。第111行,第21位。
此处出现错误:
<!-- Inline Style Module ........................................ -->
<!ENTITY % xhtml-inlstyle.module "INCLUDE" >
<![%xhtml-inlstyle.module;[
<!ENTITY % xhtml-inlstyle.mod
PUBLIC "-//W3C//ELEMENTS XHTML Inline Style 1.0//EN"
"http://www.w3.org/MarkUp/DTD/xhtml-inlstyle-1.mod" >
%xhtml-inlstyle.mod;]]>
我无法理解为什么官方dtd错了:/我该怎么办?
答案 0 :(得分:2)
唉! DTD可能会不时变得非常复杂。
让我们反汇编你的DTD片段。为清楚起见,我重新包装了行并添加了行号。
1. <!ENTITY % xhtml-inlstyle.module "INCLUDE" >
2. <![%xhtml-inlstyle.module;[
3. <!ENTITY % xhtml-inlstyle.mod PUBLIC "-//W3C//ELEMENTS XHTML Inline Style 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-inlstyle-1.mod" >
4. %xhtml-inlstyle.mod;]]>
在这种形式中,我们可以说第1行有3个是实体声明,第2行和第4行有包含实体引用的文本。
第一行是一个普通的旧文字值实体,我将在第2行添加替换文本代替引用。为了增加清晰度,我将省略第一行,添加一些空格作为缩进和换行。然后我们有:
2. <![INCLUDE[
3. <!ENTITY % xhtml-inlstyle.mod PUBLIC "-//W3C//ELEMENTS XHTML Inline Style 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-inlstyle-1.mod" >
4. %xhtml-inlstyle.mod;
5. ]]>
第2行成为带有INCLUDE
关键字的标记部分声明。第3行中的部分内容是一个实体声明,由于关键字PUBLIC
,实体文本不是文字,而是外部实体声明。这意味着替换文本不是以下引用文本,而是引用文档的内容,该位置由该正式公共标识符和系统标识符(URL)指定。如果你很幸运并且在行末尾的URL不会给你一个超时错误,你会发现这个外部DTD的内容实际上是两个参数实体声明。它们是:<!ENTITY % style.attrib "style CDATA #IMPLIED">
和<!ENTITY % Core.extra.attrib "%style.attrib;" >
。通过扩展第4行的实体引用,您的原始DTD技术上会产生此DTD片段:
<![INCLUDE[
<!ENTITY % style.attrib "style CDATA #IMPLIED">
<!ENTITY % Core.extra.attrib "%style.attrib;" >
]]>
这对我来说看起来并不太错误,但同行评审当然是值得赞赏的。因此,下一个问题是:为什么会出现错误,导致错误的原因是什么?
我想到了一些可能性:
您处理的语法是否正确且与此处显示的语法相同?如果第二个实体声明的末尾缺少>
字符,则在引用相同实体之前不会终止它(在第4行)。解析声明只有在单行写入时才有效吗?尝试重新包装它。解析器是否理解除具有字面值的实体声明之外的任何其他实体声明?尝试使用公共标识符创建类似的实体声明,但不要先引用它。问题可能是由您的(公共/系统)标识符的解析方式引起的吗?您是否有DTD目录,是否通过网络将可能的DTD查找重定向到本地副本,如果将URL更改为本地文件(或者不太可能超时的地方)会发生什么情况等等。{{{ 1}}实体声明周围的声明导致它失败?尝试将其移到INCLUDE
声明之上,以便它也远远超过实体引用。 INCLUDE
是否正常工作,尝试使用我的上一个DTD代码段也会导致错误。
我要以坏消息结束这篇文章。如果这个问题不是关于某些人为错误,例如您的真实DTD文件中放错位置或丢失字符,或者这与检索外部DTD资源的方式无关,那么我猜这个问题是由错误/不支持的功能引起的在您的解析器上(可能不会很快修复)或者然后(尽管错误明确指向DTD文件)这是由您的C#代码中的某些内容引起的,并且与其他人相比,我对此没有任何线索并且可以'帮你进一步。无论如何快乐的调试!
答案 1 :(得分:2)
您可以对xhtml11-flat.dtd进行验证,xhtml11.dtd是的聚合以及 xhtml11.dtd 引用的所有 * .mod 文件。
这样做,你应该调整你的自定义&#39; MyUrlResolver&#39;上课一点点回归&#39; xhtml11-flat.dtd&#39;而不是&#39; xhtml11.dtd&#39;。
答案 2 :(得分:0)
我的解决方案是下载xhtml11.dtd以及所有引用dtd的* .mod文件。然后我在dtd中删除http链接
<!ENTITY % xhtml-datatypes.module "INCLUDE" >
<![%xhtml-datatypes.module;[
<!ENTITY % xhtml-datatypes.mod
PUBLIC "-//W3C//ENTITIES XHTML Datatypes 1.0//EN"
"xhtml-datatypes-1.mod" >
%xhtml-datatypes.mod;]]>
现在dtd在验证期间html页面可以使用本地dtd而无需从www下载;)