C# 当不存在数据时,防止XmlSerializer中的自动关闭标记
当我序列化值时:如果for data中没有值,那么它的格式如下C# 当不存在数据时,防止XmlSerializer中的自动关闭标记,c#,.net,xml,C#,.net,Xml,当我序列化值时:如果for data中没有值,那么它的格式如下 <Note> <Type>Acknowledged by PPS</Type> <Data /> </Note> 如果数据没有赋值,我无法计算如何实现以下格式的数据 <Note> <Type>Acknowledged by PPS</Type> <Data
<Note>
<Type>Acknowledged by PPS</Type>
<Data />
</Note>
如果数据没有赋值,我无法计算如何实现以下格式的数据
<Note>
<Type>Acknowledged by PPS</Type>
<Data></Data>
</Note>
PPS认可
在我看来,使用序列化来生成所需的XML是不可能的。但是,您可以使用linqtoxml
生成如下所需的模式-
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);
}
主捕获是,如果您的值为空,则应将其设置为空字符串。它将强制生成结束标记
。如果值为null,则不会创建结束标记。您可以通过创建自己的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();
}
乱七八糟的时间-见
基本上,在生成XML文档之后,遍历每个节点,如果没有子节点,则添加一个空文本节点
// 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发送到其他一些你无法轻松修复的系统,那么你必须实事求是)你可以添加一个虚拟字段来防止自动关闭元素
[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;
}
}
}
原则上,他为我工作。但是,如果您希望XML输出能够很好地打印出来,而不必使用XmlWriterSettings和其他Stream对象(如注释中所述),那么只需在XmlTextWriter类的构造函数中设置格式即可
public MyXmlTextWriter(string filename) : base(filename, Encoding.UTF8)
{
this.Formatting = Formatting.Indented;
}
(本应将此作为评论发布,但目前还不允许;-)虽然我不确定您为什么要这样做,但请注意,您编写的xml实际上是无效的。您永远不会关闭数据元素。如果我使用它,那么[XmlElementAttribute(IsNullable=false)]完全忽略我不希望和之间的差异很小的时候,通常直接与不完整/错误的实现联系在一起。为什么要这样做?因为我正在执行一些操作,如果在value中找不到元素,则您应该阅读我的答案并将其应用于您的情况。注意:序列化/反序列化时,这将导致null->“
”。但是,生成XML时,每个元素后都不会断行:(@SuperJMN您需要围绕XmlWriter
。底层XmlWriter
需要XmlWriter设置Indent
设置为true
,并将NewLineChars
设置为合理的值。例如:(也适用于Stream
而不是textwitter
)它有一个缩进模式的包。这对我有效。我必须将if(node.HasChildNodes)
更改为if(node.HasChildNodes&&node.NodeType!=XmlNodeType.Text)
”仍然是值。
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;
}
}
}
public MyXmlTextWriter(string filename) : base(filename, Encoding.UTF8)
{
this.Formatting = Formatting.Indented;
}