{ "<user xmlns = ''>이 (가) 예상되지 않았습니다.} Twitter XML 역 직렬화


211

OAuth를 통해 Twitter에서 XML을 가져옵니다.

http://twitter.com/account/verify_credentials.xml을 요청 하여 다음 XML을 반환합니다.

<?xml version="1.0" encoding="UTF-8"?>
<user>
  <id>16434938</id>
  <name>Lloyd Sparkes</name>
  <screen_name>lloydsparkes</screen_name>
  <location>Hockley, Essex, UK</location>
  <description>Student</description>
  <profile_image_url>http://a3.twimg.com/profile_images/351849613/twitterProfilePhoto_normal.jpg</profile_image_url>
  <url>http://www.lloydsparkes.co.uk</url>
  <protected>false</protected>
  <followers_count>115</followers_count>
  <profile_background_color>9fdaf4</profile_background_color>
  <profile_text_color>000000</profile_text_color>
  <profile_link_color>220f7b</profile_link_color>
  <profile_sidebar_fill_color>FFF7CC</profile_sidebar_fill_color>
  <profile_sidebar_border_color>F2E195</profile_sidebar_border_color>
  <friends_count>87</friends_count>
  <created_at>Wed Sep 24 14:26:09 +0000 2008</created_at>
  <favourites_count>0</favourites_count>
  <utc_offset>0</utc_offset>
  <time_zone>London</time_zone>
  <profile_background_image_url>http://s.twimg.com/a/1255366924/images/themes/theme12/bg.gif</profile_background_image_url>
  <profile_background_tile>false</profile_background_tile>
  <statuses_count>1965</statuses_count>
  <notifications>false</notifications>
  <geo_enabled>false</geo_enabled>
  <verified>false</verified>
  <following>false</following>
  <status>
    <created_at>Mon Oct 12 19:23:47 +0000 2009</created_at>
    <id>4815268670</id>
    <text>&#187; @alexmuller your kidding? it should all be &quot;black tie&quot; dress code</text>
    <source>&lt;a href=&quot;http://code.google.com/p/wittytwitter/&quot; rel=&quot;nofollow&quot;&gt;Witty&lt;/a&gt;</source>
    <truncated>false</truncated>
    <in_reply_to_status_id>4815131457</in_reply_to_status_id>
    <in_reply_to_user_id>8645442</in_reply_to_user_id>
    <favorited>false</favorited>
    <in_reply_to_screen_name>alexmuller</in_reply_to_screen_name>
    <geo/>
  </status>
</user>

다음 코드를 직렬화 해제에 사용하고 있습니다.

    public User VerifyCredentials()
    {
        string url = "http://twitter.com/account/verify_credentials.xml";
        string xml = _oauth.oAuthWebRequestAsString(oAuthTwitter.Method.GET, url, null);

        XmlSerializer xs = new XmlSerializer(typeof(User),"");

        MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xml));

        return (User)xs.Deserialize(ms);
    }

그리고 나는 User수업에 대해 다음을 가지고 있습니다 .

 [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class User
{

    [XmlElement(ElementName = "id")]       
    public long Id { get; set; }

    [XmlElement(ElementName = "name")] 
    public string Name { get; set; }

    [XmlElement(ElementName = "screen_name")]       
    public string ScreenName { get; set; }

    [XmlElement(ElementName = "location")]       
    public string Location { get; set; }

    [XmlElement(ElementName = "description")]      
    public string Description { get; set; }

    [XmlElement(ElementName = "profile_image_url")]      
    public string ProfileImageUrl { get; set; }

    [XmlElement(ElementName = "url")]       
    public string Url { get; set; }

    [XmlElement(ElementName = "protected")]      
    public bool Protected { get; set; }

    [XmlElement(ElementName = "followers_count")]      
    public int FollowerCount { get; set; }

    [XmlElement(ElementName = "profile_background_color")]       
    public string ProfileBackgroundColor { get; set; }

    [XmlElement(ElementName = "profile_text_color")]       
    public string ProfileTextColor { get; set; }

    [XmlElement(ElementName = "profile_link_color")]       
    public string ProfileLinkColor { get; set; }

    [XmlElement(ElementName = "profile_sidebar_fill_color")]       
    public string ProfileSidebarFillColor { get; set; }

    [XmlElement(ElementName = "profile_sidebar_border_color")]      
    public string ProfileSidebarBorderColor { get; set; }

    [XmlElement(ElementName = "friends_count")]     
    public int FriendsCount { get; set; }

    [XmlElement(ElementName = "created_at")]     
    public string CreatedAt { get; set; }

    [XmlElement(ElementName = "favourties_count")]      
    public int FavouritesCount { get; set; }

    [XmlElement(ElementName = "utc_offset")]      
    public int UtcOffset { get; set; }

    [XmlElement(ElementName = "time_zone")]       
    public string Timezone { get; set; }

    [XmlElement(ElementName = "profile_background_image_url")]        
    public string ProfileBackgroundImageUrl { get; set; }

    [XmlElement(ElementName = "profile_background_tile")]        
    public bool ProfileBackgroundTile { get; set; }

    [XmlElement(ElementName = "statuese_count")]        
    public int StatusesCount { get; set; }

    [XmlElement(ElementName = "notifications")]       
    public string Notifications { get; set; }

    [XmlElement(ElementName = "geo_enabled")]       
    public bool GeoEnabled { get; set; }

    [XmlElement(ElementName = "Verified")]        
    public bool Verified { get; set; }

    [XmlElement(ElementName = "following")]
    public string Following { get; set; }

    [XmlElement(ElementName = "status", IsNullable=true)]
    public Status CurrentStatus { get; set; }

}

그러나 위의 XML을 직렬화 해제하면 응용 프로그램에서 다음을 throw합니다.

  • $ exception { "XML 문서 (2, 2)에 오류가 있습니다."} System.Exception {System.InvalidOperationException}

  • InnerException { "<user xmlns = ''>이 (가) 예상되지 않았습니다."} System.Exception {System.InvalidOperationException}

이제 검색 한 결과 가장 좋은 해결책은 내용을 serialize 할 때 serializer에 빈 네임 스페이스를 추가하는 것이지만 직렬화하지 않아서 할 수 없습니다.

상태를 수신하기위한 코드도 있는데, 제대로 작동합니다.

그렇다면 누군가 오류가 발생하는 이유를 설명 할 수 있습니까? 가능한 해결책뿐만 아니라?

미리 감사드립니다.


제 경우에는의 잘못된 선언 때문이었습니다 XmlSerializer. 또한 확인하십시오.
Mangesh

XmlAttribute를 사용 하여 필드 를 클래스 에 추가해야했습니다 . 링크
Stefan Varga

답변:


263

컴파일시에 사용될 XmlRoot 속성으로 루트 엔티티를 장식하십시오.

[XmlRoot(Namespace = "www.contoso.com", ElementName = "MyGroupName", DataType = "string", IsNullable=true)]

또는 런타임시 직렬화를 해제 할 때 루트 속성을 지정하십시오.

XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "user";
// xRoot.Namespace = "http://www.cpandl.com";
xRoot.IsNullable = true;

XmlSerializer xs = new XmlSerializer(typeof(User),xRoot);

6
클래스 msdn.microsoft.com/en-us/library/83y7df3e(VS.71).aspx에 XmlRoot 특성을 추가 할 수 있습니다. [XmlRoot (Namespace = "www.contoso.com", ElementName = "MyGroupName", DataType = "string", IsNullable = true)]
david valentine

39
XML은 대소 문자를 구분합니다. "사용자"와 "사용자"는 다른 이름입니다.
John Saunders

4
XmlRoot 정보가 deserialize되는 위치가 아니라 클래스 자체에 정의되어야한다고 생각했기 때문에 하향 투표했습니다. 이러한 이유로, Junto의 솔루션은 제 생각에 우월합니다.
GuiSim

4
@GuiSim OP가 원래 엔터티를 제어한다고 가정합니다. 두 답변 모두 유효합니다. 필자의 경우 XmlRoot를 MessageContract의 일부로 사용하기 때문에 엔티티에 추가 할 수 없습니다. 위의 방법을 사용하면 시나리오에 적합합니다.
Bronumski

4
@GuiSim 나는 OP가 말한 것에 동의하지 않습니다. 루트 엔티티를 완전히 제어 할 수 있지만 MessageContract 속성과 충돌하기 때문에 루트 속성을 사용할 수 없습니다. 두 답변 모두 유효하며 대안은 의견에 제시되었습니다. 요점은 당신이 타당한 답변이 아닌 유효한 답변을 투표하고 있다는 것입니다. 최고라고 동의하지 않으면 투표하지 마십시오.
Bronumski

135

수업 상단에 다음 주석을 추가하는 것이 더 쉽습니다.

[Serializable, XmlRoot("user")]
public partial class User
{
}

간단하고
직설적

25
XmlSerializer xs = new XmlSerializer(typeof(User), new XmlRootAttribute("yourRootName")); 

2
그렇지 않으면 속성에 대한 조건에 의존해야하는 경우에 환상적입니다.
Den Delimarsky

2
매우 간단하고 내 사건을 완전히 고쳤습니다. 감사!
AW

12

오류 메시지가 너무 모호합니다.이 코드는 다음과 같습니다.

var streamReader = new StreamReader(response.GetResponseStream());
var xmlSerializer = new XmlSerializer(typeof(aResponse));
theResponse = (bResponse) xmlSerializer.Deserialize(streamReader);

xmlSerializer는 aResponse로 인스턴스화되었지만 역 직렬화 중에 실수로 bResonse에 캐스팅했습니다.


2
비슷한 문제가있었습니다. XmlSerializer를이 대해서 typeof (T)으로 초기화하고 있었고, 난 목록 <T>에 캐스팅되었다
nurettin

1
부모 클래스의 XmlRoot(..)자식 클래스 ClassB에 선언 했습니다 ClassA. 나는 new XmlSerializer(typeof(ClassA)대신에 사용 ClassB하고 객체를 캐스팅했습니다. 지적 해 주셔서 감사합니다!
Shishir Gupta

6

가장 간단하고 최상의 솔루션은 직렬화 해제하려는 클래스에서 XMLRoot 속성 을 사용 하는 것입니다.

처럼:

[XmlRoot(ElementName = "YourPreferableNameHere")]
public class MyClass{
...
}

또한 다음 어셈블리를 사용하십시오 .

using System.Xml.Serialization;

3
누구든지 설명하고 싶습니까? 이 문제를 해결하기 위해 속성이 필요한 이유무엇XmlRoot() 입니까? 여기에는 "이 코드 만 추가하십시오"라는 5 가지 답변이 있으며 설명은 하나가 아닙니다. 사람들은 7 년 후에 답변을하고 있으며 여전히 "이 XmlRoot 코드 추가"입니다. 모든 답변 중에서 설명을 요청하기 위해 최신 답변을 선택했습니다.
Quantic

@Quantic에게 감사합니다. XmlRoot를 사용하면 기본 루트를 사용하지 않고 새 xml 값을 만들 수 있습니다. 컴파일 타임에 XML에 추가 할 장식 일뿐입니다. 호환성 문제가 해결 될 수 있습니다. 당신이 내 요점을 얻을 바랍니다.
Khawaja Asim

5

John Saunders가 말했듯이 클래스 / 프로퍼티 이름이 XML의 대문자와 일치하는지 확인하십시오. 그렇지 않은 경우에도 문제가 발생합니다.


2

내 문제는 내 요소 중 하나에 xmlns 특성이 있다는 것입니다.

<?xml version="1.0" encoding="utf-8"?>
<RETS ReplyCode="0">
    <RETS-RESPONSE xmlns="blahblah">
        ...
    </RETS-RESPONSE>
</RETS>

내가 무엇을 시도하든 xmlns 속성이 직렬 변환기를 손상시키는 것처럼 보이므로 xml 파일에서 xmlns = "..."의 흔적을 제거했습니다.

<?xml version="1.0" encoding="utf-8"?>
<RETS ReplyCode="0">
    <RETS-RESPONSE>
        ...
    </RETS-RESPONSE>
</RETS>

그리고 짜잔! 모든 것이 효과가있었습니다.

이제 직렬화 해제하기 전에 xml 파일을 구문 분석하여이 속성을 제거하십시오. 왜 이것이 효과가 있는지 잘 모르겠습니다 .xmlns 속성을 포함하는 요소가 루트 요소가 아니기 때문에 제 경우가 다를 수 있습니다.


파일에서 RETS-RESPONSE가 "blahblah"네임 스페이스에 있음을 지정했습니다. 이것이 스키마와 일치하지 않으면 요소를 찾지 못한 것입니다. 또한 기본 네임 스페이스를 추가하면 모든 종류의 다른 참조 문제가 발생합니다.
Suncat2000

2

내 경우에는 David Valentine 코드를 사용하는 것이 유일한 방법이었습니다. 루트 속성 사용 Person 클래스에서 도움이되지 않았습니다.

이 간단한 Xml이 있습니다.

<?xml version="1.0"?>
<personList>
 <Person>
  <FirstName>AAAA</FirstName>
  <LastName>BBB</LastName>
 </Person>
 <Person>
  <FirstName>CCC</FirstName>
  <LastName>DDD</LastName>
 </Person>
</personList>

C # 클래스 :

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Main 메서드에서 직렬화 해제 C # 코드 :

XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "personList";
xRoot.IsNullable = true;
using (StreamReader reader = new StreamReader(xmlFilePath))
{
List<Person> result = (List<Person>)(new XmlSerializer(typeof(List<Person>), xRoot)).Deserialize(reader);
 int numOfPersons = result.Count;
}  

2

필자의 경우 XML에는 여러 네임 스페이스와 속성이 있습니다. 그래서이 사이트를 사용하여 객체를 생성했습니다-https: //xmltocsharp.azurewebsites.net/

그리고 아래 코드를 사용하여 역 직렬화

 XmlDocument doc =  new XmlDocument();
        doc.Load("PathTo.xml");
        User obj;
        using (TextReader textReader = new StringReader(doc.OuterXml))
        {
            using (XmlTextReader reader = new XmlTextReader(textReader))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(User));
                obj = (User)serializer.Deserialize(reader);
            }
        }

