将字符串变量传递给 XMLSerializer 的 XmlAttribute
Pass string variable to XmlAttribute of XMLSerializer
假设我有以下代码,想序列化到代码下面的XML中:
class Human
{
[XmlElement("OwnedObjects")]
public List<WorldObjects> ownedObjects;
}
class WorldObjects
{
[XmlIgnore]
public string type;
[XmlAttribute(type)]
public string name;
public WorldObjects(string _type, string _name)
{
type = _type;
name = _name;
}
}
Human bob = new Human;
bob.ownedObjects = new List<WorldObjects>;
bob.ownedObjects.Add(new WorldObjects(drink, tea));
// Serialize
XML:
<Human>
<OwnedObjects drink="tea" />
</Human>
第 [XmlAttribute(type)]
行将导致错误。
是否可以通过传递字符串变量来更改属性名称?
提前致谢。
编辑:我必须道歉,我忽略了这样一个简单的解决方案。谢谢您的回答。
另外,感谢 Ben 和 dbc 建议对设计进行改进。
您可以使用 [XmlAnyAttribute]
for this purpose. It specifies that the member (a field that returns an array of XmlAttribute
对象)可以包含任何 XML 属性。 请注意,可以使用 属性 以及一个字段来构造和 return 具有所需名称和值的单个属性:
public class WorldObjects
{
[XmlAnyAttribute]
public XmlAttribute [] Attributes
{
get
{
var attr = new XmlDocument().CreateAttribute(XmlConvert.EncodeLocalName(type));
attr.Value = name;
return new[] { attr };
}
set
{
var attr = (value == null ? null : value.SingleOrDefault());
if (attr == null)
name = type = string.Empty;
else
{
type = XmlConvert.DecodeName(attr.Name);
name = attr.Value;
}
}
}
[XmlIgnore]
public string name;
[XmlIgnore]
public string type;
// XmlSerializer required parameterless constructor
public WorldObjects() : this(string.Empty, string.Empty) { }
public WorldObjects(string _type, string _name)
{
type = _type;
name = _name;
}
}
XmlConvert.EncodeLocalName()
is required in cases where the type
string is not a valid XML name。例如,有效的 XML 名称必须以字母而非数字开头。
例子fiddle.
但是,如果需要,使用 type="drink" name="tea"
等固定属性可能会更容易在以后创建 XML 架构,因此您可能会重新考虑您的设计。 [XmlAnyAttribute]
对应于架构元素 xsd:anyAttribute
,它允许出现任意数量的任意名称的属性。您可能希望为您的 <OwnedObjects>
元素指定一个任意名称的属性。
假设我有以下代码,想序列化到代码下面的XML中:
class Human
{
[XmlElement("OwnedObjects")]
public List<WorldObjects> ownedObjects;
}
class WorldObjects
{
[XmlIgnore]
public string type;
[XmlAttribute(type)]
public string name;
public WorldObjects(string _type, string _name)
{
type = _type;
name = _name;
}
}
Human bob = new Human;
bob.ownedObjects = new List<WorldObjects>;
bob.ownedObjects.Add(new WorldObjects(drink, tea));
// Serialize
XML:
<Human>
<OwnedObjects drink="tea" />
</Human>
第 [XmlAttribute(type)]
行将导致错误。
是否可以通过传递字符串变量来更改属性名称?
提前致谢。
编辑:我必须道歉,我忽略了这样一个简单的解决方案。谢谢您的回答。 另外,感谢 Ben 和 dbc 建议对设计进行改进。
您可以使用 [XmlAnyAttribute]
for this purpose. It specifies that the member (a field that returns an array of XmlAttribute
对象)可以包含任何 XML 属性。 请注意,可以使用 属性 以及一个字段来构造和 return 具有所需名称和值的单个属性:
public class WorldObjects
{
[XmlAnyAttribute]
public XmlAttribute [] Attributes
{
get
{
var attr = new XmlDocument().CreateAttribute(XmlConvert.EncodeLocalName(type));
attr.Value = name;
return new[] { attr };
}
set
{
var attr = (value == null ? null : value.SingleOrDefault());
if (attr == null)
name = type = string.Empty;
else
{
type = XmlConvert.DecodeName(attr.Name);
name = attr.Value;
}
}
}
[XmlIgnore]
public string name;
[XmlIgnore]
public string type;
// XmlSerializer required parameterless constructor
public WorldObjects() : this(string.Empty, string.Empty) { }
public WorldObjects(string _type, string _name)
{
type = _type;
name = _name;
}
}
XmlConvert.EncodeLocalName()
is required in cases where the type
string is not a valid XML name。例如,有效的 XML 名称必须以字母而非数字开头。
例子fiddle.
但是,如果需要,使用 type="drink" name="tea"
等固定属性可能会更容易在以后创建 XML 架构,因此您可能会重新考虑您的设计。 [XmlAnyAttribute]
对应于架构元素 xsd:anyAttribute
,它允许出现任意数量的任意名称的属性。您可能希望为您的 <OwnedObjects>
元素指定一个任意名称的属性。