我想反序列化以下XML元素。
<error code="1" type="post">
<bad-request xmlns="blah:ns"> // <-- may be some different element name
<text>You fail.</text> // <-- this is optional
</bad-request>
</error>
子元素bad-request
可以有多个不同的名称。我想将该元素名称反序列化为一个错误类型,在我的命名空间中定义为枚举,如下所示。
public enum ErrorType { BadRequest = 1, Forbidden = 2, Blah = 3, ... }
此外,我希望将text
'元素文本解析为ErrorText
属性。所以我的最后一堂课看起来就像那样。
public class Error
{
public string ErrorText { get; set; }
public ErrorType ErrorType { get; set; }
}
如何在C#和反序列化中实现这样的目标?
更新:
我目前的解决方案似乎对我来说太过分了。
public class Error
{
private string _type;
[XmlAttribute("type")]
public string Type // <-- there is clearly a bug in here I should not do that on the type attribute because it has nothing to do with the error type
{
get { return _type; }
set
{
_type = value;
switch (value)
{
case "bad-request":
ErrorType = ErrorTypes.BadRequest;
ErrorText = BadRequest.Text.Value;
break;
default:
...
break;
}
}
}
public ErrorTypes ErrorType { get; set; }
public string ErrorText { get; set; }
[XmlElement("bad-request")]
public BadRequest BadRequest { get; set; }
}
public enum ErrorTypes
{
BadRequest = 0,
Conflict = 1,
FeatureNotImplemented = 2,
Forbidden = 3
}
public class Text
{
[XmlText]
public string Value { get; set; }
}
public class BadRequest
{
[XmlElement("text")]
public Text Text { get; set; }
}
上面的代码需要为每个元素名称/类型设置一个单独的类。
答案 0 :(得分:3)
您可以使用继承反序列化此类XML,而不是将其隐藏在enum
后面:
public enum ErrorType { BadRequest = 1, Forbidden = 2, Blah = 3, ... }
[Serializable]
[XmlRoot(ElementName="error")]
public class Error
{
[XmlElement(
ElementName = "bad-request",
Type = typeof(BadRequest),
Namespace = "blah:ns")]
[XmlElement(
ElementName = "forbidden",
Type = typeof(Forbidden),
Namespace = "blah:ns")]
public ErrorDetails ErrorDetails { get; set; }
[XmlAttribute(AttributeName = "type")]
public string Type { get; set; }
[XmlAttribute(AttributeName = "code")]
public int Code { get; set; }
}
[Serializable]
public abstract class ErrorDetails
{
public abstract ErrorType ErrorType { get; }
}
[Serializable]
public class BadRequest : ErrorDetails
{
public override ErrorType ErrorType
{
get
{
return ErrorType.BadRequest;
}
}
[XmlElement(ElementName = "text")]
public string Text { get; set; }
public override string ToString()
{
return Text;
}
}
[Serializable]
public class Forbidden : ErrorDetails
{
public override ErrorType ErrorType
{
get
{
return ErrorType.Forbidden;
}
}
[XmlElement(ElementName = "text")]
public string Text { get; set; }
public override string ToString()
{
return Text;
}
}
测试:
string data1 = @"<error code=""1"" type=""post"">
<bad-request xmlns=""blah:ns"">
<text>You fail.</text>
</bad-request>
</error>";
string data2 = @"<error code=""1"" type=""post"">
<forbidden xmlns=""blah:ns"">
<text>You fail.</text>
</forbidden>
</error>";
byte[] bytes1 = ASCIIEncoding.ASCII.GetBytes(data1);
byte[] bytes2 = ASCIIEncoding.ASCII.GetBytes(data2);
MemoryStream ms1 = new MemoryStream(bytes1);
MemoryStream ms2 = new MemoryStream(bytes2);
XmlSerializer xs = new XmlSerializer(typeof(Error));
Error result1 = xs.Deserialize(ms1) as Error;
Error result2 = xs.Deserialize(ms2) as Error;
Console.WriteLine(result1.ErrorDetails.ToString());
Console.WriteLine(result2.ErrorDetails.ToString());