在没有包装器的情况下向 XmlElement 添加固定属性 class
Add fixed attribute to XmlElement without a wrapper class
我有 class 以下示例结构:
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>
如果不为每个字段编写包装器 class,这可能吗?
类似于:
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; }
}
亲切的问候
您可以编写自定义序列化程序,而不是使用 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);
}
}
}
}
不,XML 属性不提供此类功能。一种选择是让 DataClass
实施 IXmlSerializable
。这使您可以完全控制输出 XML。您必须自己序列化所有属性,但是由于您无论如何都必须为每个 属性 提供代码属性,所以这还不错。如果你有很多 DataClass
es,你可能会考虑创建一个自定义属性来装饰属性,并将序列化逻辑移动到一个基础 class 或者,如果一个公共基础 class 用于所有 DataClass
es不方便,放到单独的helper中class。 IXmlSerializable.WriteXml
然后会调用此自定义逻辑。如果你控制 DataClass
es,我认为这是更好的选择。
一个更 hacky 的替代方法是为 DataClass
创建一个包装器,它将包装的 DataClass
对象的序列化委托给常规的 XML 序列化程序,但替换为自定义 XmlWriter
会将您的 XML 属性添加到对应于属性的 XML 元素。
您可以使用自定义 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);
我有 class 以下示例结构:
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>
如果不为每个字段编写包装器 class,这可能吗? 类似于:
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; }
}
亲切的问候
您可以编写自定义序列化程序,而不是使用 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);
}
}
}
}
不,XML 属性不提供此类功能。一种选择是让 DataClass
实施 IXmlSerializable
。这使您可以完全控制输出 XML。您必须自己序列化所有属性,但是由于您无论如何都必须为每个 属性 提供代码属性,所以这还不错。如果你有很多 DataClass
es,你可能会考虑创建一个自定义属性来装饰属性,并将序列化逻辑移动到一个基础 class 或者,如果一个公共基础 class 用于所有 DataClass
es不方便,放到单独的helper中class。 IXmlSerializable.WriteXml
然后会调用此自定义逻辑。如果你控制 DataClass
es,我认为这是更好的选择。
一个更 hacky 的替代方法是为 DataClass
创建一个包装器,它将包装的 DataClass
对象的序列化委托给常规的 XML 序列化程序,但替换为自定义 XmlWriter
会将您的 XML 属性添加到对应于属性的 XML 元素。
您可以使用自定义 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);