Предотвращать самозакрывающиеся теги в XmlSerializer, когда данных нет

Когда я сериализую значение: Если для данных нет значения, то он приближается, как ниже.

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

Но то, что я хочу получить в XML-формате ниже:

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

Код Для этого я написал:

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

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

Я не могу понять, что делать для получения данных в формате ниже, если данные не присваивают никакого значения.

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

Ответ 1

Вы можете сделать это, создав свой собственный XmlTextWriter, чтобы перейти в процесс сериализации.

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

    }

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

Вы можете проверить результат, используя:

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();
    }

Ответ 2

IMO, невозможно создать желаемый XML с помощью Serialization. Но вы можете использовать LINQ to XML для генерации желаемой схемы, например:

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);
}

Основной улов in case your value is null, you should set it to empty string. Это будет force the closing tag to be generated. В случае, если значение равно нулю, закрывающий тег не создается.

Ответ 3

Время Kludge - см. Генерировать результат System.Xml.XmlDocument.OuterXml(), действительный в HTML

В основном после того, как XML-документ был создан, пройдите через каждый node, добавив пустой текст node, если нет дочерних

// 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(""))
}

(Да, я знаю, что вам не нужно это делать, но если отправка XML в другую систему, которую вы не можете легко исправить, должна быть прагматичной в отношении вещей)

Ответ 4

Вы можете добавить фиктивное поле, чтобы предотвратить самозакрывающийся элемент.

[XmlText]
public string datavalue= " ";

Или, если вам нужен код для вашего класса, тогда ваш класс должен быть таким.

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

   [XmlElement("Data")]
   private string _dataValue;
   public string dataValue {
      get {
          if(string.IsNullOrEmpty(_dataValue))
             return " ";
          else
             return _dataValue;
      }
      set {
          _dataValue = value;
      }
   }
}

Ответ 5

В принципе, armen.shimoon ответ работал для меня. Но если вы хотите, чтобы ваш вывод XML был напечатан без использования XmlWriterSettings и дополнительного объекта Stream (как указано в комментариях), вы можете просто установить форматирование в конструкторе вашего класса XmlTextWriter.

public MyXmlTextWriter(string filename) : base(filename, Encoding.UTF8)
{
    this.Formatting = Formatting.Indented;
}

(Написал бы это как комментарий, но пока не допускается ;-))