我已经实现了 XmlTextReader,并覆盖了 CheckCharacters 设置。像这样的东西:
class MyXmlTextReader : XmlTextReader
{
public MyXmlTextReader(TextReader input) : base(input)
{
}
/// <summary>
/// Settings
/// </summary>
public override XmlReaderSettings Settings
{
get { return new XmlReaderSettings { CheckCharacters = false }; }
}
}
当我在正常情况下使用它并使用无效的 xml 数据时,一切正常:
var sr3 = new StringReader(xml);
var xr3 = new MyXmlTextReader(sr3);
var obj3 = (MyObject)ser.Deserialize(xr3);
但是一旦我打开标准化,我就开始收到 InvalidCharacter 异常:
var sr3 = new StringReader(xml);
var xr3 = new MyXmlTextReader(sr3);
xr3.Normalization = true;
var obj3 = (MyObject)ser.Deserialize(xr3);
有没有办法进行规范化,但同时忽略无效的 xml 字符?
这是一个重现该问题的示例应用程序: https://gist.github.com/ncksol/29bd6490edd0580c25f7338b417b37d3
这似乎是实施中的一个缺点:
XmlReader
没有 Normalization
属性。XmlReader.Create
允许您将CheckCharacters
作为设置传递,但由于它返回XmlReader
,因此您无法通过它控制标准化。XmlTextReader
(实际上包裹了XmlTextReaderImpl
)有Normalization
,但是没有公共的CheckCharacters
属性,也没有办法接受XmlReaderSettings
。XmlTextReaderImpl
,它完成所有real工作,可以进行规范化和省略字符检查,但由于上述所有原因,没有公共路径来以这种方式配置它。如果你不介意在这种情况下依赖实现,可以通过反射来完成:
var sr3 = new StringReader(xml);
var xr3 = XmlReader.Create(sr3, new XmlReaderSettings { CheckCharacters = false });
// xr3.Normalization is not accessible
xr3.GetType()
.GetProperty("Normalization", BindingFlags.Instance | BindingFlags.NonPublic)
.SetValue(xr3, true);
var obj3 = (MyObject)ser.Deserialize(xr3);
Hacky,但仍然比从头开始实施
XmlTextReader
要好得多,考虑到实施过程中的所有巧妙之处,这并不是一件可以轻易进行的事情。
请注意,
XmlReader.Create
不有义务返回具有 Normalization
属性的类型的实例,它恰好在当前实现中这样做。
您可以使用
XmlTextReader
并将 Normalization
属性设置为 false
。不需要像上面建议的那样进行反思。
参考API备注:XmlTextReader.Normalization属性
如果标准化设置为 false,这也会禁用数字实体的字符范围检查。因此,允许使用字符实体,例如 �。