{"<user xmlns = ''> ไม่ได้คาดหวัง} Deserializing Twitter XML


211

ฉันดึง XML จาก Twitter ผ่าน OAuth

ฉันขอ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>

ฉันใช้รหัสต่อไปนี้เพื่อ Deserialize:

    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; }

}

แต่เมื่อ deserializing XML ข้างต้นแอปพลิเคชันจะแสดงข้อความต่อไปนี้:

  • $ exception {"มีข้อผิดพลาดในเอกสาร XML (2, 2)"} System.Exception {System.InvalidOperationException}

  • InnerException {"<user xmlns = ''> ไม่ถูกคาดหวัง"} System.Exception {System.InvalidOperationException}

ตอนนี้ฉันค้นหาไปแล้วและทางออกที่ดีที่สุดที่ฉันสามารถหาได้คือการเพิ่มเนมสเปซว่างลงในซีเรียลไลเซอร์เมื่อคุณทำให้เนื้อหาเป็นอนุกรม แต่ฉันไม่ได้ทำให้เป็นอนุกรม

ฉันยังมีรหัสสำหรับรับสถานะซึ่งทำงานได้ดี

บางคนสามารถอธิบายให้ฉันฟังได้ว่าทำไมข้อผิดพลาดจึงเกิดขึ้น? เช่นเดียวกับวิธีการแก้ปัญหาที่เป็นไปได้?

ขอบคุณล่วงหน้า.


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
คุณสามารถเพิ่มแอตทริบิวต์ XmlRoot ลงในคลาสmsdn.microsoft.com/en-us/library/83y7df3e(VS.71).aspx [XmlRoot (Namespace = "www.contoso.com", ElementName = "MyGroupName", DataType = "string", IsNullable = true)]
david valentine

39
XML เป็นกรณี ๆ ไป "ผู้ใช้" และ "ผู้ใช้" เป็นชื่อที่แตกต่างกัน
469 John Saunders ที่

4
ฉันลงคะแนนเพราะฉันรู้สึกว่าควรกำหนดข้อมูล XmlRoot ในชั้นเรียนของตัวเองไม่ใช่ที่ที่จะทำการ deserialized สำหรับเหตุผลนี้ Junto แก้ปัญหาได้ดีกว่า
GuiSim

4
@GuiSim คุณกำลังสมมติว่า OP มีการควบคุมเอนทิตีดั้งเดิม คำตอบทั้งสองถูกต้อง ในกรณีของฉันฉันไม่สามารถเพิ่ม XmlRoot ให้กับเอนทิตีเพราะมันถูกใช้เป็นส่วนหนึ่งของ MessageContract การใช้วิธีการด้านบนใช้ได้กับสถานการณ์ของฉัน
Bronumski

4
@GuiSim ฉันไม่เห็นด้วยกับสิ่งที่ OP พูด ฉันมีการควบคุมที่สมบูรณ์ของเอนทิตีรูทของฉัน แต่ไม่สามารถใช้รูทแอททริบิวได้เพราะมันขัดแย้งกับแอตทริบิวต์ของ MessageContract คำตอบทั้งสองถูกต้องและเป็นทางเลือกที่นำเสนอในความคิดเห็น ประเด็นคือคุณกำลังลงคะแนนตอบที่ถูกต้องไม่ใช่คำตอบที่ผิด หากคุณไม่เห็นด้วยว่าวิธีที่ดีที่สุดคืออย่าโหวต
Bronumski

135

ง่ายยิ่งขึ้นเพียงเพิ่มคำอธิบายประกอบต่อไปนี้ที่ด้านบนของชั้นเรียนของคุณ:

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

เรียบง่ายและตรงไปตรงมา
mayowa ogundele

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 ดูเหมือนว่าจะทำลาย serializer ดังนั้นฉันจึงลบร่องรอยของ xmlns = "... " ออกจากไฟล์ xml:

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

และ voila! ทุกอย่างทำงานได้

ตอนนี้ฉันแยกไฟล์ xml เพื่อลบคุณลักษณะนี้ก่อน deserializing ไม่แน่ใจว่าทำไมสิ่งนี้ถึงใช้งานได้เคสของฉันอาจแตกต่างกันเนื่องจากองค์ประกอบที่มีแอตทริบิวต์ xmlns ไม่ใช่องค์ประกอบหลัก


ไฟล์ของคุณระบุว่า RETS-RESPONSE อยู่ในเนมสเปซ "blahblah" หากสิ่งนั้นไม่ตรงกับสคีมาของคุณองค์ประกอบจะไม่ถูกค้นพบ นอกจากนี้การเพิ่มเนมสเปซเริ่มต้นทำให้เกิดปัญหาการอ้างอิงอื่น ๆ ทุกประเภทด้วยเช่นกัน
Suncat2000

2

สิ่งเดียวที่ทำงานในกรณีของฉันคือการใช้รหัสวาเลนไทน์ดาวิด การใช้ Root Attr ในระดับบุคคลไม่ได้ช่วย

ฉันมี 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; }
}

การทำให้เป็นรหัส 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);
            }
        }

ลิงค์นี้ให้ความช่วยเหลืออย่างมากในการเลิก desizeial XML ไปยังคลาส
smr5

1

ปัญหาของฉันคือองค์ประกอบรากมี xmlns = "abc123" จริง ๆ

ดังนั้นต้องสร้าง XmlRoot ("elementname", NameSpace = "abc123")


1

ทั้งหมดข้างต้นไม่ได้ทำงานสำหรับฉัน แต่นี้คือ: ตรวจสอบว่าชื่อขององค์ประกอบหลักของการเรียนคือว่าเช่นเดียวจากของ 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- ใช้เครื่องมือออนไลน์สำหรับสตริง unescape และ xml prettify / formatter

3- ตรวจสอบให้แน่ใจว่าคลาส C # (คลาสหลัก) ที่คุณพยายามแมป / ยกเลิกการเรียงสตริงสตริง xml กับHAS AN XmlRootAttributeที่ตรงกับองค์ประกอบรากของการตอบสนอง

Exmaple:

การตอบสนอง XML ของฉันกำลังจ้องมองอย่างเช่น:

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

และแอตทริบิวต์ C + class definition + เป็นเช่น:

[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.