Jason
Jason

Reputation: 3040

Xmlserializer nillable element with xmlattribute, possible?

I have an object :

class Thing {
  [Xmlarray("Widget", IsNullable=true) ] 
  List<Widget> Widgets;
 } 

class Widget  {
  [Xmlattribute] 
  public string Name;
  [XmlTextAttribute] 
  public string Value; 
} 

Basically I want sample output to look like :

<Thing>
  <Widget name="foo" xsi:nil="true"/>
  <Widget name="bar">Nerds</Widget>
</Thing>

The problem I am experiencing is that the xmlserializer isn't doing that for the foo line. It's not writing out the xsi:nil bit for widgets that have a Value containing null. It's just an empty element (<Widget name="foo"/>

The parser that ends up eating this Xml is old, and garbage and out of my control. It expects that nil bit to be there if I want that widget record removed from its system/storage versus setting it empty (which is what it does if the nil bit is missing from an empty Widget entry).

Sorry if there's mistakes, writing it on a cellphone. Essentially how do I get the xmlserializer to write the nil bit?

UPDATE: Here's the actual tags. I'm reading vague things about how it can't be set nillable if there's an attribute on the arrayitem (a Widget in the Widgets list).

<Widget xsi:nil="true"/>

is useless to me, as I'd mentioned -- the entry needs the name attribute and the nil=true (it tells the processor "this field, delete it from the store"). Without the name attribute, it doesn't know what field. Sadly, it only depends on xsi:nil to tell it that. If it sees an empty one <Widget name="foo"/> - it sets it blank/empty, not removed entirely.

class Thing{
        [System.Xml.Serialization.XmlArrayItemAttribute("Widget", IsNullable=true)]
        public List<Widget> Widgets { get; set; } 
}
class Widget{
        [System.Xml.Serialization.XmlAttribute][JsonProperty]
        public string name {get;set;}
        [System.Xml.Serialization.XmlTextAttribute]
        public string Value {get;set;}
}

Essentially it can't be <Widget name="foo"><Value>Bar</Value></Widget> or <Widget xsi:nil=true/> or <Widget name="foo"/> -- must be <Widget name="foo" xsi:nil="true"/> only. Blame the processor this thing gets sent to (of which I have no control).

So, is it serializable?

Upvotes: 1

Views: 711

Answers (1)

Phenix_yu
Phenix_yu

Reputation: 304

I update the answer,and delete the code not relevant again. Implementing IXmlSerializable may work for this issue.I only implement WriteXml interface function,you can implement others if you need.The code will be changed as the belows:

public class Thing:IXmlSerializable
    {      
        public List<Widget> Widgets{get;set;}

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            throw new NotImplementedException();
        }

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            throw new NotImplementedException();
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            throw new NotImplementedException();
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteStartElement("xsi","Thing", @"http://www.w3.org/2001/XMLSchema-instance");
            foreach (Widget widget in Widgets)
            {
                if (string.IsNullOrEmpty(widget.Value))
                {
                    writer.WriteStartElement("widget");
                    writer.WriteAttributeString("Name", widget.Name);
                    writer.WriteAttributeString("xsi", "nil", @"http://www.w3.org/2001/XMLSchema-instance", "true");                                  
                    writer.WriteEndElement();
                }
                else
                {
                    writer.WriteStartElement("widget");
                    writer.WriteAttributeString("Name", widget.Name);
                    writer.WriteString(widget.Value);
                    writer.WriteEndElement();
                }
            }
            writer.WriteEndElement();
            writer.Flush();
        }
    }

    public class Widget
    {
        public string Name{get;set;}
        public string Value { get; set; }
    } 
}

 public static void SaveXml()
        {
            XmlWriterSettings settings= new XmlWriterSettings();
            settings.Indent = true;
            settings.OmitXmlDeclaration = true;                

            XmlWriter xmlWriter = XmlWriter.Create(@"c:\test.xml",settings);           
            thing.WriteXml(xmlWriter);

        }

After serialization,the xml looks like the below.widget3's value is null.Hope this helpful.

   <xsi:Thing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <widget Name="name1">widget1</widget>
      <widget Name="name2">widget2</widget>
      <widget Name="name3" xsi:nil="true" />
    </xsi:Thing>

Upvotes: 2

Related Questions