【问题标题】:XML Deserialization failing on DocType tagDocType 标记上的 XML 反序列化失败
【发布时间】:2013-01-05 01:27:29
【问题描述】:

我正在与向我们发送 XML 消息的第三方应用程序集成。他们的 XML 看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE theirObj SYSTEM "theirDTD-2.0.dtd">
<theirObj>
    <properties>
        <datasource>ThirdParty</datasource>
        <datetime>2009-03-05T14:45:39</datetime>
    </properties>
        <data>
          ...
        </data>
</theirObj>

我正在尝试使用 XmlSerializer 对其进行反序列化:

public theirObj Deserialize(string message) {
            if( string.IsNullOrWhiteSpace( message ) ) {
                throw new ArgumentNullException( "message" );
            }
            XmlSerializer xmlSerializer = new XmlSerializer( typeof(theirObj ) );

            TextReader textReader = new StringReader( message );

            using (XmlReader xmlReader = new XmlTextReader( textReader )) {
                object deserializedObject = xmlSerializer.Deserialize( xmlReader );

                theirObj ent = deserializedObject as theirObj ;

                if (ent == null) {
                    throw new InvalidCastException("Unable to cast deserialized object to an theirObj object. {0}".FormatInvariant( deserializedObject));
                }

                return ent;
            }
        }
}

我使用 xsd.exe 生成了对象。

如果我删除 &lt;!DOCTYPE&gt; 标记,那么它可以很好地反序列化。

有没有办法让 XmlSerializer 忽略 &lt;!DOCTYPE&gt; 标记?

我知道我可以在将它传递给 XmlSerializer 之前将其删除,但如果我不需要,我宁愿不去那个级别的 XML 操作。

【问题讨论】:

  • 去看看这个链接,它对我有用。 Solution

标签: c# doctype xmlserializer


【解决方案1】:

不使用XmlTextReader,而是调用XmlReader.Create 并将XmlReaderSettings 对象传递给它,并将DtdProcessing 设置为Ignore

TextReader textReader = new StringReader( message );
var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore };

using (XmlReader xmlReader = XmlReader.Create(textReader, settings))

注意:DtdProcessing 属性是在 .NET 4.0 中添加的。在 .NET 3.5 中,您可以改为将 ProhibitDtd 设置为 false 并将 XmlResolver 设置为 null

var settings = new XmlReaderSettings { ProhibitDtd = false, XmlResolver = null };

【讨论】:

  • 完美!这就像一个魅力。我害怕不得不把标签去掉(感觉太像黑客了)。
【解决方案2】:

DOCTYPE 没有内置的 XmlSerlization 属性。事实上,这是因为 XML 序列化是基于元素而不是基于文档的。我认为您可以使用以下方法在序列化中跳过 DOCTYPE:

public static String Serialize(object obj)
{
    StringBuilder builder = new StringBuilder();
    XmlSerializer serializer = new XmlSerializer(typeof(theirObj));

    using (XmlWriter writer = XmlWriter.Create(builder, new XmlWriterSettings() { OmitXmlDeclaration = true }))
        xmlSerializer.Serialize(writer, obj);

    return builder.ToString();
}

然后,在文档被反序列化后将其注入回去。

【讨论】:

    【解决方案3】:

    您可以删除文档类型

    TextReader textReader = new StringReader( message );
    XmlDocument XDoc = new XmlDocument();
    XDoc.Load(textReader);
    XmlDocumentType XDType = XDoc.DocumentType;
    XDoc.RemoveChild(XDType);
    
    using (XmlReader xmlReader = new XmlTextReader(XDoc)) {
                    object deserializedObject = xmlSerializer.Deserialize( xmlReader );
    
                    theirObj ent = deserializedObject as theirObj ;
    
                    if (ent == null) {
                        throw new InvalidCastException("Unable to cast deserialized object to an theirObj object. {0}".FormatInvariant( deserializedObject));
                    }
    
                    return ent;
                }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 2012-12-26
      • 2021-04-07
      • 2017-09-24
      • 2021-08-20
      • 1970-01-01
      • 2019-09-28
      相关资源
      最近更新 更多