当规范化开启时,XmlTextReader 会忽略 CheckCharacters=false

问题描述 投票:0回答:2

我已经实现了 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

c# xml
2个回答
2
投票

这似乎是实施中的一个缺点:

  • 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
属性的类型的实例,它恰好在当前实现中这样做。


0
投票

您可以使用

XmlTextReader
并将
Normalization
属性设置为
false
。不需要像上面建议的那样进行反思。

参考API备注:XmlTextReader.Normalization属性

如果标准化设置为 false,这也会禁用数字实体的字符范围检查。因此,允许使用字符实体,例如 �。

© www.soinside.com 2019 - 2024. All rights reserved.