开发者

Deserialize Xml with empty elements in C#

开发者 https://www.devze.com 2023-01-01 21:49 出处:网络
Trying to deserialize some xml snippits from a vendor into objects.The problem is that I\'m getting an invalid format on every empy element tag.I can deserialize the object no problem when all of the

Trying to deserialize some xml snippits from a vendor into objects. The problem is that I'm getting an invalid format on every empy element tag. I can deserialize the object no problem when all of the elements have values. Or the empty elements are ommitted.

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;}   
 }

Is there a setting on the class I can make to adjust the parsing?
or
Is there an easy way I can apply xsl to remove these elements?
or
Should开发者_运维百科 I use regEx to remove the empty elements be fore desrializing?
or
an even better way?


The most uniform way to clean out these nodes appears to be to add a RegEx filter to the deserializer.

    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 "";}


Another option if you've not got control over the inbound XML is to work around this by having the deserializer pretend that the variable is a string:

[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; }
  }
}

The Deserialiser is happy to parse a string element when it's empty, so you make use of that.

It's not particularly nice, but it'll do if you've only got one or 2 tags to cover


See this article: Can XmlSerializer deserialize into a Nullable?

In a nutshell your Xml should look like this if you want to use Nullable types:

<foo xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<propOne>1</propOne>
<propTwo xsi:nil='true'/>
</foo>

The two changes are adding the namespace, and explicitly setting xsi:nil to true on the null element.

If you don't have control over your Xml there is a more advanced technique described here: Using XmlSerializer to deserialize into a Nullable


For simplicity, why don't you parse the xml explictly using XmlDocument and XPath? Use XPath to explictly access each xml node e.g.

XmlNode node = xml.SelectSingleNode ("foo/PropOne");
if (node != null)
{
     propOneValue = node.innerText;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消