{"<user xmlns = ''>は予期されていませんでした。} Twitter XMLを逆シリアル化しています


211

私はTwitterからOAuth経由でXMLを取得しています。

次のXMLを返すhttp://twitter.com/account/verify_credentials.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 {"<user xmlns = ''>は予期されていませんでした。"} System.Exception {System.InvalidOperationException}

今私は周りを検索しましたが、見つけることができる最善の解決策は、コンテンツをシリアル化するときに空の名前空間をシリアライザーに追加することですが、シリアル化していないのでできません。

ステータスを受信するためのコードもいくつかあります。

エラーが発生している理由を誰かに説明してもらえますか?可能な解決策と同様に?

前もって感謝します。


私の場合、それはの誤った宣言が原因でしたXmlSerializer。それも確認してください。
Mangesh

XmlAttributeを持つフィールドをクラスに追加する必要がありました。リンク
Stefan Varga

回答:


261

コンパイル時に使用される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)]
バレンタイン

39
XMLでは大文字と小文字が区別されます。「ユーザー」と「ユーザー」は別の名前です。
John Saunders、

4
XmlRoot情報は、逆シリアル化されている場所ではなく、クラス自体で定義する必要があると思うので、反対票を投じました。この理由から、Juntoのソリューションは私の意見では優れています。
GuiSim

4
@GuiSim OPが元のエンティティを制御していると想定しています。どちらの回答も有効です。私の場合、XmlRootをMessageContractの一部として使用しているため、エンティティに追加できません。上記の方法を使用すると、私のシナリオで機能します。
Bronumski 2013

4
@GuiSim OPの発言には同意しません。ルートエンティティを完全に制御できますが、MessageContract属性と競合するため、root属性を使用できません。どちらの回答も有効であり、代替案はコメントに記載されています。ポイントは、あなたが間違った答えではなく有効な答えを投票しているということです。それが最高であることに同意しない場合は、投票しないでください。
Bronumski 2013

135

さらに簡単なのは、次の注釈をクラスの先頭に追加することです。

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

シンプルで
わかりやすい

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

2
これは、属性の条件に依存する必要がある場合に最適です。
Den Delimarsky、2015

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)に初期化され、List <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つの回答があり、1つの説明ではありません。人々は7年後に答えて、それはまだ「このXmlRootコードを追加する」だけです。すべての回答のうち、最新のものを選んで説明を求めました。
Quanticの

@ Quantic、XmlRootを使用すると、デフォルトのルートを使用するのではなく、新しいxml値を作成してカスタマイズできます。これは、コンパイル時にxmlに追加する一種の装飾です。互換性の問題を解消することがあります。あなたが私のポイントを理解してくれることを願っています。
Khawaja Asim

5

John Saundersが言うように、クラス/プロパティ名がXMLの大文字と一致するかどうかを確認します。そうでない場合、問題も発生します。


2

私の問題は、要素の1つにxmlns属性があったことです。

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

何を試してもxmlns属性がシリアライザを壊しているように見えたので、xmlns = "..."のトレースをxmlファイルから削除しました。

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

そして出来上がり!すべてがうまくいった。

逆シリアル化する前に、xmlファイルを解析してこの属性を削除します。なぜこれが機能するのかわからない、おそらくxmlns属性を含む要素がルート要素ではないため、私の場合は異なる。


ファイルで、RETS-RESPONSEが "blahblah"名前空間にあることが指定されていました。それがスキーマと一致しない場合、要素は見つかりませんでした。また、デフォルトの名前空間を追加すると、他のあらゆる種類の参照問題も発生します。
Suncat2000

2

私の場合、唯一有効だったのは、デビッドバレンタインコードを使用することでした。ルート属性の使用。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

上記のすべては私にとってはうまくいきませんでしたが、これは次のとおりでした:クラスのルート要素の名前が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 - を確認してくださいあなたがXML文字列をデシリアライズ/マップしようとしているC#クラス(メインクラス)ということは、AN XmlRootAttribute HAS応答のルート要素にマッチします。

例:

私の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.