Xmlserializer - Сопряжение элемента-атрибута (исправлено) - PullRequest
1 голос
/ 09 апреля 2009

XmlSerializer делает все, что я хочу, с одним исключением. Мне нужно связать элемент с другим элементом в качестве атрибута этого элемента. Я не хочу писать полностью настраиваемый метод сериализации. Вот мой класс:

public class Transaction
{
   [XmlElement("ID")]
   public int m_id;

   [XmlElement("TransactionType")]
   public string m_transactiontype;

   [XmlAttribute("TransactionTypeCode")]
   public string m_transactiontypecode;
}

Я создаю и сериализирую следующим образом:

   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());

Дает мне:

   <Transaction TransactionTypeCode="520">
     <ID>1</ID>
     <TransactionType>Withdrawal</TransactionType> 
   </Transaction>

Я хочу:

   <Transaction>
     <ID>1</ID>
     <TransactionType TransactionTypeCode="520">Withdrawal</TransactionType>
   </Transaction>

Кто-то (Крис Доггет) предложил:

   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; 
   }

Использование класса TransactionType выглядит многообещающе - можете ли вы показать мне, как создавать экземпляры классов перед сериализацией?

Спасибо!

Ответы [ 7 ]

2 голосов
/ 08 апреля 2009
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; 
}

дает мне это:

<?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>

К сожалению, «Тип» - это фактический тип в .NET, поэтому вы не можете использовать его (как минимум в верхнем регистре) в качестве имени поля.

1 голос
/ 28 апреля 2009

Предполагая этот код для ваших типов:

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;
}

Этот код будет инициализировать и сериализовать так, как вы хотите:

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());
    }
}
1 голос
/ 08 апреля 2009

Я считаю, что единственный способ сделать это - создать класс Type (с плохим именем, учитывая, что это также ключевое слово в платформе ...) со свойством члена TypeCode. Тогда у вас есть экземпляр Type или ссылка как часть класса Transaction.

0 голосов
/ 09 апреля 2009

ОК, давайте удалим проблему «тип является типом в .NET» (мой плохой):

   public class Transaction
   {
       [XmlElement("ID")]
       public int m_id;

       [XmlElement("TransactionType")]
       public string m_transactiontype;

       [XmlAttribute("TransactionTypeCode")]
       public string m_transactiontypecode;
   }

Я создаю и сериализирую следующим образом:

   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());

Дает мне:

<Transaction TransactionTypeCode="520">
  <ID>1</ID>
  <TransactionType>Withdrawal</TransactionType>
</Transaction>

Я хочу:

<Transaction>
  <ID>1</ID>
  <TransactionType TransactionTypeCode="520">Withdrawal</TransactionType>
</Transaction>

Использование класса TransactionType выглядит многообещающе. Можете ли вы показать мне, как создавать экземпляры классов перед сериализацией?

Спасибо!

0 голосов
/ 08 апреля 2009

Ваш желаемый XML не совпадает с тем, как вы размещаете свои объекты в своем коде.

Если вы читаете XML, вы говорите следующее ...

Транзакция содержит два элемента: идентификатор и тип. Тип имеет атрибут с именем TypeCode

Если вы посмотрите на объект, который пытаетесь создать, вы скажете следующее ...

Транзакция содержит три свойства: ID, Type и TypeCode

... вы можете увидеть разрыв между ними. Вы должны согласовать цели каждого из них, чтобы получить правильную сериализацию (измените либо класс, либо xml так, чтобы два согласовали то, что вы пытаетесь передать).

0 голосов
/ 08 апреля 2009

Реализация IXmlSerializable и использование Linq to XML для создания вашего сериализованного объекта .

Таким образом, вы можете точно контролировать, как выглядит ваш xml.

Лично я бы отбросил XmlSerialization, пошел бы с XAML и забыл о попытке получить мой XML внешний вид . Это может выглядеть как дерьмо, пока это работает!

0 голосов
/ 08 апреля 2009

Полагаю, вам следует создать отдельный класс с полями Type и TypeCode. Украсьте TypeCode с помощью [XmlAttribute] и введите с помощью [XmlText].

...