在没有包装类的情况下将固定属性添加到XmlElement

时间:2017-04-25 07:41:27

标签: c# xml xmlserializer

我有以下样本结构的类:

public class DataClass{

    public String Field1{ get; set; }
    public Int32 Field2{ get; set; }
    public Int32 Field3{ get; set; }

}

我必须为每个字段添加一个固定属性,以便输出如下:

<DataClass>
   <Field1 code="code#1">Value of Field1</Field1>
   <Field2 code="code#2">Value of Field2</Field2>
   <Field3 code="code#3">Value of Field3</Field3>
</DataClass>

如果不为每个字段编写包装类,这是否可行? 类似的东西:

public class DataClass{

    [XmlElement(FixedAttribute="code#1")]
    public String Field1{ get; set; }

    [XmlElement(FixedAttribute="code#2")]
    public Int32 Field2{ get; set; }

    [XmlElement(FixedAttribute="code#3")]
    public Int32 Field3{ get; set; }

}

亲切的问候

3 个答案:

答案 0 :(得分:1)

您可以编写自定义序列化程序,而不是使用内置的序列化程序使用Xml Linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication49
{
    class Program
    {

        static void Main(string[] args)
        {
            XElement dataClass = new XElement("DataClass");

            for(int i = 1; i <= 3; i++)
            {
                XElement field = new XElement("Field" + i.ToString(), new object[] {
                    new XAttribute("code", "code#" + i.ToString()),
                    "Value of Field" + i.ToString()
                });
                dataClass.Add(field);
            }

        }
    }
}

答案 1 :(得分:1)

不,XML属性不提供此类功能。一种选择是DataClass实施IXmlSerializable。这使您可以完全控制输出XML。您必须自己序列化所有属性,但由于您必须为每个属性提供代码属性,所以它并不是那么糟糕。如果你有很多DataClass es,你可以考虑创建一个自定义属性来装饰属性并将序列化逻辑移动到基类中,或者如果所有DataClass es的公共基类不方便,把它放到一个单独的助手类中。然后IXmlSerializable.WriteXml将调用此自定义逻辑。如果您控制DataClass es,我认为这是更好的选择。

更为hacky的替代方法是为DataClass创建一个包装器,它将包装的DataClass对象的序列化委托给常规XML序列化程序,但替换将添加的自定义XmlWriter XML属性与属性对应的XML元素。

答案 2 :(得分:0)

您可以使用自定义xml编写器:

public class DataClassWriter : XmlTextWriter
{
    public DataClassWriter(string url) : base(url, Encoding.UTF8) { }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        if (localName.StartsWith("Field"))
        {
            base.WriteStartElement(prefix, localName, ns);
            base.WriteAttributeString("code", "code#" + localName.Substring(5));
        }
        else
            base.WriteStartElement(prefix, localName, ns);
    }
}

使用:

var xs = new XmlSerializer(typeof(DataClass));

using (var writer = new DataClassWriter("out.xml"))
    xs.Serialize(writer, data);