【问题标题】:How do I stop an empty tag of a collection from being emitted by XmlSerializer?如何阻止 XmlSerializer 发出集合的空标记?
【发布时间】:2019-06-05 18:51:55
【问题描述】:

在寻找建议时,我遇到了各种解决方案:从 IXMLSerializerShouldSerialize,再到简单的 .Replace() 或 RegEx。 我不想使用后两者,因为我认为它们效率低下,但是我没有足够的 C# 知识来实现​​与 Serializer 相关的建议,所以希望有人能提供建议。

我有各种旅行相关选项的“详细信息”集合 - 航班、火车、酒店等... XSD 课程由第 3 方提供给我们,以下是相关部分:

[XmlRoot(ElementName = "Details")]
public class Details
{
    [XmlElement(ElementName = "Flight")]
    public Flight Flight { get; set; }
    [XmlElement(ElementName = "Train")]
    public Train train { get; set; }
    [XmlElement(ElementName = "RentalCar")]
    public RentalCar rentalCar { get; set; }
    [XmlElement(ElementName = "Hotel")]
    public Hotels Hotel { get; set; }
    [XmlElement(ElementName = "Bus")]
    public Bus Bus { get; set; }

}

每个元素都有自己的 XMLRoot,例如酒店一号:

 [XmlRoot(ElementName = "Hotel")]
    public class Hotels
    {
        [XmlElement(ElementName = "VoucherNo")]
        public string VoucherNo { get; set; }
        [XmlElement(ElementName = "VoucherRef")]
        public string VoucherRef { get; set; }
        [XmlElement(ElementName = "DepartureDate")]
        public string departureDate;
        [XmlElement(ElementName = "DepartureDateFieldSpecified")]
        public bool departureDateFieldSpecified;
        [XmlElement(ElementName = "ReturnDate")]
        public string returnDate;
        [XmlElement(ElementName = "ReturnDateFieldSpecified")]
        public bool returnDateFieldSpecified;
    }

细节又是产品的一部分

[XmlRoot(ElementName = "Product")]
public class Product
{
    [XmlElement(ElementName = "ArticleNumber")]
    public int articleNumber { get; set; }
//many other elements
    public Details Details { get; set; }

}

在我的代码中,我声明了 objProductDetails 集合

Details objProductDetails = new Details();

并填充相关数据。一些元素可以保持为空:并非每次旅行都有火车或租车,因此例如我只能填充 Hotel 元素。我使用非空检查如下

if (objHotel != null)
      objProductDetails.Hotel = objHotel;

if (objRentalCar != null)
      objProductDetails.rentalCar = objRentalCar;

目前,当我执行我的代码时,我确实获得了酒店的所有数据,但其他所有数据都是空标签:

酒店:

<qfl:Product>
  <qfl:ArticleNumber>100</qfl:ArticleNumber>
     <qfl:Details>
        <qfl:Hotel>
          <qfl:VoucherNo>1234</qfl:VoucherNo>

/...... rest of the result

其他

 <qfl:Product>
    <qfl:ArticleNumber>180</qfl:ArticleNumber>
       <qfl:Details />
  </qfl:Product>
        /...... rest of the result

跳过空的详细信息元素的最佳方法是什么,请接收以下内容:

 <qfl:Product>
     <qfl:ArticleNumber>180</qfl:ArticleNumber>
 </qfl:Product>

注意在下面 Ivan 的 cmets 之后,我似乎遇到了另一个问题 - 虽然我的租车对象是空的,但 objRentalCar == null 是错误的。任何帮助都感激不尽。

【问题讨论】:

    标签: c# serialization collections


    【解决方案1】:

    您创建了空的Details 对象,因此它被序列化为空标签。如果您不想序列化它,您应该检查此对象中的所有属性是否为空并且不要创建对象或不要在Product 对象中设置属性Details

    if (objHotel != null || objRentalCar != null || ...)
    {
        product.Details = objProductDetails;
    }
    

    【讨论】:

    • objHotel 在我的情况下不为空,因此您的 if() 子句将返回 true 并继续像我现在一样。还是我错过了什么?
    • 那么Details属性不能为空标签。它包含酒店数据。或者您不想序列化酒店数据?
    • 似乎问题出在 objRentalCar 上。我会尝试附加一张图片,但尽管它显示它的所有元素都是空的,但 objRentalCar !=null 会返回 true。你能告诉我为什么吗?
    • 您有所有属性为空的对象。它是有效的,您不需要创建这样的对象。我的意思是在创建对象之前检查数据,如果所有数据都为空,则不要创建空对象。
    • 是的,我已经实例化了它 RentalCar objRentalCar = new RentalCar(); 否则它将失败并出现异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多