在C#中反序列化具有空元素的Xml

20

尝试将来自供应商的一些XML片段反序列化为对象,但问题在于每个空元素标签上都会获得无效格式的错误。当所有元素都具有值时,我可以轻松地反序列化对象;或者省略空元素。

XML片段:

<foo>
<propOne>1</propOne>
<propTwo />
</foo>

C#类:

[Serialilbe()]     
public class foo
{ 
   public foo(){}
   [XmlElementAttribute(IsNullable = true)]
   public int? propOne {get;set;} 
   [XmlElementAttribute(IsNullable = true)]
   public int? propTwo {get;set;}   
 }

我可以在类上设置什么参数来调整解析吗?
或者
有没有一种简单的方法可以应用xsl来删除这些元素?
或者
我应该使用正则表达式在反序列化之前删除空元素吗?
或者
是否有更好的方法?


你是通过相同的接口(例如XmlSerializer类)进行序列化吗? - Adam Driscoll
顺便提一下,XMLSerializer 已经接近被弃用了。你可以考虑使用DataContractSerializer。 - Brian Genisio
4个回答

14
看起来最均一的清除这些节点的方法似乎是向反序列化器添加一个正则表达式过滤器。
    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
如果一个元素完整但是没有值: <Element></Element>。我已经编写了自己的逻辑来删除它,但速度太慢并且文件太大。我们可以编写正则表达式来检测这个吗? - MrFox

11

如果您无法控制传入的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; }
  }
}

当字符串元素为空时,反序列化程序可以愉快地解析它,因此您可以利用这一点。

如果您只需要覆盖一个或两个标记,这不是特别好,但可行。


编辑:propOneString 显然应该是一个字符串,而不是一个整数 :) - Brondahl
是的,这对我来说是最简单的方法。只需要处理一个标签。谢谢! - interesting-name-here

9

“使用XmlSerializer反序列化为Nullable”链接已失效。一种方法是实现IXmlSerializable并在ReadXml()内将空值转换为null。类似于https://dev59.com/bnRB5IYBdhLWcg3wbGxB#625463。 - bodhizero

0
为了简单起见,为什么不使用XmlDocument和XPath显式解析xml呢?使用XPath显式访问每个xml节点,例如:
XmlNode node = xml.SelectSingleNode ("foo/PropOne");
if (node != null)
{
     propOneValue = node.innerText;
}

3
我假设他想将数据反序列化为一个类/类型,而不是逐个获取值。 - user1040975

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接