0

我針對XSD文件運行SvcUtil.exe以生成類。然後嘗試使用以下代碼行從XML中創建對象。我得到如下所示的錯誤。請參閱下面的詳細代碼。與SvcUtils.exe一起使用時,DataContractSerializer.ReadObject()無法創建對象

PersonType prs = (PersonType)xs.ReadObject(new MemoryStream(File.ReadAllBytes(sFileName))); 

Error in line 3 position 58. Expecting element 'PersonType' from namespace 'http://service.a1.com/base1/2005/'.. Encountered 'Element' with name 'Person', namespace 'http://service.a1.com/base1/2005/'. 

所用命令

svcutil.exe" "C:\Temp\S1\UseXSDExe\UseXSDExe\Sample2\Prs.xsd" /t:code /language:cs /out:C:\SPrxy.cs /dconly 

的完整代碼

(class generated by SvcUtils.exe) 
    [assembly: System.Runtime.Serialization.ContractNamespaceAttribute("http://service.a1.com/base1/2005/", ClrNamespace="service.a1.com.base1._2005")] 
    namespace service.a1.com.base1._2005 
    { 
     using System.Runtime.Serialization; 


     [System.Diagnostics.DebuggerStepThroughAttribute()] 
     [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")] 
     [System.Runtime.Serialization.DataContractAttribute(Name="PersonType", Namespace="http://service.a1.com/base1/2005/")] 
     public partial class PersonType : object, System.Runtime.Serialization.IExtensibleDataObject 
     { 
      private System.Runtime.Serialization.ExtensionDataObject extensionDataField; 

      private string LastNameField; 

      private string FirstNameField; 

      public System.Runtime.Serialization.ExtensionDataObject ExtensionData 
      { 
       get 
       { 
        return this.extensionDataField; 
       } 
       set 
       { 
        this.extensionDataField = value; 
       } 
      } 

      [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true, EmitDefaultValue=false)] 
      public string LastName 
      { 
       get 
       { 
        return this.LastNameField; 
       } 
       set 
       { 
        this.LastNameField = value; 
       } 
      } 

      [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=1)] 
      public string FirstName 
      { 
       get 
       { 
        return this.FirstNameField; 
       } 
       set 
       { 
        this.FirstNameField = value; 
       } 
      } 
     } 
    } 

(code used for converting XML to object) 
    public static void convertToObject(string sFileName) 
    { 
     DataContractSerializer xs = new DataContractSerializer(typeof(PersonType)); 
     PersonType Person = (PersonType)xs.ReadObject(new MemoryStream(File.ReadAllBytes(sFileName))); 

    } 

(XSD)

<?xml version="1.0" encoding="utf-8"?> 
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://service.a1.com/base1/2005/" xmlns:bse1="http://service.a1.com/base1/2005/" elementFormDefault="qualified"> 
     <xs:complexType name="PersonType"> 
      <xs:sequence> 
       <xs:element minOccurs="1" maxOccurs="1" name="LastName" type="xs:string" /> 
       <xs:element minOccurs="0" maxOccurs="1" name="FirstName" type="xs:string" /> 
      </xs:sequence> 
     </xs:complexType> 
     <xs:element name="Person" type="bse1:PersonType"/> 
    </xs:schema> 

(XML)

<?xml version="1.0" encoding="utf-8"?> 
    <pr:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xsi:schemaLocation="http://service.a1.com/base1/2005/ Prs.xsd" 
       xmlns:pr="http://service.a1.com/base1/2005/"> 
     <pr:LastName> Lane </pr:LastName> 
     <pr:FirstName> Fane </pr:FirstName> 
    </pr:Person> 

我在同一個XSD文件上運行XSD.exe。然後我能夠使用XmlSerializer.Deserialize()將XML轉換爲對象。

XSD沒有任何屬性。我已經針對XSD驗證了XML。

請讓我知道爲什麼Deserialize()失敗。

回答

1

你的XSD指定一個根元素名稱和數據類型名稱是不同的:

<xs:element name="Person" type="bse1:PersonType"/> 

svcutil.exe對於這種類型的生成數據合同類,它把類型名稱到數據契約,而不是根元素名稱。這似乎是故意的,請參閱Svcutil generates wrong Name property value in DataContractAttribute。也許它是這樣做的,因爲契約類型本身可以在對象圖中的任何地方重新使用,並且沒有數據契約等價物XmlRoot適用於只有當問題類型是文檔的根元素。

作爲一種解決辦法,你有幾個選擇:

  1. 硬編碼預期的根元素名稱時constructing the serializer

    var xs = new DataContractSerializer(typeof(service.a1.com.base1._2005.PersonType), "Person", "http://service.a1.com/base1/2005/"); 
    
  2. 預載的XML爲XDocument,並用實際的根元素構建串行器時的名稱:

    var doc = XDocument.Load(sFileName); 
        service.a1.com.base1._2005.PersonType person; 
        var xs = new DataContractSerializer(typeof(service.a1.com.base1._2005.PersonType), doc.Root.Name.LocalName, "http://service.a1.com/base1/2005/"); 
        using (var reader = doc.CreateReader()) 
        { 
         person = (service.a1.com.base1._2005.PersonType)xs.ReadObject(reader); 
        } 
    
  3. 或使用XmlSerializer

+0

我在CTOR中傳遞了根名稱並解決了這個問題。這是一個很好的例子,說明爲什麼有一個CTOR採用根名稱。非常感謝Dbc – user1174790