Reputation: 43
Let's say I have the following code, and want to serialize into the XML below the code:
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>
The line [XmlAttribute(type)]
will result in an error.
Is there anyway to change the attribute name by passing on a string variable?
Thank you in advance.
EDIT: I must apologise I overlooked such an easy solution. Thank you for your answers. Also, thank you Ben and dbc for suggesting an improvement on the design.
Upvotes: 4
Views: 1398
Reputation: 117016
You can use [XmlAnyAttribute]
for this purpose. It specifies that the member (a field that returns an array of XmlAttribute
objects) can contain any XML attributes. Note that a property can be used as well as a field to construct and return a single attribute with the required name and value:
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. A valid XML name must, for instance, begin with a letter, not a number.
Example fiddle.
However, using fixed attributes such as type="drink" name="tea"
may make it easier to create an XML schema down the road if required, so you might rethink your design. [XmlAnyAttribute]
corresponds to the schema element xsd:anyAttribute
which allows for any number of attributes of any name to appear. You would want to specify that there must be exactly one attribute of any name for your <OwnedObjects>
element.
Upvotes: 3