XML 反序列化在 DocType 标记上失败
本文关键字:失败 DocType 反序列化 XML | 更新日期: 2023-09-27 17:55:19
我正在与向我们发送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 生成了对象。
如果我删除 <!DOCTYPE>
标签,那么它可以很好地反序列化。
有没有办法让 XmlSerializer 忽略 <!DOCTYPE>
标记?
我知道我可以在传递 XmlSerializer 之前将其剥离,但如果没有必要,我宁愿不进行该级别的 XML 操作。
不使用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 };
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();
}
然后,在反序列化文档后将其注入回去。
您可以删除文档类型
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;
}