XML 纯字符串属性
XML Attribute on Plain String
我想用 C# 代码生成如下 XML。
<card>
<name>Cool Card</name>
<set rarity="common">S1</set>
</card>
我有这样的东西。
public class card
{
public string name = "Cool Card";
[XmlAttribute]
public string rarity = "common";
public string set = "S1";
}
public static void WriteXml()
{
var serializer = new XmlSerializer(typeof(card));
var myCard = new();
using var sw = new StringWriter();
serializer.Serialize(sw, myCard);
XDocument doc = XDocument.Parse(sw.ToString());
XmlWriterSettings xws = new();
xws.OmitXmlDeclaration = true;
xws.Indent = true;
using var xw = XmlWriter.Create(path, xws);
doc.Save(xw);
}
问题是这不会将“稀有度”属性添加到“设置”值。尝试添加 [XmlAttribute] 会将其添加到父元素而不是下一个同级元素,我不知道如何在普通字符串元素上获取它,所以目前我的输出看起来像。
<card rarity="common">
<name>Cool Card</name>
<set>S1</set>
</card>
XML example doc 显示了如何在元素上设置属性的示例,但只有一个具有嵌套字段的示例,而不是一个纯字符串。是否可以像我第一个发布的示例演示的那样向 XML 中的普通旧字符串元素添加属性?
试试这个:
public class card
{
public string name = "Cool Card";
public Set set = new();
}
public class Set
{
[XmlText]
public string value = "S1";
[XmlAttribute]
public string rarity = "common";
}
如果您考虑一下,没有其他方法可以将 xml 属性仅应用于声明它的元素。因此您需要将其移至另一个 class。当您执行此操作时,新的 属性 值是必需的,并且需要将其展平,因为不需要值节点,因为您需要 XmlText 属性。
在这种情况下最干净的选择是实现 IXmlSerializable:
public class card : IXmlSerializable
{
public string name = "Cool Card";
public string rarity = "common";
public string set = "S1";
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
reader.ReadStartElement(nameof(card));
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
if (reader.Name == nameof(name))
{
this.name = reader.ReadElementContentAsString();
}
else if (reader.Name == nameof(set))
{
this.rarity = reader.GetAttribute(nameof(rarity));
this.set = reader.ReadElementContentAsString();
}
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteElementString(nameof(name), this.name);
writer.WriteStartElement(nameof(set));
writer.WriteAttributeString(nameof(rarity), this.rarity);
writer.WriteString(this.set);
writer.WriteEndElement();
}
}
如果你的 class 很大,你只需要在 XML 中做一点改变,有时实现 IXmlSerializable 是一团糟(你必须保存所有属性并且只保存一两个,做一点改变)。在这些情况下,您可以使用属性和一些小助手 classes 来获得相同的结果。这个想法是告诉 XML 序列化器不要序列化一些 属性 并使用另一个伪造的 属性 来进行序列化。
例如,使用您想要的 XML 结构创建集合 class:
public class XmlSet
{
private readonly card _card;
public XmlSet()
{
this._card = new card();
}
public XmlSet(card card)
{
this._card = card;
}
[XmlText]
public string set
{
get { return this._card.set; }
set { this._card.set = value; }
}
[XmlAttribute]
public string rarity
{
get { return this._card.rarity; }
set { this._card.rarity = value; }
}
}
它只是一个包装器,具有您想要的 XML 属性。您 get/set 值 from/to 您的 card
对象。
然后,在你的卡片class中,忽略集合属性并序列化假的属性:
public class card
{
public string name = "Cool Card";
[XmlIgnore]
public string rarity = "common";
[XmlIgnore]
public string set = "S1";
// Added to serialization
private XmlSet _xmlSetNode;
[XmlElement("set")]
public XmlSet XmlSet
{
get
{
this._xmlSetNode = this._xmlSetNode ?? new XmlSet(this);
return this._xmlSetNode;
}
set { this._xmlSetNode = value; }
}
}
我想用 C# 代码生成如下 XML。
<card>
<name>Cool Card</name>
<set rarity="common">S1</set>
</card>
我有这样的东西。
public class card
{
public string name = "Cool Card";
[XmlAttribute]
public string rarity = "common";
public string set = "S1";
}
public static void WriteXml()
{
var serializer = new XmlSerializer(typeof(card));
var myCard = new();
using var sw = new StringWriter();
serializer.Serialize(sw, myCard);
XDocument doc = XDocument.Parse(sw.ToString());
XmlWriterSettings xws = new();
xws.OmitXmlDeclaration = true;
xws.Indent = true;
using var xw = XmlWriter.Create(path, xws);
doc.Save(xw);
}
问题是这不会将“稀有度”属性添加到“设置”值。尝试添加 [XmlAttribute] 会将其添加到父元素而不是下一个同级元素,我不知道如何在普通字符串元素上获取它,所以目前我的输出看起来像。
<card rarity="common">
<name>Cool Card</name>
<set>S1</set>
</card>
XML example doc 显示了如何在元素上设置属性的示例,但只有一个具有嵌套字段的示例,而不是一个纯字符串。是否可以像我第一个发布的示例演示的那样向 XML 中的普通旧字符串元素添加属性?
试试这个:
public class card
{
public string name = "Cool Card";
public Set set = new();
}
public class Set
{
[XmlText]
public string value = "S1";
[XmlAttribute]
public string rarity = "common";
}
如果您考虑一下,没有其他方法可以将 xml 属性仅应用于声明它的元素。因此您需要将其移至另一个 class。当您执行此操作时,新的 属性 值是必需的,并且需要将其展平,因为不需要值节点,因为您需要 XmlText 属性。
在这种情况下最干净的选择是实现 IXmlSerializable:
public class card : IXmlSerializable
{
public string name = "Cool Card";
public string rarity = "common";
public string set = "S1";
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
reader.ReadStartElement(nameof(card));
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
if (reader.Name == nameof(name))
{
this.name = reader.ReadElementContentAsString();
}
else if (reader.Name == nameof(set))
{
this.rarity = reader.GetAttribute(nameof(rarity));
this.set = reader.ReadElementContentAsString();
}
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteElementString(nameof(name), this.name);
writer.WriteStartElement(nameof(set));
writer.WriteAttributeString(nameof(rarity), this.rarity);
writer.WriteString(this.set);
writer.WriteEndElement();
}
}
如果你的 class 很大,你只需要在 XML 中做一点改变,有时实现 IXmlSerializable 是一团糟(你必须保存所有属性并且只保存一两个,做一点改变)。在这些情况下,您可以使用属性和一些小助手 classes 来获得相同的结果。这个想法是告诉 XML 序列化器不要序列化一些 属性 并使用另一个伪造的 属性 来进行序列化。
例如,使用您想要的 XML 结构创建集合 class:
public class XmlSet
{
private readonly card _card;
public XmlSet()
{
this._card = new card();
}
public XmlSet(card card)
{
this._card = card;
}
[XmlText]
public string set
{
get { return this._card.set; }
set { this._card.set = value; }
}
[XmlAttribute]
public string rarity
{
get { return this._card.rarity; }
set { this._card.rarity = value; }
}
}
它只是一个包装器,具有您想要的 XML 属性。您 get/set 值 from/to 您的 card
对象。
然后,在你的卡片class中,忽略集合属性并序列化假的属性:
public class card
{
public string name = "Cool Card";
[XmlIgnore]
public string rarity = "common";
[XmlIgnore]
public string set = "S1";
// Added to serialization
private XmlSet _xmlSetNode;
[XmlElement("set")]
public XmlSet XmlSet
{
get
{
this._xmlSetNode = this._xmlSetNode ?? new XmlSet(this);
return this._xmlSetNode;
}
set { this._xmlSetNode = value; }
}
}