【问题标题】:xml rpc response map to object C#xml rpc 响应映射到对象 C#
【发布时间】:2016-12-16 15:00:31
【问题描述】:

我有以下

`<?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,但没有成功。我无法理解更改整数值的“名称”元素。任何帮助表示赞赏。

【问题讨论】:

  • 无法从您的描述中获得 - 您需要序列化或反序列化为 c# 对象吗?
  • XML-RPC 在 2002 年 .NET 的第一个版本问世之前就被 SOAP 取代了。本质上,它是一组类似于 Json 的键/值对(实际上是名称/值对)。如果你不能说服创建服务器的人使用更多……新鲜的东西,你应该寻找像 XML-RPC.Net 这样的库,也可以作为 Nuget 包提供
  • @Mitklantekutli 问题很明确 - OP 想要反序列化服务器的响应。这不是立即的,因为 元素 具有不同的内容和结构,就像 Json 一样。
  • 您要调用什么服务器?它有一个 Json API 可以用来代替 XML-RPC 吗?您是否正在尝试使用可能使用 Frontpage 扩展的网站?
  • 澄清一下,我得到这个 xml 作为来自服务器的响应,我想把这个响应反序列化成一个对象。不,服务器没有json api,只有xml rpc。我有一个实现 IXmlRpcProxy 的类接口,那里有我可以调用的所有 webmethods。对于这个函数,结果比整数或字符串要复杂一些。所以我还没有想出兼容的对象——我应该有的返回类型。

标签: c# .net xml serialization


【解决方案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;

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      在考虑了您的答案后,动态关键字让我想到了这个不完美但确实有效的解决方案。 我将方法的返回类型设为动态,然后在运行时使用 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; }
          }
      
      }
      

      所以我成功地反序列化了响应。它不理想,但还可以。如果有人想到更好的解决方案,请随时发布,感谢您的回答

      【讨论】:

      • 您尝试过 XML-RPC.NET 吗?或者检查 alternative API?例如,SharePoint 有 SOAP 和 REST API,它们提供与 XML-RPC 相同的功能。
      • 我使用 CookComputing.XmlRpcV2 库。在这种情况下,我只能使用 XML-RPC。谢谢
      • 您是否尝试过我的解决方案,它的代码少了很多,不使用第二方 dll,并给出了相同的结果?
      • 我检查您的解决方案。但是,我已经用这个库实现了最大的部分,到目前为止,xml 部分的代码行很少。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-10
      • 2017-11-03
      • 2019-09-24
      • 1970-01-01
      • 2020-08-08
      • 2019-07-22
      相关资源
      最近更新 更多