找到了使用 XMLReader 实例读取 XHTML 源代码的答案,该源代码包含命名实体,如   而不会抛出 XmlException
首先,我直接从 W3C 的页面复制了以下 XML 示例:XML Schema 中的 XHTML 1.0,1.5. Using DTD and XML Schema together 部分以支持引入命名实体字符并同时进行基于模式的验证:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"[
<!ATTLIST html
xmlns:xsi CDATA #FIXED "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation CDATA #IMPLIED
>
]>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/1999/xhtml
http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd">
...
</html>
并且是 替换 XHTML 片段,例如<body><div><b>xhtml stuff</b></div></body> 到上面示例中... 的位置。
这成功地将 DTD(引用命名实体)与架构验证混合在一起。遇到命名实体时,XMLReader 不再抛出 XMLExeption。
成功!
处理上述示例的C#.NET 代码
using System;
using System.IO;
using System.Xml;
核心逻辑如下。 注意:这是逐字复制和粘贴的。一些设置可能是轻率或多余的,因此您可以调整以实现其他各种里程。
XmlReaderSettings settingsXRdr = new XmlReaderSettings();
settingsXRdr.ProhibitDtd = false;
settingsXRdr.CheckCharacters = true;
settingsXRdr.ConformanceLevel = ConformanceLevel.Document;
settingsXRdr.IgnoreProcessingInstructions = false;
settingsXRdr.IgnoreComments = false;
settingsXRdr.XmlResolver = new CustomXmlResolver();
settingsXRdr.ValidationType = ValidationType.DTD;
// This is a format string; notice the placeholder {0} where the fragment will be injected:
string mixFmtString1 = @"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Strict//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd""[
<!ATTLIST html
xmlns:xsi CDATA #FIXED ""http://www.w3.org/2001/XMLSchema-instance""
xsi:schemaLocation CDATA #IMPLIED
>
]>
<html xmlns=""http://www.w3.org/1999/xhtml"" lang=""en"" xml:lang=""en""
xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xsi:schemaLocation=""http://www.w3.org/1999/xhtml
http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd"">
<head><title></title></head>
<body>
<div>{0}</div>
</body>
</html>";
// Inject any well-formed fragment via the second argument
string xhtml = string.Format(mixFmtString1, "<b>Xhtml fragment w/named entity: </b>");
// Creates a validating reader (derived type) because of the above settings)
XmlReader rdr = XmlReader.Create(new StringReader(xhtml), settingsXRdr);
// Reads the entire XHTML document (validating it along the way).
while (rdr.Read()) {
// Do whatever you want here for each piece processed.
var dummy = rdr.NodeType.ToString(); // Access a string value for fun.
// If you just want validation to occur then leave this an empty code block.
}
注意:此解决方案对 XHTML 使用 Strict 模板,因此某些已弃用的标签(如 <center>)将使阅读器失败。您可能希望重新定义引用的项目以指向更宽容的loose XHTML template。
沿途相关/有用的资源: