0

편집 : 사람이 솔루션을 찾고 여기에 오는 경우 - 코드가 아래에 업데이트되어 올바르게 .NET을 대상으로 C#을 사용 허용 대답XML의 역 직렬화 오류 - 예상치 못한 '하는 endElement'


덕분에 작동 4.5.3, C# 클래스 인스턴스에 웹 API REST XML 응답을 역 직렬화하려고합니다.

내 질문은 : 어떻게해야 할 일을하도록이 코드를 수정할 수 있습니까? XML 응답을 C# 클래스 인스턴스로 올바르게 역 직렬화합니다. 여기

Message: Error in line 1 position 226. 'EndElement' 'matchset' from namespace 'urn:expasy:scanprosite' is not expected. Expecting element 'n_match'. 

Source: System.Runtime.Serialization 

StackTrace: 
at System.Runtime.Serialization.XmlObjectSerializerReadContext.ThrowRequiredMemberMissingException(XmlReaderDelegator xmlReader, Int32 memberIndex, Int32 requiredIndex, XmlDictionaryString[] memberNames) 
at ReadmatchsetFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[]) 
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context) 
at System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader) 
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract) 
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns) 
at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver) 
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver) 
at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlReader reader) 
at System.Net.Http.Formatting.XmlMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger) 
at System.Net.Http.Formatting.XmlMediaTypeFormatter.ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger) 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at System.Net.Http.HttpContentExtensions.<ReadAsAsyncCore>d__0`1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
at ConsoleApplication4.Prosite.<XmlDeserialize>d__1.MoveNext() in C:\Users\Aaron\Documents\Visual Studio 14\Projects\ConsoleApplication4\ConsoleApplication4\Prosite.cs:line 22 

콘솔 윈도우 프로그램에서 출력 (애드 팍 미결정) : I 추가 한 이후

는 예외가 발생하고, 속성에 '= TRUE 애드 팍'

n_match: 
n_seq: 
matchset.match.length: 0 
여기

using System; 
using System.Net.Http; 
using System.Net.Http.Headers; 
using System.Threading.Tasks; 

namespace ConsoleApplication4 
{ 
    public static class Prosite 
    { 
     public static async Task<string> GetPrositeXML() 
     { 
      using (var client = new HttpClient()) 
      { 
       client.BaseAddress = new Uri("http://www.expasy.org/"); 
       client.DefaultRequestHeaders.Accept.Clear(); 
       client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml")); 

       // HTTP GET 
       HttpResponseMessage response = await client.GetAsync("cgi-bin/prosite/PSScan.cgi?seq=ENTK_HUMAN&output=xml"); 
       if (response.IsSuccessStatusCode) 
       { 
        return await response.Content.ReadAsStringAsync();//AsAsync<matchset>(); 
       } 
      } 

      return null; 
     } 
    } 
} 

가 있습니다 : 여기

는 HTTP 요청 및 드 - 직렬화 코드 콘솔 응용 프로그램 코드 : 여기

using System; 
using System.Diagnostics; 
using System.IO; 
using System.Xml; 
using System.Xml.Serialization; 

namespace ConsoleApplication4 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var matchsetTask = Prosite.GetPrositeXML(); 

      var xmlString = matchsetTask.Result; 

      var matchset = xmlString.LoadFromXML<matchset>(); 

      if (matchset != null) 
      { 
       Console.WriteLine("n_match: " + matchset.n_match); 
       Console.WriteLine("n_seq: " + matchset.n_seq); 
       Console.WriteLine("matchset.match.length: " + matchset.match.Length); 

       foreach (var match in matchset.match) 
       { 
        Console.WriteLine("level: " + match.level); 
        Console.WriteLine("level_tag: " + match.level_tag); 
        Console.WriteLine("score: " + match.score); 
        Console.WriteLine("sequence_ac: " + match.sequence_ac); 
        Console.WriteLine("sequence_db: " + match.sequence_db); 
        Console.WriteLine("sequence_id: " + match.sequence_id); 
        Console.WriteLine("signature_ac: " + match.signature_ac); 
        Console.WriteLine("signature_id: " + match.signature_id); 
        Console.WriteLine("start: " + match.start); 
        Console.WriteLine("stop: " + match.stop); 
        Console.WriteLine(""); 
       } 
      } 

      Console.ReadKey(); 
     } 
    } 
} 

루트 노드의 클래스입니다 'matchset'모델 : 여기

using System; 
using System.Runtime.Serialization; 
using System.Xml.Serialization; 
using System.ServiceModel; 

namespace ConsoleApplication4 
{ 
    [Serializable] 
    [XmlSerializerFormat] 
    [DataContract(Name = "match", Namespace = "")] 
    public class match 
    { 
     [DataMember(Name = "sequence_ac")] 
     [XmlElement("sequence_ac")] 
     public string sequence_ac; 

     [DataMember(Name = "sequence_id")] 
     [XmlElement("sequence_id")] 
     public string sequence_id; 

     [DataMember(Name = "sequence_db")] 
     [XmlElement("sequence_db")] 
     public string sequence_db; 

     [DataMember(Name = "start")] 
     [XmlElement("start")] 
     public string start; 

     [DataMember(Name = "stop")] 
     [XmlElement("stop")] 
     public string stop; 

     [DataMember(Name = "signature_ac")] 
     [XmlElement("signature_ac")] 
     public string signature_ac; 

     [DataMember(Name = "signature_id")] 
     [XmlElement("signature_id")] 
     public string signature_id; 

     [DataMember(Name = "level_tag")] 
     [XmlElement("level_tag")] 
     public string level_tag; 

     [DataMember(Name = "score")] 
     [XmlElement("score")] 
     public string score; 

     [DataMember(Name = "level")] 
     [XmlElement("level")] 
     public string level; 
    } 
} 

: 여기

using System; 
using System.Runtime.Serialization; 
using System.Xml.Serialization; 
using System.ServiceModel; 

namespace ConsoleApplication4 
{ 
    [Serializable] 
    [XmlSerializerFormat] 
    [DataContract(Name = "matchset", Namespace = "urn:expasy:scanprosite")] 
    [XmlRoot(ElementName = "matchset", Namespace = "urn:expasy:scanprosite")] 
    public class matchset 
    { 
     [DataMember(Name = "match")] 
     [XmlElement("match")] 
     public match[] match; 

     [DataMember(Name = "n_match", IsRequired = true)] 
     [XmlAttribute("n_match")] 
     public string n_match; 

     [DataMember(Name = "n_seq", IsRequired = true)] 
     [XmlAttribute("n_seq")] 
     public string n_seq; 
    } 
} 

는 '일치'모델에 대한 코드입니다 deserialize되고있는 XML입니다 :

<?xml version="1.0" encoding="UTF-8"?> 
<matchset xmlns="urn:expasy:scanprosite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:expasy:scanprosite http://expasy.org/tools/scanprosite/scanprosite.xsd" n_match="13" n_seq="1"> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>54</start> 
     <stop>169</stop> 
     <signature_ac>PS50024</signature_ac> 
     <signature_id>SEA</signature_id> 
     <score>32.979</score> 
     <level>0</level> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>183</start> 
     <stop>222</stop> 
     <signature_ac>PS50068</signature_ac> 
     <signature_id>LDLRA_2</signature_id> 
     <score>10.75</score> 
     <level>0</level> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>197</start> 
     <stop>221</stop> 
     <signature_ac>PS01209</signature_ac> 
     <signature_id>LDLRA_1</signature_id> 
     <level_tag>(0)</level_tag> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>225</start> 
     <stop>334</stop> 
     <signature_ac>PS01180</signature_ac> 
     <signature_id>CUB</signature_id> 
     <score>13.293</score> 
     <level>0</level> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>345</start> 
     <stop>504</stop> 
     <signature_ac>PS50060</signature_ac> 
     <signature_id>MAM_2</signature_id> 
     <score>42.203</score> 
     <level>0</level> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>391</start> 
     <stop>431</stop> 
     <signature_ac>PS00740</signature_ac> 
     <signature_id>MAM_1</signature_id> 
     <level_tag>(0)</level_tag> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>524</start> 
     <stop>634</stop> 
     <signature_ac>PS01180</signature_ac> 
     <signature_id>CUB</signature_id> 
     <score>17.206</score> 
     <level>0</level> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>642</start> 
     <stop>678</stop> 
     <signature_ac>PS50068</signature_ac> 
     <signature_id>LDLRA_2</signature_id> 
     <score>13.3</score> 
     <level>0</level> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>655</start> 
     <stop>677</stop> 
     <signature_ac>PS01209</signature_ac> 
     <signature_id>LDLRA_1</signature_id> 
     <level_tag>(0)</level_tag> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>678</start> 
     <stop>788</stop> 
     <signature_ac>PS50287</signature_ac> 
     <signature_id>SRCR_2</signature_id> 
     <score>16.02</score> 
     <level>0</level> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>785</start> 
     <stop>1019</stop> 
     <signature_ac>PS50240</signature_ac> 
     <signature_id>TRYPSIN_DOM</signature_id> 
     <score>39.104</score> 
     <level>0</level> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>821</start> 
     <stop>826</stop> 
     <signature_ac>PS00134</signature_ac> 
     <signature_id>TRYPSIN_HIS</signature_id> 
     <level_tag>(0)</level_tag> 
    </match> 
    <match> 
     <sequence_ac>P98073</sequence_ac> 
     <sequence_id>ENTK_HUMAN</sequence_id> 
     <sequence_db>sp</sequence_db> 
     <start>965</start> 
     <stop>976</stop> 
     <signature_ac>PS00135</signature_ac> 
     <signature_id>TRYPSIN_SER</signature_id> 
     <level_tag>(0)</level_tag> 
    </match> 
</matchset> 
허용 대답에 @dbc에서 제공 1,363,210

XmlSerializationHelper 클래스 :

using System.IO; 
using System.Xml; 
using System.Xml.Serialization; 

namespace ConsoleApplication4 
{ 
    public static class XmlSerializationHelper 
    { 
     public static string GetXml<T>(T obj, XmlSerializer serializer, bool omitStandardNamespaces) 
     { 
      using (var textWriter = new StringWriter()) 
      { 
       XmlWriterSettings settings = new XmlWriterSettings(); 
       settings.Indent = true;  // For cosmetic purposes. 
       settings.IndentChars = " "; // For cosmetic purposes. 
       using (var xmlWriter = XmlWriter.Create(textWriter, settings)) 
       { 
        if (omitStandardNamespaces) 
        { 
         XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
         ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines. 
         serializer.Serialize(xmlWriter, obj, ns); 
        } 
        else 
        { 
         serializer.Serialize(xmlWriter, obj); 
        } 
       } 
       return textWriter.ToString(); 
      } 
     } 

     public static string GetXml<T>(this T obj, XmlSerializer serializer) 
     { 
      return GetXml(obj, serializer, false); 
     } 

     public static string GetXml<T>(this T obj, bool omitNamespace) 
     { 
      XmlSerializer serializer = new XmlSerializer(obj.GetType()); 
      return GetXml(obj, serializer, omitNamespace); 
     } 

     public static string GetXml<T>(this T obj) 
     { 
      return GetXml(obj, false); 
     } 

     public static T LoadFromXML<T>(this string xmlString) 
     { 
      return xmlString.LoadFromXML<T>(new XmlSerializer(typeof(T))); 
     } 

     public static T LoadFromXML<T>(this string xmlString, XmlSerializer serial) 
     { 
      T returnValue = default(T); 

      using (StringReader reader = new StringReader(xmlString)) 
      { 
       object result = serial.Deserialize(reader); 
       if (result is T) 
       { 
        returnValue = (T)result; 
       } 
      } 
      return returnValue; 
     } 
    } 
} 

감사합니다.

+2

xml이 유효하지 않습니까? 그렇습니다.'xmlns'는 ... 횡설수설입니까? 이것은 거의 확실히 XML 네임 스페이스와 관련이 있습니다. ''은 (는) ''또는 '과 동일하지 않습니다. 나는 당신이'xmlns = "urn : expasy : scanprosite"'를 의미한다고 생각하고있다. 또는...? –

+0

@MarcGravell 스택 오버플로에 대해 들여 쓰기 탭을 만들기 위해 XML을 Visual Studio에 붙여 넣었습니다. 자동 서식 지정은 일부 텍스트를 변경해야합니다. 나는 그것을 지금 다시 붙여 넣었다. 그 점을 지적 해 주셔서 감사합니다. – Aalawlx

답변

2

클래스에는 데이터 계약 속성과 XmlSerializer 속성이 혼합되어 있습니다. 나는 [XmlSerializerFormat] 속성의 응용 때문에 당신이 XmlSerializer을 사용하고 있다고 가정 할 것입니다.

  1. matchsetXmlRoot 속성을 다시 넣어 :이 경우, 다음을 수행해야

    [Serializable] 
    [XmlSerializerFormat] 
    [DataContract(Name = "matchset", Namespace = "urn:expasy:scanprosite")] 
    [XmlRoot(ElementName = "matchset", Namespace = "urn:expasy:scanprosite")] 
    public class matchset 
    { 
    
  2. 변경 public match[] matchXmlElement에 :

    [DataMember(Name = "match")] 
        [XmlElement("match")] 
        public match[] match 
        { 
         get { return this.matchField; } 
         set { this.matchField = value; } 
        } 
    

내가 일을 한 후 주어진 XML 문자열을 읽을 수 있습니까? 게시하다.

답변은 수정 된 클래스가 아닌 원래 클래스를 기반으로합니다. 다음은 테스트 한 방법입니다.

public static class TestMatchSet 
{ 
    public static void Test() 
    { 
     var xml = XmlProvider.GetXml(); // Returns the long XML string from the post. 
     var matchSet = XmlSerializationHelper.LoadFromXML<matchset>(xml); 

     Debug.WriteLine(matchSet.GetXml()); 
    } 
} 

public static class XmlSerializationHelper 
{ 
    public static string GetXml<T>(T obj, XmlSerializer serializer, bool omitStandardNamespaces) 
    { 
     using (var textWriter = new StringWriter()) 
     { 
      XmlWriterSettings settings = new XmlWriterSettings(); 
      settings.Indent = true;  // For cosmetic purposes. 
      settings.IndentChars = " "; // For cosmetic purposes. 
      using (var xmlWriter = XmlWriter.Create(textWriter, settings)) 
      { 
       if (omitStandardNamespaces) 
       { 
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
        ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines. 
        serializer.Serialize(xmlWriter, obj, ns); 
       } 
       else 
       { 
        serializer.Serialize(xmlWriter, obj); 
       } 
      } 
      return textWriter.ToString(); 
     } 
    } 

    public static string GetXml<T>(this T obj, XmlSerializer serializer) 
    { 
     return GetXml(obj, serializer, false); 
    } 

    public static string GetXml<T>(this T obj, bool omitNamespace) 
    { 
     XmlSerializer serializer = new XmlSerializer(obj.GetType()); 
     return GetXml(obj, serializer, omitNamespace); 
    } 

    public static string GetXml<T>(this T obj) 
    { 
     return GetXml(obj, false); 
    } 

    public static T LoadFromXML<T>(this string xmlString) 
    { 
     return xmlString.LoadFromXML<T>(new XmlSerializer(typeof(T))); 
    } 

    public static T LoadFromXML<T>(this string xmlString, XmlSerializer serial) 
    { 
     T returnValue = default(T); 

     using (StringReader reader = new StringReader(xmlString)) 
     { 
      object result = serial.Deserialize(reader); 
      if (result is T) 
      { 
       returnValue = (T)result; 
      } 
     } 
     return returnValue; 
    } 
} 
+0

내가 제안한 두 가지 변경 사항을 만들었지 만 동일한 예외가 여전히 발생합니까? 만약 당신이 그것을 가지고 있다면 - 전체 코드를 붙여 넣을 수있는 기회가 있습니까 아니면 다른 제안이 있습니까? 고맙습니다. – Aalawlx

+0

일치 배열을 읽지 못했습니다. 클래스를 복사하고 디버깅 한 후에 "IsRequired"를 추가했습니다. 이제 다시 시작해야할까요? – dbc

+0

예 일치 배열을 읽지는 않지만 속성을 읽지 않습니다. 그러나 제안 된 변경 사항을 적용해도 일치 배열이 읽히지 않았습니다. 그것만으로 개선 될 수 있습니다. – Aalawlx