简体   繁体   English

在C#中使用空元素反序列化Xml

[英]Deserialize Xml with empty elements in C#

Trying to deserialize some xml snippits from a vendor into objects. 尝试将某些xml snippit从供应商反序列化为对象。 The problem is that I'm getting an invalid format on every empy element tag. 问题是我在每个empy元素标签上获得的格式无效。 I can deserialize the object no problem when all of the elements have values. 当所有元素都有值时,我可以反复排序对象没问题。 Or the empty elements are ommitted. 或者省略空元素。

Xml Snippit: Xml Snippit:

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

C# Class: C#类:

[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? 有没有一种简单的方法可以应用xsl来删除这些元素?
or 要么
Should I use regEx to remove the empty elements be fore desrializing? 我应该使用regEx删除空元素进行去串化吗?
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. 清除这些节点的最统一方法似乎是向反序列化器添加一个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 "";}

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

The Deserialiser is happy to parse a string element when it's empty, so you make use of that. Deserialiser很高兴在字符串元素为空时解析它,因此您可以使用它。

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? 看到这篇文章: XmlSerializer可以反序列化为Nullable吗?

In a nutshell your Xml should look like this if you want to use Nullable types: 简而言之,如果你想使用Nullable类型,你的Xml应该是这样的:

<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. 这两个更改是添加命名空间,并在null元素上显式设置xsi:nil为true。

If you don't have control over your Xml there is a more advanced technique described here: Using XmlSerializer to deserialize into a Nullable 如果您无法控制Xml,则可以使用此处描述的更高级技术: 使用XmlSerializer反序列化为Nullable

For simplicity, why don't you parse the xml explictly using XmlDocument and XPath? 为简单起见,为什么不使用XmlDocument和XPath明确解析xml? Use XPath to explictly access each xml node eg 使用XPath明确访问每个xml节点,例如

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM