{"<user xmlns = ''> không được mong đợi.} Giải nén Twitter XML


211

Tôi đang lấy XML từ Twitter thông qua OAuth.

Tôi đang thực hiện một yêu cầu tới http://twitter.com/account/verify_credentials.xml , trả về XML sau:

<?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>

Tôi đang sử dụng đoạn mã sau để 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);
    }

Và tôi có những điều sau đây cho Userlớp học của mình :

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

}

Nhưng khi nó giải tuần tự hóa XML ở trên, ứng dụng sẽ ném như sau:

  • $ ngoại lệ {"Có lỗi trong tài liệu XML (2, 2)."} System.Exception {System.InvalidOperationException}

  • InternalException {"<user xmlns = ''> không được mong đợi."} System.Exception {System.InvalidOperationException}

Bây giờ tôi đã tìm kiếm xung quanh và giải pháp tốt nhất tôi có thể tìm thấy là thêm các không gian tên trống vào serializer khi bạn tuần tự hóa nội dung, nhưng tôi không tuần tự hóa nó vì vậy tôi không thể.

Tôi cũng có một số mã để nhận Statuses, hoạt động tốt.

Vì vậy, ai đó có thể giải thích cho tôi tại sao lỗi xảy ra? Cũng như một giải pháp có thể?

Cảm ơn trước.


Trong trường hợp của tôi, đó là do khai báo sai XmlSerializer. Vì vậy, kiểm tra mà cũng.
Mangesh

Tôi đã phải thêm trường với XmlAttribution vào lớp. Xem liên kết
Stefan Varga

Câu trả lời:


261

Trang trí thực thể gốc của bạn bằng thuộc tính XmlRoot sẽ được sử dụng tại thời điểm biên dịch.

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

Hoặc chỉ định thuộc tính gốc khi de serialization trong thời gian chạy.

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

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

6
Bạn có thể thêm một thuộc tính XmlRoot vào lớp msdn.microsoft.com/en-us/l Library / 83y7df3e (VS.71) .aspx [XmlRoot (Namespace = "www.contoso.com", ElementName = "MygroupName", DataType = "chuỗi", IsNullable = true)]
david valentine

39
XML phân biệt chữ hoa chữ thường. "Người dùng" và "người dùng" là các tên khác nhau.
John Saunders

4
Tôi đã bỏ qua vì tôi cảm thấy rằng thông tin XmlRoot nên được xác định trên chính lớp đó, chứ không phải nơi nó đang được giải tuần tự hóa. Đối với reaon này, theo tôi, giải pháp của Junto là vượt trội.
GuiSim

4
@GuiSim Bạn đang giả sử rằng OP có quyền kiểm soát thực thể ban đầu. Cả hai câu trả lời đều hợp lệ. Trong trường hợp của tôi, tôi không thể thêm XmlRoot vào thực thể vì nó được sử dụng như một phần của MessageContract. Sử dụng phương pháp trên hoạt động cho kịch bản của tôi.
Bronumski

4
@GuiSim Tôi không đồng ý với những gì OP nói. Tôi có toàn quyền kiểm soát thực thể gốc của mình nhưng không thể sử dụng thuộc tính gốc vì nó xung đột với thuộc tính MessageContract. Cả hai câu trả lời là hợp lệ và thay thế đã được trình bày trong các ý kiến. Vấn đề là bạn đang bỏ phiếu một câu trả lời hợp lệ không phải là một câu trả lời sai. Nếu bạn không đồng ý rằng đó là điều tốt nhất thì đừng bỏ phiếu.
Bronumski

135

Thậm chí dễ dàng hơn chỉ là thêm các chú thích sau vào đầu lớp của bạn:

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

Đơn giản và dễ hiểu
mayowa ogundele

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

2
Điều này là tuyệt vời cho các trường hợp nếu không bạn sẽ phải dựa vào các điều kiện cho các thuộc tính.
Den Delimarsky

2
Rất đơn giản và cố định hoàn toàn trường hợp của tôi. Cảm ơn!
AW

12

Thông báo lỗi rất mơ hồ, đối với tôi, tôi đã có mã này:

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

Lưu ý xmlSerializer được khởi tạo bằng aResponse nhưng khi khử lưu huỳnh, tôi vô tình chuyển nó thành bResonse.


2
Chỉ có một vấn đề tương tự. xmlserializer đã được khởi tạo thành typeof (T) và tôi đã chuyển sang Danh sách <T>
Nurettin

