我尝试使用C#将XML反序列化为对象,但出现一些错误。
我的XML文件是:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:transmission xmlns:ns0="blabla.xsd">
<ns0:DiagnosisErrorResponse>
<ns0:ID>7</ns0:ID>
<ns0:ErrorCode>9</ns0:ErrorCode>
<ns0:ErrorDescription>sometext</ns0:ErrorDescription>
<ns0:ErrorDate>11-12-2018</ns0:ErrorDate>
</ns0:DiagnosisErrorResponse>
</ns0:transmission>
我有一个这样的实体:
[XmlRoot(Namespace = "blabla.xsd", ElementName = "ns0:transmission", DataType = "string", IsNullable = true)]
public class DiagnosisErrorResponse
{
[XmlElement("ID")]
public long ID { get; set; }
[XmlElement("ErrorCode")]
public int ErrorCode { get; set; }
[XmlElement("ErrorDescription")]
public string ErrorDescription { get; set; }
[XmlElement("ErrorDate")]
public string ErrorDate { get; set; }
}
我的错误是:
<transmission xmlns='blabla.xsd'> was not expected.
我的功能是这样:
private void ReadXmlFileByPath(string filePath)
{
string xmlText = string.Empty;
XmlDocument d = new XmlDocument();
using (XmlTextReader tr = new XmlTextReader(filePath))
{
tr.Namespaces = true;
d.Load(tr);
xmlText = d.InnerXml;
}
XmlSerializer xs = new XmlSerializer(typeof(DiagnosisErrorResponse), "");
using (TextReader reader = new StringReader(xmlText))
{
DiagnosisErrorResponse result = (DiagnosisErrorResponse)xs.Deserialize(reader);
}
}
更新:我从实体的XmlElement
属性中删除了“ ns0:”前缀,但仍然遇到相同的错误。
答案 0 :(得分:0)
您的问题是您的c#数据模型与XML不匹配。具体来说:
您已指出DiagnosisErrorResponse
的元素名称应为"ns0:transmission"
。应当不包括名称空间前缀ns0:
,它只是在XML文件中查找以查找实际的名称空间,该名称空间由xmlns属性{{1}定义}。
XML的嵌套级别未在您的数据模型中说明。您问题中的XML没有缩进;如果我缩进,它看起来像:
xmlns:ns0="blabla.xsd"
现在可以看到,<ns0:transmission xmlns:ns0="blabla.xsd">
<ns0:DiagnosisErrorResponse>
<ns0:ID>7</ns0:ID>
<ns0:ErrorCode>9</ns0:ErrorCode>
<ns0:ErrorDescription>sometext</ns0:ErrorDescription>
<ns0:ErrorDate>11-12-2018</ns0:ErrorDate>
</ns0:DiagnosisErrorResponse>
</ns0:transmission>
等不是ID
的子代,它们是transmission
的子代,而DiagnosisErrorResponse
是transmission
的子代。这需要在您的c#类中解决。
结合这两个问题,您的数据模型应类似于:
[XmlRoot(Namespace = "blabla.xsd", ElementName = "transmission", IsNullable = true)]
public class Transmission
{
[XmlElement("DiagnosisErrorResponse")]
public DiagnosisErrorResponse DiagnosisErrorResponse { get; set; }
}
[XmlRoot(Namespace = "blabla.xsd", IsNullable = true)]
public class DiagnosisErrorResponse
{
[XmlElement("ID")]
public long ID { get; set; }
[XmlElement("ErrorCode")]
public int ErrorCode { get; set; }
[XmlElement("ErrorDescription")]
public string ErrorDescription { get; set; }
[XmlElement("ErrorDate")]
public string ErrorDate { get; set; }
}
您的反序列化代码应类似于:
private DiagnosisErrorResponse ReadXmlFileByPath(string filePath)
{
using (var xmlReader = XmlReader.Create(filePath))
{
XmlSerializer xs = new XmlSerializer(typeof(Transmission));
var result = (Transmission)xs.Deserialize(xmlReader);
return result.DiagnosisErrorResponse;
}
}
演示小提琴#1 here。
或者,如果您尝试仅反序列化XML文件中的<DiagnosisErrorResponse>
元素而不为根元素创建数据模型,则可以使用XmlReader
在XML中向前扫描,直到合适为止。找到元素:
private DiagnosisErrorResponse ReadXmlFileByPath(string filePath)
{
using (var xmlReader = XmlReader.Create(filePath))
{
if (!xmlReader.ReadToDescendant("DiagnosisErrorResponse", "blabla.xsd"))
return null;
XmlSerializer xs = new XmlSerializer(typeof(DiagnosisErrorResponse));
var result = (DiagnosisErrorResponse)xs.Deserialize(xmlReader);
return result;
}
}
演示小提琴#2 here。
注意:
无需将XML文件加载到XmlDocument
中,将其重新序列化为字符串,然后反序列化该字符串。可以使用XmlReader
或StreamReader
在一个步骤中直接从文件中反序列化XML。
XmlTextReader
已被Microsoft在其documentation中弃用。应该使用XmlReader.Create()
。
您可以使用Generate C# class from XML中提到的一种代码生成工具来避免建模错误,例如上述错误。
诊断XML反序列化中的错误的最简单方法是序列化您根类型的实例,然后将生成的XML与要反序列化的XML进行比较。通常会很容易发现不一致之处,并指出您的问题所在。