5

私は Windows ストア アプリケーションに取り組んでいます。

次の手動で作成された Fault クラスがあります。

[XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/", ElementName = "Fault")]
public partial class SoapFault
{
    [XmlElement(Form = XmlSchemaForm.Unqualified, ElementName = "faultcode")]
    public String FaultCode { get; set; }

    [XmlElement(Form = XmlSchemaForm.Unqualified, ElementName = "faultstring")]
    public String FaultDescription { get; set; }

    [XmlElement(Form = XmlSchemaForm.Unqualified, ElementName = "detail")]
    public InnerException[] Detail { get; set; }
}

    [XmlType(Namespace = "http://my.namespace.com", TypeName = "InnerException")]
    public partial class InnerException 
    {
        [XmlElement(Form = XmlSchemaForm.Unqualified, ElementName = "message")]
        public String Message { get; set; }
    }

これは、私が読もうとしているサーバーの応答です:

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><env:Body><env:Fault><faultcode>env:Server</faultcode><faultstring>internal error</faultstring><detail><ns2:InnerException xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://ns1.my.namespace.com" xmlns:ns2="http://my.namespace.com" xmlns:ns3="http://ns3.my.namespace.com"><message>internal error</message></ns2:InnerException ></detail></env:Fault></env:Body></env:Envelope>

私がそれを読み取ろうとしている方法は次のとおりです。

using (XmlReader reader = XmlReader.Create(await response.Content.ReadAsStreamAsync()))
{
    string SoapNamespace = "http://schemas.xmlsoap.org/soap/envelope/";
    try
    {
         var serializer = new XmlSerializer(typeof(SoapFault));

         reader.ReadStartElement("Envelope", SoapNamespace);
         reader.ReadStartElement("Body", SoapNamespace);

         var fault = serializer.Deserialize(reader) as SoapFault;

         reader.ReadEndElement();
         reader.ReadEndElement();
    }
    catch(Exception ex)
    {
         throw new Exception("Exception was thrown:" + ex.Message);
    }
}

名前空間を追加して XmlElement 属性を変更しようとしましたが、常に SoapFault の Detail プロパティが NULL になります。タイプをオブジェクトに変更すると、少なくともデータを含む XmlNode セットを取得します。

シリアル化でインスタンス化された正しいクラスを取得するには、このコードで何を変更する必要がありますか?

注意: 残念ながら、手動で呼び出しを作成することを余儀なくされており、自動生成されたコードを使用することはできません。

4

1 に答える 1

7

How to Deserialize XML document に大いに触発されたので、これでうまくいくはずです。

次のようにクラスを生成しました。

  1. Xml サーバーの応答をディスクに保存します (c:\temp\reply.xml)。
  2. xsd c:\temp\reply.xml /o:"c:\temp"
  3. xsd c:\temp\reply.xsd reply_app1.xsd /classes /o:"c:\temp"
  4. プロジェクトに reply_app1.cs を追加します。

これにより、次の結果が得られました。

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.269
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.Xml.Serialization;

// 
// This source code was auto-generated by xsd, Version=4.0.30319.1.
// 

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://schemas.xmlsoap.org/soap/envelope/", IsNullable=false)]
public partial class Envelope {

    private EnvelopeBody[] itemsField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Body")]
    public EnvelopeBody[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
public partial class EnvelopeBody {

    private EnvelopeBodyFault[] faultField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Fault")]
    public EnvelopeBodyFault[] Fault {
        get {
            return this.faultField;
        }
        set {
            this.faultField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
public partial class EnvelopeBodyFault {

    private string faultcodeField;

    private string faultstringField;

    private EnvelopeBodyFaultDetail detailField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string faultcode {
        get {
            return this.faultcodeField;
        }
        set {
            this.faultcodeField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string faultstring {
        get {
            return this.faultstringField;
        }
        set {
            this.faultstringField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public EnvelopeBodyFaultDetail detail {
        get {
            return this.detailField;
        }
        set {
            this.detailField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
public partial class EnvelopeBodyFaultDetail {

    private InnerException innerExceptionField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace="http://my.namespace.com")]
    public InnerException InnerException {
        get {
            return this.innerExceptionField;
        }
        set {
            this.innerExceptionField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://my.namespace.com")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://my.namespace.com", IsNullable=false)]
public partial class InnerException {

    private string messageField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string message {
        get {
            return this.messageField;
        }
        set {
            this.messageField = value;
        }
    }
}

はい、自動生成されますが、逆シリアル化できるクラスを作成する最も簡単な方法だと思いました。あなたはこのようにすることができます:

XmlDocument document = new XmlDocument();
document.Load(Server.MapPath("~/Data/reply.xml"));

System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Envelope));
Envelope envelope = (Envelope)serializer.Deserialize(new StringReader(document.OuterXml));

Detailプロパティを正しくピックアップしたもの。あなたの場合XmlReader、 my の代わりに以前と同じように使用new StringReader(document.OuterXml)し、 using ブロックなどでラップする必要があります。

逆シリアル化されたオブジェクトのプロパティ名の一部は、クラスにあったものと正確に一致しないことに注意してくださいSoapFault(たとえば、現在は と呼ばれていますEnvelope)。プロパティの一部は、単一のオブジェクトではなく配列として表現されていますが、必要に応じて Xsd を微調整することもできます。

于 2012-10-12T10:18:42.573 に答える