Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent self closing tags in XmlSerializer when no data is present

Tags:

c#

.net

xml

When I serialize the value : If there is no value present in for data then it's coming like below format.

  <Note>
        <Type>Acknowledged by PPS</Type>
        <Data />
  </Note>

But what I want xml data in below format:

  <Note>
        <Type>Acknowledged by PPS</Type>
        <Data></Data>
  </Note>

Code For this i have written :

[Serializable]
public class Notes
{
    [XmlElement("Type")]
    public string typeName { get; set; }

    [XmlElement("Data")]
    public string dataValue { get; set; }
}

I am not able to figure out what to do for achieve data in below format if data has n't assign any value.

  <Note>
        <Type>Acknowledged by PPS</Type>
        <Data></Data>
  </Note>
like image 607
Nishant Kumar Avatar asked Nov 24 '12 08:11

Nishant Kumar


People also ask

Is it mandatory to use closing tags in XML?

All XML elements must have a closing tag.

What is the only self closing tag?

The br tag inserts a line break (not a paragraph break). This tag has no content, so it is self closing.

Does HTML support self closing tags?

Notes. ↑ The full list of valid self-closing tags in HTML5 is: area, base, br, col, embed, hr, img, input, keygen, link, meta, param, source, track, and wbr. However, only ‎<br /> , ‎<hr /> , ‎<wbr /> are allowed through the parser.

How does the XmlSerializer work C#?

The XmlSerializer creates C# (. cs) files and compiles them into . dll files in the directory named by the TEMP environment variable; serialization occurs with those DLLs. These serialization assemblies can be generated in advance and signed by using the SGen.exe tool.


3 Answers

You can do this by creating your own XmlTextWriter to pass into the serialization process.

public class MyXmlTextWriter : XmlTextWriter
{
    public MyXmlTextWriter(Stream stream) : base(stream, Encoding.UTF8)
    {

    }

    public override void WriteEndElement()
    {
        base.WriteFullEndElement();
    }
}

You can test the result using:

class Program
{
    static void Main(string[] args)
    {
        using (var stream = new MemoryStream())
        {
            var serializer = new XmlSerializer(typeof(Notes));
            var writer = new MyXmlTextWriter(stream);
            serializer.Serialize(writer, new Notes() { typeName = "Acknowledged by PPS", dataValue="" });
            var result = Encoding.UTF8.GetString(stream.ToArray());
            Console.WriteLine(result);
        }
       Console.ReadKey();
    }
like image 82
armen.shimoon Avatar answered Oct 09 '22 17:10

armen.shimoon


IMO it's not possibe to generate your desired XML using Serialization. But, you can use LINQ to XML to generate the desired schema like this -

XDocument xDocument = new XDocument();
XElement rootNode = new XElement(typeof(Notes).Name);
foreach (var property in typeof(Notes).GetProperties())
{
   if (property.GetValue(a, null) == null)
   {
       property.SetValue(a, string.Empty, null);
   }
   XElement childNode = new XElement(property.Name, property.GetValue(a, null));
   rootNode.Add(childNode);
}
xDocument.Add(rootNode);
XmlWriterSettings xws = new XmlWriterSettings() { Indent=true };
using (XmlWriter writer = XmlWriter.Create("D:\\Sample.xml", xws))
{
    xDocument.Save(writer);
}

Main catch is in case your value is null, you should set it to empty string. It will force the closing tag to be generated. In case value is null closing tag is not created.

like image 1
Rohit Vats Avatar answered Oct 09 '22 18:10

Rohit Vats


Kludge time - see Generate System.Xml.XmlDocument.OuterXml() output thats valid in HTML

Basically after XML doc has been generated go through each node, adding an empty text node if no children

// Call with
addSpaceToEmptyNodes(xmlDoc.FirstChild);

private void addSpaceToEmptyNodes(XmlNode node)
{
    if (node.HasChildNodes)
    {
        foreach (XmlNode child in node.ChildNodes)
            addSpaceToEmptyNodes(child);
    }
    else         
        node.AppendChild(node.OwnerDocument.CreateTextNode(""))
}

(Yes I know you shouldn't have to do this - but if your sending the XML to some other system that you can't easily fix then have to be pragmatic about things)

like image 1
Ryan Avatar answered Oct 09 '22 19:10

Ryan