问题
The XmlSerializer
does everything I want with one exception. I need to pair an element with another element as an attribute of that element. I don't want to write a completely custom serialize method. Here's my class:
public class Transaction
{
[XmlElement("ID")]
public int m_id;
[XmlElement("TransactionType")]
public string m_transactiontype;
[XmlAttribute("TransactionTypeCode")]
public string m_transactiontypecode;
}
I instantiate and serialize as follows;
Transaction tx = new Transaction();
tx.m_id = 1;
tx.m_transactiontype = "Withdrawal";
tx.m_transactiontypecode = "520";
StringWriter o = new
StringWriter(CultureInfo.InvariantCulture);
XmlSerializer s = new
XmlSerializer(typeof(Transaction));
s.Serialize(o, tx);
Console.Write(o.ToString());
Gives me:
<Transaction TransactionTypeCode="520">
<ID>1</ID>
<TransactionType>Withdrawal</TransactionType>
</Transaction>
I want:
<Transaction>
<ID>1</ID>
<TransactionType TransactionTypeCode="520">Withdrawal</TransactionType>
</Transaction>
Someone (Chris Dogget) suggested:
public class Transaction
{
[XmlElement("ID")]
public int m_id;
public TransactionType m_transactiontype;
}
public class TransactionType
{
public TransactionType(){}
public TransactionType(string type) { this.m_transactiontype = type; }
[XmlTextAttribute]
public string m_transactiontype;
[XmlAttribute("TransactionTypeCode")]
public string m_transactiontypecode;
}
The use of the TransactionType class looks promising - can you show me how you would instantiate the classes before serializing?
Thanks!
回答1:
public class Transaction
{
[XmlElement("ID")]
public int m_id;
public TransactionType type;
}
public class TransactionType
{
public TransactionType(){}
public TransactionType(string type) { this.@Type = type; }
[XmlTextAttribute]
public string @Type;
[XmlAttribute("TypeCode")]
public string typecode;
}
gives me this:
<?xml version="1.0" encoding="utf-16"?>
<Transaction xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>1</ID>
<type TypeCode="520">Withdrawal</type>
</Transaction>
Unfortunately, "Type" is an actual type in .NET, so you can't really use that (uppercase at least) as your field name.
回答2:
I believe the only way to do this is to create a class of Type (bad name though, given that it's a keyword in the framework as well ...) with member property TypeCode. Then you have a Type instance or reference as part of class Transaction.
回答3:
Assuming this code for your types:
public class Transaction
{
public Transaction() { ttype = new TransactionType(); }
[XmlElement("ID")]
public int id;
[XmlElement("TransactionType")]
public TransactionType ttype;
}
public class TransactionType
{
public TransactionType(){}
public TransactionType(string txType) { this.type = txType; }
[XmlText]
public string type;
[XmlAttribute("TransactionTypeCode")]
public string typecode;
}
This code will initialize and serialize the way you want:
public void Run()
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add( "", "" );
Transaction tx = new Transaction();
tx.id = 1;
tx.ttype.type = "Withdrawal";
tx.ttype.typecode = "520";
using (StringWriter o =
new StringWriter(CultureInfo.InvariantCulture))
{
XmlSerializer s = new XmlSerializer(typeof(Transaction));
s.Serialize(o, tx, ns);
Console.Write(o.ToString());
}
}
回答4:
I guess you should create a separate class with Type and TypeCode fields. Decorate TypeCode with [XmlAttribute] and Type with [XmlText].
回答5:
Implement IXmlSerializable and use Linq to XML to construct your serialized object.
This way you can control exactly how your xml looks.
Personally, I'd drop XmlSerialization, go with XAML and forget about trying to get my XML looks. It can look like crap, as long as it works!
回答6:
Your desired XML doesn't line up with the way you're laying out your objects in your code.
If you read the XML you are saying the following...
The transaction contains two elements: ID and Type. Type has an attribute called TypeCode
If you look at the object you're trying to create, you're saying this...
The transaction contains three properties: ID, Type, and TypeCode
...you can see the disconnect between the two. You have to align the goals of each to get proper serialization (modify either the class or the xml so the two align which what you're trying to communicate).
回答7:
OK, let's remove the "'type' is a type in .NET" issue (my bad):
public class Transaction
{
[XmlElement("ID")]
public int m_id;
[XmlElement("TransactionType")]
public string m_transactiontype;
[XmlAttribute("TransactionTypeCode")]
public string m_transactiontypecode;
}
I instantiate and serialize as follows;
Transaction tx = new Transaction();
tx.m_id = 1;
tx.m_transactiontype = "Withdrawal";
tx.m_transactiontypecode = "520";
StringWriter o = new StringWriter(CultureInfo.InvariantCulture);
XmlSerializer s = new XmlSerializer(typeof(Transaction));
s.Serialize(o, tx);
Console.Write(o.ToString());
Gives me:
<Transaction TransactionTypeCode="520">
<ID>1</ID>
<TransactionType>Withdrawal</TransactionType>
</Transaction>
I want:
<Transaction>
<ID>1</ID>
<TransactionType TransactionTypeCode="520">Withdrawal</TransactionType>
</Transaction>
The use of the TransactionType class looks promising - can you show me how you would instantiate the classes before serializing?
Thanks!
来源:https://stackoverflow.com/questions/732314/xmlserializer-control-element-attribute-pairing-revised