繁体   English   中英

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]会将其添加到父元素而不是下一个同级元素,我无法弄清楚如何在普通字符串元素上获取它,所以目前我的 output 看起来像。

<card rarity="common">
 <name>Cool Card</name>
 <set>S1</set>
</card>

XML 示例文档显示了如何在元素上设置属性的示例,但只有一个具有嵌套字段,而不是一个纯字符串。 是否可以像我第一个发布的示例演示的那样向 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 就是一团糟(你必须保存所有属性,只保存一两个属性,做一点改变)。 在这些情况下,您可以使用属性和一些小的助手类来获得相同的结果。 这个想法是告诉 XML 序列化器不序列化某些属性并使用另一个假属性来进行序列化。

例如,使用所需的 XML 结构创建一个 Set 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 属性。 您从card object 获取/设置值。

然后,在你的卡 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; }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM