Xml serileştirme - Boş değerleri gizle


128

Standart bir .NET Xml Serileştirici kullanırken, tüm boş değerleri gizlememin herhangi bir yolu var mı? Aşağıdaki, sınıfımın çıktısının bir örneğidir. Null olarak ayarlanmışlarsa, null yapılabilir tamsayıların çıktısını almak istemiyorum.

Geçerli Xml çıktısı:

<?xml version="1.0" encoding="utf-8"?>
<myClass>
   <myNullableInt p2:nil="true" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance" />
   <myOtherInt>-1</myOtherInt>
</myClass>

İstediğim:

<?xml version="1.0" encoding="utf-8"?>
<myClass>
   <myOtherInt>-1</myOtherInt>
</myClass>

Yanıtlar:


255

ShouldSerialize{PropertyName}XmlSerializer'a üyeyi serileştirmesi gerekip gerekmediğini söyleyen desenle bir işlev oluşturabilirsiniz .

Örneğin, sınıf mülkünüz çağrılırsa MyNullableInt,

public bool ShouldSerializeMyNullableInt() 
{
  return MyNullableInt.HasValue;
}

İşte tam bir örnek

public class Person
{
  public string Name {get;set;}
  public int? Age {get;set;}
  public bool ShouldSerializeAge()
  {
    return Age.HasValue;
  }
}

Aşağıdaki kodla serileştirildi

Person thePerson = new Person(){Name="Chris"};
XmlSerializer xs = new XmlSerializer(typeof(Person));
StringWriter sw = new StringWriter();
xs.Serialize(sw, thePerson);

Aşağıdaki XML'deki sonuçlar - Yaş olmadığına dikkat edin

<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>Chris</Name>
</Person>

9
Tek kelime: Harika! MSDN
ShouldSerialize

7
ShouldSerialize kalıbı yalnızca, özellik bir XmlAttribute özniteliğiyle işaretlenmemişse çalışır (bunun işe yarayacağını düşündüm, çünkü öznitelik isteğe bağlı olabilir, ancak değil).
Matze

@Matze ilginç, bunu denemedim. Ben de işe yarayacağını varsayardım.
Chris Taylor

@ChrisTaylor Evet; Ben de aynısını varsaydım. Zor olan şey, XmlAttribute nullable int-özelliğinden kaldırılana kadar XmlSerializer örneğinin oluşturulmasının başarısız olmasıydı (türü yansıtırken bir hata nedeniyle).
Matze

2
@PierredeLESPINAY - Visual Studio 2015 ve sonraki sürümlerde şunları kullanabilirsiniz: public bool ShouldSerializeAge () => Age.HasValue;
RooiWillie

34

Chris Taylor'ın yazdıklarına ek olarak: eğer bir öznitelik olarak serileştirilmiş bir şeyiniz varsa, sınıfınızda {PropertyName}Specifiedserileştirilmesi gerekip gerekmediğini kontrol etmek için adlandırılmış bir özelliğe sahip olabilirsiniz . Kodda:

public class MyClass
{
    [XmlAttribute]
    public int MyValue;

    [XmlIgnore]
    public bool MyValueSpecified;
}

Dikkatli olun, {PropertyName}Specifiedöznitelikler bool türünde olmalıdır.
sinsedrix

30

Adında bir özellik var XmlElementAttribute.IsNullable

IsNullable özelliği true olarak ayarlanmışsa, null başvuru olarak ayarlanmış sınıf üyeleri için xsi: nil özniteliği oluşturulur.

Aşağıdaki örnek, kendisine XmlElementAttributeuygulanan bir alanı ve IsNullable özelliği false olarak ayarlanmış bir alanı gösterir .

public class MyClass
{
   [XmlElement(IsNullable = false)]
   public string Group;
}

XmlElementAttributeSerileştirmede vb. İsimleri değiştirmek için diğerlerine bakabilirsiniz .


11
Ne yazık ki, bu yalnızca başvuru türleri için işe yarar, değer türleri veya Null değerine sahip eşdeğerleri için değil.
Vincent Sels

3
@VincentSels doğru. MSDN diyor: Bir değer türü null içeremediğinden, IsNullable özelliğini değer türü olarak yazılan bir üyeye uygulayamazsınız. Ayrıca, bu özelliği null yapılabilir değer türleri için false olarak ayarlayamazsınız. Bu tür türler boş olduğunda, xsi: nil değeri true olarak ayarlanarak serileştirilecektir.
bouvierr

12

Bazı varsayılan değerler tanımlayabilirsiniz ve bu alanların serileştirilmesini engeller.

    [XmlElement, DefaultValue("")]
    string data;

    [XmlArray, DefaultValue(null)]
    List<string> data;

Maalesef bu, null yapılabilir değer türleri için çalışmaz
bubi

2

Otomatik oluşturulan etiketler olmadan kendi xml'mi oluşturmayı tercih ederim. Bunda, null değerlere sahip düğümleri oluşturmayı göz ardı edebilirim:

public static string ConvertToXML<T>(T objectToConvert)
    {
        XmlDocument doc = new XmlDocument();
        XmlNode root = doc.CreateNode(XmlNodeType.Element, objectToConvert.GetType().Name, string.Empty);
        doc.AppendChild(root);
        XmlNode childNode;

        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
        foreach (PropertyDescriptor prop in properties)
        {
            if (prop.GetValue(objectToConvert) != null)
            {
                childNode = doc.CreateNode(XmlNodeType.Element, prop.Name, string.Empty);
                childNode.InnerText = prop.GetValue(objectToConvert).ToString();
                root.AppendChild(childNode);
            }
        }            

        return doc.OuterXml;
    }

1
private static string ToXml(Person obj)
{
  XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
  namespaces.Add(string.Empty, string.Empty);

  string retval = null;
  if (obj != null)
  {
    StringBuilder sb = new StringBuilder();
    using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { OmitXmlDeclaration = true }))
    {
      new XmlSerializer(obj.GetType()).Serialize(writer, obj,namespaces);
    }
    retval = sb.ToString();
  }
  return retval;
}

1

Benim durumumda, boş değer atanabilir değişkenler / öğeler tüm String tipiydi. Bu yüzden, basitçe bir kontrol yaptım ve NULL durumunda bunlara string.Empty atadım. Bu şekilde gereksiz nil ve xmlns özniteliklerinden kurtulmuş oldum (p3: nil = "true" xmlns: p3 = "http://www.w3.org/2001/XMLSchema-instance)

// Example:

myNullableStringElement = varCarryingValue ?? string.Empty

// OR

myNullableStringElement = myNullableStringElement ?? string.Empty

1
Bu çözümler çok sınırlıdır ve sadece string ile çalışır. Diğer türler için boş dizge hala bir değerdir. Bazı ayrıştırıcılar özniteliği bulmaya ve bulunursa değeri hedef türe dönüştürmeye çalışır. Bu tür ayrıştırıcılar için, eksik öznitelik boş anlamına gelir ve öznitelik varsa geçerli bir değere sahip olması gerekir.
ZafarYousafi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.