Десериализация XML дает неверные результаты - PullRequest
1 голос
/ 07 января 2010

Я новичок в XML, использую C # .NET 2.0 / Visual Studio 2005.

У меня есть пример данных в XML, который я хотел бы преобразовать в строго типизированные структуры данных. У меня также есть XSD для этого файла, который я запускал через Visual Studio xsd.exe для генерации кода для него. Я запустил его против System.Xml.Serialization.XmlSerializer Он проделал достойную работу, но нуждается в некоторой настройке.

Запуск теста с использованием этого кода:

static int Main() {
    System.IO.StreamReader str = new System.IO.StreamReader(
        @"C:\xmlstm-2009122816413365.xml");
    System.Xml.Serialization.XmlSerializer xSerializer = new System.Xml.Serialization.XmlSerializer(typeof(AidStatements));
    AidStatements statementDataSet = (AidStatements)xSerializer.Deserialize(str);

    foreach (AssocRecord associations in statementDataSet.AssocRecords) {
        foreach (statementrecord statement in associations.statementrecord) {
            Console.WriteLine(statement.acctno);
        }
    }

    str.Close();

    Console.ReadLine();

    return 0;
}

Там, где тестовый код просто выводит номер счета из каждой записи.

Проблема в том, что сгенерированный код игнорирует половину записей в файле. Я думаю, это связано с элементом <Assoc-Record>.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="Aid-Statements">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" ref="Assoc-Record"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="Assoc-Record">
    <xs:complexType>
        <xs:sequence>
            <xs:element maxOccurs="unbounded" ref="statement-record"/>
        </xs:sequence>
    </xs:complexType>
    </xs:element>
    <xs:element name="statement-record">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="assoc-no"/>
                <xs:element ref="acct-no"/>
                <xs:element ref="acct-no-mask"/>
                <xs:element ref="member-no"/>
                <xs:element ref="cr-code"/>
                <xs:element ref="stm-bal-fwd-date"/>
                <xs:element ref="stm-close-date"/>
                <xs:element ref="stm-due-date"/>
                <xs:element ref="prop-address-info"/>
                <xs:element ref="own-mail-info"/>
                <xs:element ref="messages"/>
                <xs:element ref="balances"/>
                <xs:element ref="trx-detail"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    ...

Сгенерированный код из xsd.exe это (фрагмент):

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute("Aid-Statements", Namespace="", IsNullable=false)]
public partial class AidStatements {

    private statementrecord[] assocRecordField;

    /// <remarks/>
    [System.Xml.Serialization.XmlArrayAttribute("Assoc-Record")]
    [System.Xml.Serialization.XmlArrayItemAttribute("statement-record", typeof(statementrecord), IsNullable=false)]
    public statementrecord[] AssocRecord {
        get {
            return this.assocRecordField;
        }
        set {
            this.assocRecordField = value;
        }
    }
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute("statement-record", Namespace="", IsNullable=false)]
public partial class statementrecord {
    private string assocnoField;
    private string acctnoField;
    private string acctnomaskField;
    private string membernoField;
    private string crcodeField;
    private string stmbalfwddateField;
    private string stmclosedateField;
    private string stmduedateField;
    private propaddressinfo propaddressinfoField;
    private ownmailinfo ownmailinfoField;
    private messages messagesField;
    private balances balancesField;
    private trxrecord[] trxdetailField;
    // Matching properties below this
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute("Assoc-Record", Namespace="", IsNullable=false)]
public partial class AssocRecord {

    private statementrecord[] statementrecordField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("statement-record")]
    public statementrecord[] statementrecord {
        get {
            return this.statementrecordField;
        }
        set {
            this.statementrecordField = value;
        }
    }
}

Похоже, xsd.exe неправильно предполагает что-то о <Assoc-Record>, но ничего из того, что я пробовал до сих пор, не помогло. Попытка установить <Assoc-Record> в качестве атрибута массива (насколько я мог понять) не дала никаких результатов; код выполняется, но <Assoc-Record> не содержит элементов <statement-record> (например, массив нулевой длины).

Кроме того, xsd.exe сначала превратил AidStatements.assocRecordField в двумерный массив, который я изменил на одномерный массив, чтобы заставить его работать в текущем состоянии.

Есть идеи?

1 Ответ

1 голос
/ 07 января 2010

Класс AidStatements должен выглядеть следующим образом:

public partial class AidStatements
{
  [XmlElement("Assoc-Record")]
  public AssocRecord[] AssocRecords;
}

Схема XSD выглядит довольно запутанно - вместо последовательностей, содержащих элементы определенного типа, последовательности содержат ссылки на элемент, и это, вероятно, сбивает с толку xsd.exe (все эти XmlTypeAttribute(AnonymousType=true) выглядят странно).

...