xml rpc响应映射到对象C#

时间:2016-12-16 15:00:32

标签: c# .net xml serialization

我有以下

`<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
   <params>
      <param>
         <value>
            <struct>
               <member>
                  <name>1</name>
                  <value>
                     <struct>
                        <member>
                           <name>imageID</name>
                           <value>
                              <string>40087</string>
                           </value>
                        </member>
                        <member>
                           <name>imageURL</name>
                           <value>                         <string>http://local.server.gr/public_html/main/phpthumb/phpThumb.php?id=40087</string>
                           </value>
                        </member>
                     </struct>
                  </value>
               </member>
               <member>
                  <name>2</name>
                  <value>
                     <struct>
                        <member>
                           <name>imageID</name>
                           <value>
                              <string>40088</string>
                           </value>
                        </member>
                        <member>
                           <name>imageURL</name>
                           <value>
                              <string>http://local.server.gr/public_html/main/phpthumb/phpThumb.php?id=40088</string>
                           </value>
                        </member>
                     </struct>
                  </value>
               </member>
               <member>
                  <name>3</name>
                  <value>
                     <struct>
                        <member>
                           <name>imageID</name>
                           <value>
                              <string>40089</string>
                           </value>
                        </member>
                        <member>
                           <name>imageURL</name>
                           <value>
                              <string>http://local.server.gr/public_html/main/phpthumb/phpThumb.php?id=40089</string>
                           </value>
                        </member>
                     </struct>
                  </value>
               </member>
            </struct>
         </value>
      </param>
   </params>
</methodResponse>`

来自服务器的xmlrpc响应。

我尝试过接受并成功序列化这个xml的不同类型的对象,但没有成功。我无法理解&#34;名称&#34;更改整数值的元素。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:1)

XML-RPC由Microsoft创建,并在2002年第一个.NET版本之前被SOAP取代。它的问题在于您不知道实际对象的架构是什么。 XML-RPC类似于Json,它将所有内容序列化为可用于重建对象属性的名称/值项。你不知道所有这些属性是什么。

> 幸运的是,Frontpage使用了XML-RPC,它的使用在SharePoint中幸存下来。这意味着您可以使用现成的架构here

您可以使用旧的xsd.exe程序从中生成C#类。将模式保存到文件(例如xmlrpc.xsd),确保标记之前没有空格,并使用以下行生成类:

xsd xmlrpc.xsd /c /nx:XlmRpcNS

其中XmlRpcNS是您要用于生成的类的命名空间。将生成的文件添加到项目中(默认情况下为xmlrpc.cs)并使用它们反序列化响应,例如:

using (var reader = new StringReader(response))
{
    var sz = new XmlSerializer(typeof(methodResponse));
    var methodResponse= (methodResponse)sz.Deserialize(reader);
    var content = (methodResponseParams)methodResponse.Item;
    var structContent = (StructType)content.param.value.Item;
    //...
}

问题是xsd.exe为每个选择元素生成object Item属性,这就是你需要转换为正确类型的原因。

另一个选择是使用dynamic来避免演员表。你这样失去了Intellisens:

dynamic methodResponse= (methodResponse)sz.Deserialize(reader);
var members = methodResponse.Item.param.value.Item;

答案 1 :(得分:0)

试试xml linq。在这种情况下工作真的很好

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;


namespace ConsoleApplication33
{

    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {

            XDocument doc = XDocument.Load(FILENAME);
            var results = doc.Descendants("struct").FirstOrDefault().Elements("member").Select(x => new {
                name = (int)x.Element("name"),
                imageID = x.Descendants("member").Where(y => (string)y.Element("name") == "imageID").Select(z => (int)z.Descendants("string").FirstOrDefault()).FirstOrDefault(),
                imageURL = x.Descendants("member").Where(y => (string)y.Element("name") == "imageURL").Select(z => (string)z.Descendants("string").FirstOrDefault()).FirstOrDefault(),

            }).ToList();
        }
    }


}

进入班级

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;


namespace ConsoleApplication33
{

    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {

            XDocument doc = XDocument.Load(FILENAME);
            Image.images = doc.Descendants("struct").FirstOrDefault().Elements("member").Select(x => new Image() {
                name = (int)x.Element("name"),
                imageID = x.Descendants("member").Where(y => (string)y.Element("name") == "imageID").Select(z => (int)z.Descendants("string").FirstOrDefault()).FirstOrDefault(),
                url = x.Descendants("member").Where(y => (string)y.Element("name") == "imageURL").Select(z => (string)z.Descendants("string").FirstOrDefault()).FirstOrDefault(),

            }).ToList();
        }
    }
    public class Image
    {
        public static List<Image> images { get; set; }
        public int name { get; set; }
        public int imageID { get; set; }
        public string url { get; set; }
    }


}

答案 2 :(得分:0)

在考虑了你的答案之后,动态关键字让我想到这个解决方案并不完美,但是它的工作方式。 我将方法的返回类型设置为动态,然后在运行时使用visual studio调试器分析动态对象。然后我构建这个类:

public class ImageListResult
{
    public List<ImageSlot> Slots { get; set; }
    public ImageListResult(dynamic res)
    {
        this.Slots = new List<ImageSlot>();
        try {
            int keys = res.Keys.Count;
            int values = res.Values.Count;

            if (keys == values)
            {
                for (int i = 0; i < keys; i++)
                {
                    ImageSlot slot = new ImageSlot()
                    {
                        Index = int.Parse(res.Keys[i])
                    };

                    int subCount = res.Values[i].Keys.Count;
                    for (int j = 0; j < subCount; j++)
                    {
                        string k = res.Values[i].Keys[j];
                        string v = res.Values[i].Values[j];
                        if (k.ToLower().Trim() == "imageid")
                        {
                            slot.ImageId = v;
                        }
                        else if(k.ToLower().Trim() == "imageurl")
                        {
                            slot.ImageUrl = v;
                        }
                    }

                    this.Slots.Add(slot);
                }
            }
        }catch(Exception ex)
        {

        }
    }

    public class ImageSlot
    {
        /// <summary>
        /// το index του image slot, απο το 1 εως το 25
        /// </summary>
        public int Index { get; set; } 

        public string ImageId { get; set; }

        public string ImageUrl { get; set; }
    }

}

所以我成功地设法反序列化了响应。它不理想,但还行。如果有人想到一个更好的解决方案随时发布它,谢谢你的答案