尝试将某些xml snippit从供应商反序列化为对象。问题是我在每个empy元素标签上获得的格式无效。当所有元素都有值时,我可以反复排序对象没问题。或者省略空元素。
Xml Snippit:
< foo>
< propOne> 1< / propOne>
< propTwo />
< / foo>
C#Class:
[Serialilbe()]
public class foo
{
public foo(){}
[XmlElementAttribute(IsNullable = true)]
public int? propOne {get;set;}
[XmlElementAttribute(IsNullable = true)]
public int? propTwo {get;set;}
}
我可以通过类来设置调整解析吗?
或
有没有一种简单的方法可以应用xsl去除这些元素?
或
我是否应该使用regEx删除空元素以进行反序列化?
或
更好的方式呢?
答案 0 :(得分:13)
清除这些节点的最统一方法似乎是向反序列化程序添加一个RegEx过滤器。
public static T Deserialize<T>(string xml){ XmlSerializer xs = new XmlSerializer(typeof(T)); string cleanXml = Regex.Replace(xml, @"<[a-zA-Z].[^(><.)]+/>", new MatchEvaluator(RemoveText)); MemoryStream memoryStream = new MemoryStream((new UTF8Encoding()).GetBytes(cleanXml)); XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); return (T)xs.Deserialize(memoryStream); }
static string RemoveText(Match m) { return "";}
答案 1 :(得分:9)
请参阅此文章:Can XmlSerializer deserialize into a Nullable?
简而言之,如果你想使用Nullable类型,你的Xml应该是这样的:
<foo xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<propOne>1</propOne>
<propTwo xsi:nil='true'/>
</foo>
两个更改是添加命名空间,并在null元素上显式设置xsi:nil为true。
如果您无法控制Xml,则可以使用此处描述的更高级技术:Using XmlSerializer to deserialize into a Nullable
答案 2 :(得分:9)
如果你无法控制入站XML,另一个选择就是通过让反序列化器假装变量是一个字符串来解决这个问题:
[Serializable()]
public class foo
{
public foo(){}
[XmlElement("propOne")]
[EditorBrowsable(EditorBrowsableState.Never)]
public string propOneString {get;set;}
[XmlIgnore]
private int? propOneInternal = null;
[XmlIgnore]
private bool propOneSet = false;
[XmlIgnore]
public int? propOne
{
get
{
if (!propOneSet)
{
if(!string.IsNullOrEmpty(propOneString)
{
propOneInternal = int.Parse(propOneString);
}
//else leave as pre-set default: null
propOneSet = true;
}
return propOneInternal;
}
set { propOneInternal = value; }
}
}
Deserialiser很高兴在字符串元素为空时解析它,所以你可以使用它。
这不是特别好,但如果你只有一个或两个标签可以覆盖
答案 3 :(得分:0)
为简单起见,为什么不使用XmlDocument和XPath显式解析xml?使用XPath显式访问每个xml节点,例如
XmlNode node = xml.SelectSingleNode ("foo/PropOne");
if (node != null)
{
propOneValue = node.innerText;
}