1
Tôi tuyên bố XmlRoot(..)trên lớp con ClassBcủa lớp cha mẹ ClassA. Tôi đã sử dụng new XmlSerializer(typeof(ClassA)thay vì trên ClassBvà cũng đúc đối tượng cho nó. Cảm ơn đã chỉ ra!
Shishir Gupta

6

Giải pháp đơn giản và tốt nhất là sử dụng XMLRoot thuộc tính trong lớp của bạn, trong đó bạn muốn giải tuần tự hóa.

Giống:

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

Ngoài ra, sử dụng hội sau :

using System.Xml.Serialization;

3
Bất cứ ai cũng muốn đưa ra một lời giải thích? Tại saoXmlRoot()thuộc tính cần thiết để khắc phục vấn đề này? Có 5 câu trả lời ở đây có nội dung: "chỉ cần thêm mã này" và không phải là một lời giải thích. Mọi người đang trả lời 7 năm sau và vẫn chỉ là "Thêm mã XmlRoot này". Trong tất cả các câu trả lời tôi chọn câu trả lời mới nhất để yêu cầu giải thích.
Quantic

Thankyou @Quantic, XmlRoot cho phép bạn tạo một giá trị xml mới thay vì sử dụng root mặc định, bạn có thể tùy chỉnh nó. Nó chỉ là loại trang trí bạn sẽ thêm vào xml của bạn tại thời gian biên dịch. Sẽ loại bỏ một số lần vấn đề tương thích. Hy vọng bạn có được quan điểm của tôi.
Khawaja Asim

5

Như John Saunders nói, hãy kiểm tra xem tên lớp / thuộc tính có khớp với vỏ vốn của XML của bạn không. Nếu đây không phải là trường hợp, vấn đề cũng sẽ xảy ra.


2

Vấn đề của tôi là một trong những yếu tố của tôi có thuộc tính xmlns:

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

Không có vấn đề gì, tôi đã thử thuộc tính xmlns dường như phá vỡ serializer, vì vậy tôi đã xóa bất kỳ dấu vết nào của xmlns = "..." khỏi tệp xml:

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

và Voila! Tất cả mọi thứ đã làm việc.

Bây giờ tôi phân tích tệp xml để loại bỏ thuộc tính này trước khi khử lưu huỳnh. Không chắc tại sao điều này hoạt động, có thể trường hợp của tôi khác vì phần tử chứa thuộc tính xmlns không phải là phần tử gốc.


Tệp của bạn đã chỉ định rằng RETS-RESPONSE nằm trong không gian tên "blahblah". Nếu điều đó không phù hợp với lược đồ của bạn, phần tử sẽ không được tìm thấy. Ngoài ra, việc thêm một không gian tên mặc định cũng gây ra tất cả các loại vấn đề tham chiếu khác.
Suncat2000

2

Điều duy nhất làm việc trong trường hợp của tôi là bằng cách sử dụng mã valentine david. Sử dụng Root Attr. trong lớp Người không giúp được gì.

Tôi có Xml đơn giản này:

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

Lớp C #:

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

Khử tuần tự mã C # từ một phương thức chính:

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

Trong trường hợp của tôi, xml của tôi có nhiều không gian tên và thuộc tính. Vì vậy, tôi đã sử dụng trang web này để tạo các đối tượng - https://xmltocsharp.azurewebsites.net/

Và sử dụng đoạn mã dưới đây để giải tuần tự hóa

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

Liên kết đã cung cấp một trợ giúp rất lớn để giải trừ xml đến lớp.
smr5

1

Vấn đề của tôi là phần tử gốc thực sự có xmlns = "abc123"

Vì vậy, phải tạo XmlRoot ("Elementname", NameSpace = "abc123")


1

Tất cả ở trên không làm việc cho tôi, nhưng đây là: Kiểm tra xem tên của phần tử Root của lớp có chính xác như tên của trường hợp XML không .


1

Không có gì làm việc cho tôi cho những lỗi này NGOẠI TRỪ

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

Ngoại trừ cách này

1- Bạn cần kiểm tra phản hồi xml dưới dạng chuỗi (phản hồi mà bạn đang cố gắng hủy tuần tự hóa thành một đối tượng)

2- Sử dụng các công cụ trực tuyến cho chuỗi unescape và xml prettify / formatter

3- HÃY ĐẢM BẢO rằng Lớp C # (lớp chính) mà bạn đang cố gắng ánh xạ / giải tuần tự chuỗi xml thành ĐÃ XmlRootAttribution phù hợp với phần tử gốc của phản hồi.

Sơ đồ:

Phản hồi XML của tôi đang nhìn chằm chằm như:

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

Và các thuộc tính + định nghĩa lớp C # giống như:

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

Lưu ý rằng định nghĩa lớp không có " XmlRootAttribution "

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

Và khi tôi cố gắng tuần tự hóa bằng phương pháp chung:

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

Tôi đã nhận được các lỗi ở trên

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

Bây giờ chỉ bằng cách thêm "XmlRootAttribution" đã khắc phục sự cố này và cho mọi yêu cầu / phản hồi khác, tôi gặp vấn đề tương tự với:

[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
{
    ........
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.