이 링크는 XML을 클래스로 직렬화 해제하는 데 큰 도움이되었습니다.
smr5

1

내 문제는 루트 요소에 실제로 xmlns = "abc123"이 있다는 것입니다

XmlRoot ( "elementname", NameSpace = "abc123")를 만들어야했습니다.


1

위의 모든 것이 나를 위해 작동하지는 않았지만 이것은 다음 과 같습니다. class의 Root 요소 이름이 XML 대소 문자 구분정확히 일치 하는지 확인하십시오 .


1

아무것도 일하지 이러한 오류를 저를 위해 제외

... was not expected, 
... there is an error in XML document (1,2)
... System.FormatException Input String was not in correct format ...

이 방법을 제외하고

1- xml 응답을 문자열로 검사해야합니다 (객체에 직렬화 해제하려는 응답)

2- 문자열 이스케이프 및 XML prettify / formatter에 온라인 도구 사용

3 확인 연결하려고하는 C # 클래스 (기본 클래스) / 위해 XML 문자열을 역 직렬화 그게 XmlRootAttribute를 갖고 응답의 루트 요소와 일치합니다.

예 :

내 XML 응답은 다음과 같습니다.

<ShipmentCreationResponse xmlns="http://ws.aramex.net/ShippingAPI/v1/">
       <Transaction i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>
           ....

