1

C# オブジェクトに逆シリアル化したい次の形式の xml を含むストリームがあります。

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<OrganisationMetaData xmlns="urn:organisationMetaDataSchema">
   <Organisations>
     <Organisation>
       <Code>XXX</Code>
       <Name>Yyyyyy</Name>...

私はこれを文字列で何度も実行しましたが、ストリームでは、名前空間属性をすべての複雑な要素に親切に追加しています。xmlns 属性を削除しただけで、スキーマに対する検証を忘れると、空の xmlns 属性が追加されるだけです。私が抱えている問題は、XmlSerializer (?) の Deserialize メソッドが、属性を想定していないというエラーをスローすることです。クラスを XmlRoot 属性と XmlType 属性で装飾しようとしましたが、何も変わりませんでした。

これが私がデシリアライズしたいクラスです

[XmlRoot(
   ElementName = "OrganisationMetaData", 
   Namespace = "urn:organisationMetaDataSchema")]
public class OrganisationMetaData
{
    public List<Organisation> Organisations { get; set; }
}

[XmlType(
   TypeName = "Organisation", 
   Namespace = "urn:organisationMetaDataSchema")]
public class Organisation
{
   public string Code {get; set;}

   public string Name {get; set;}
}

作業を行うために使用されている方法は次のとおりです

 public IList<Organisation> DeserializeOrganisations(Stream stream)
    {
        var serializer = new XmlSerializer(typeof(OrganisationMetaData));

        var mappingAssembly = //Resource in another assembly

        var schemas = new XmlSchemaSet();
        schemas.Add(
            "urn:organisationMetaDataSchema",
            XmlReader.Create(
                mappingAssembly.GetManifestResourceStream(
                    // An xml schema
                    )
                )
            );
        var settings = new XmlReaderSettings()
                           {
                               ValidationType = ValidationType.Schema,
                               Schemas = schemas,
                               ValidationFlags =
                     XmlSchemaValidationFlags.ReportValidationWarnings
                           };            

        settings.ValidationEventHandler += settings_ValidationEventHandler;
        var reader = XmlReader.Create(stream, settings);

        var metaData= (OrganisationMetaData)serializer.Deserialize(reader);
        return metaData.Organisations.ToList();
    }

私は DataContractSerializer を使用してこれを試しましたが、それは学習する独自の機会をもたらします。そのため、XmlSerializer を機能させるために属性に入れるべきものを誰かが助けることができれば、それは素晴らしいことです.

どんな助けでも感謝します、ありがとう。

4

2 に答える 2

1

ここで重要なのは、[XmlRoot]はクラスなどのルート タイプにのみ適用できるということです。a をルートとして使用している場合は機能しList<>ませんが、 でそれをシムでき[XmlElement]ます。私はStream(経由でEncoding.UTF8)アプローチを使用していますが、これは実際にはIMOの問題の核心ではないことに注意してください(ルートタイプは次のとおりです):

[XmlRoot(Namespace="urn:organisationMetaDataSchema")]
public class Organisations
{
    private readonly List<Organisation> items = new List<Organisation>();
    [XmlElement("Organisation")]
    public List<Organisation> Items { get { return items; } }

}
public class Organisation
{
    public string Code { get; set; }
    public string Name { get; set; }
}
static class Program
{
    static void Main()
    {
        string xml = @"<?xml version='1.0' encoding='utf-8' standalone='yes'?><Organisations xmlns='urn:organisationMetaDataSchema'><Organisation><Code>XXXX</Code><Name>YYYYYYYY</Name></Organisation></Organisations>";
        XmlSerializer ser = new XmlSerializer(typeof(Organisations));
        using (Stream input = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
        {
            Organisations orgs = (Organisations)ser.Deserialize(input);
        }
    }
}
于 2010-03-04T12:15:41.283 に答える
0

データコントラクトシリアライザーを使用するようにコードを変更することになりました。名前空間に関するより明白なエラーが発生し、スキーマに対してxmlストリームを検証するリーダーを作成し、ストリームを巻き戻して、逆シリアル化した別のリーダーで再度使用できるようになりました。 xml。

この質問を読んだことで、xml要素をアルファベット順に並べる必要があるという落とし穴がわかりました。また、列挙型であるクラスのプロパティを逆シリアル化するときに、これが存在することを要求する必要があることもわかりました(結局、null許容ではありません)。

これにより、一部の値が省略されたxmlノードがあるという別のエラーが発生しました(スキーマでは問題ありません)が、データコントラクトはこれらが順番に並んでいることを期待していたため、これを明示的に指定する必要がありました。

私はこのようなデータメンバー属性になりました

[DataMember(
        Name = "MyEnumType", 
        EmitDefaultValue = false, 
        IsRequired = true, 
        Order = 3)] 
//Just assume I added this prop after my Code, and Name properties from above

これを見て時間を割いてくれたMarcに感謝します。

于 2010-03-09T16:30:06.843 に答える