【问题标题】:{"<user xmlns=''> was not expected.} Deserializing Twitter XML{"<user xmlns=''> 不是预期的。} 反序列化 Twitter XML
【发布时间】:2010-12-06 03:01:05
【问题描述】:

我正在通过 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 时,应用程序会抛出以下内容:

$exception {"XML 文档中存在错误 (2, 2)。"} System.Exception {System.InvalidOperationException}

InnerException {" 不是预期的。"} System.Exception {System.InvalidOperationException}

现在我已经四处搜索,我能找到的最佳解决方案是在序列化内容时向序列化程序添加空白名称空间,但我没有对其进行序列化,所以我不能。

我还有一些用于接收状态的代码,效果很好。

那么有人可以向我解释为什么会发生错误吗?以及可能的解决方案?

【问题讨论】:

  • 就我而言,这是因为XmlSerializer 的错误声明。所以也要检查一下。
  • 我必须将带有 XmlAttribute 的字段添加到类中。见link

标签: c# twitter xml-serialization


【解决方案1】:

使用 XmlRoot 属性装饰您的根实体,该属性将在编译时使用。

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

或者在运行时反序列化时指定root属性。

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

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

【讨论】:

  • 您可以将 XmlRoot 属性添加到类 msdn.microsoft.com/en-us/library/83y7df3e(VS.71).aspx [XmlRoot(Namespace = "www.contoso.com", ElementName = "MyGroupName", DataType = "string", IsNullable=true)]
  • XML 区分大小写。 “用户”和“用户”是不同的名称。
  • 我投了反对票,因为我觉得应该在类本身上定义 XmlRoot 信息,而不是在反序列化的地方。为此,在我看来,Junto 的解决方案更胜一筹。
  • @GuiSim 您假设 OP 可以控制原始实体。两个答案都是有效的。在我的情况下,我无法将 XmlRoot 添加到实体,因为它用作 MessageContract 的一部分。使用上述方法适用于我的场景。
  • @GuiSim 我不同意 OP 所说的话。我可以完全控制我的根实体,但不能使用根属性,因为它与 MessageContract 属性冲突。这两个答案都是有效的,并且在 cmets 中提供了替代方案。关键是你投了一个有效的答案而不是一个错误的答案。如果您不同意这是最好的,请不要投票。
【解决方案2】:

更简单的方法是在类的顶部添加以下注释:

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

【讨论】:

  • 简单明了
  • 啊!!您刚刚保存了我从 XML 到类 obj 的 6 次手动转换!按预期工作.. 谢谢
【解决方案3】:
XmlSerializer xs = new XmlSerializer(typeof(User), new XmlRootAttribute("yourRootName")); 

【讨论】:

  • 这对于您必须依赖条件来获取属性的情况非常有用。
  • 非常简单,完全解决了我的问题。谢谢!
【解决方案4】:

错误信息太模糊了,对我来说我有这个代码:

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

注意 xmlSerializer 是用 aResponse 实例化的,但在反序列化时我不小心将其转换为 bResonse。

【讨论】:

  • 刚刚遇到了类似的问题。 xmlserializer 被初始化为 typeof(T) 并且我正在转换为 List
  • 我在父类ClassA 的子类ClassB 上声明了XmlRoot(..)。我使用new XmlSerializer(typeof(ClassA) 而不是ClassB 并且还向它投射了对象。谢谢指出!
【解决方案5】:

最简单和最好的解决方案就是在您希望反序列化的类中使用 XMLRoot 属性。

喜欢:

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

另外,使用以下程序集

using System.Xml.Serialization;

【讨论】:

  • 有人想解释一下吗? 为什么需要XmlRoot() 属性来解决这个问题?这里有 5 个答案说“只需添加此代码”,而不是一个解释。人们在 7 年后回答,仍然只是“添加这个 XmlRoot 代码”。在所有答案中,我选择了最新的一个来寻求解释。
  • 谢谢@Quantic,XmlRoot 允许您创建一个新的 xml 值,而不是使用您可以自定义的默认根。它只是一种装饰,您将在编译时添加到您的 xml 中。将消除某些时候的兼容性问题。希望你明白我的意思。
【解决方案6】:

正如 John Saunders 所说,检查类/属性名称是否与 XML 的大写字母匹配。如果不是这样,问题也会出现。

【讨论】:

    【解决方案7】:

    在我的例子中,我的 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 反序列化为类提供了巨大帮助。
    • 提供的网址对我来说也很大。
    【解决方案8】:

    在我的案例中唯一有效的是使用大卫情人节代码。使用根属性。在 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;
    }  
    

    【讨论】:

    • 这个对我有用,但在这个例子中,我必须使用与类名相同的小写“Person”名称。
    • 或者你可以在你的项目类上方使用[XmlType(TypeName = "Person")]注解。
    【解决方案9】:

    我的问题是根元素实际上有一个 xmlns="abc123"

    所以不得不制作 XmlRoot("elementname",NameSpace="abc123")

    【讨论】:

    • 绝对帮了我...如果您的 XML 有命名空间,则必须添加命名空间。
    【解决方案10】:

    我的问题是我的元素之一具有 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”命名空间中。如果这与您的架构不匹配,则不会找到该元素。此外,添加默认命名空间也会导致各种其他引用问题。
    【解决方案11】:

    这些错误对我来说没有任何效果除了

    ... 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- 确保您尝试将 xml 字符串映射/反序列化为 具有与根元素匹配的 XmlRootAttribute 的 C# 类(主类)回应。

    示例:

    我的 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
    {
        ........
    }
    

    【讨论】:

      【解决方案12】:

      以上所有对我都不起作用,但这是: 检查类的 Root 元素的名称是否与 XML 区分大小写中的名称完全相同

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-23
        • 1970-01-01
        • 1970-01-01
        • 2012-03-19
        • 1970-01-01
        • 2018-08-28
        • 2021-03-06
        相关资源
        最近更新 更多