그리고 C # 클래스 정의 + 속성은 다음과 같습니다.

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="ShipmentCreationResponse", WrapperNamespace="http://ws.aramex.net/ShippingAPI/v1/", IsWrapped=true)]
public partial class ShipmentCreationResponse {
  .........
}

클래스 정의에는 " XmlRootAttribute " 가 없습니다.

[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.aramex.net/ShippingAPI/v1/", IsNullable = false)]

그리고 일반적인 방법으로 직렬화를 시도하면 :

public static T Deserialize<T>(string input) where T : class
{
    System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(T));

    using (System.IO.StringReader sr = new System.IO.StringReader(input))
    {
        return (T)ser.Deserialize(sr);
    }
}





var _Response = GeneralHelper.XMLSerializer.Deserialize<ASRv2.ShipmentCreationResponse>(xml);

위의 오류가 발생했습니다.

... was not expected, ... there is an error in XML document (1,2) ...

이제 문제를 해결 한 "XmlRootAttribute"를 추가하고 다른 모든 요청 / 응답에 대해 비슷한 문제가 발생했습니다.

[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.aramex.net/ShippingAPI/v1/", IsNullable = false)]

..

[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://ws.aramex.net/ShippingAPI/v1/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.aramex.net/ShippingAPI/v1/", IsNullable = false)]
public partial class ShipmentCreationResponse
{
    ........
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.