将moodle XML解析为C#(dotnet)对象
我正在尝试反序列化从moodle web服务收到的XML响应 如果它有不同的命名属性,如id、shortname、idnumber等,我可以将其解析为dotnet对象。但它有一个关键属性数组,实际字段名作为值,在该数组中,有另一个节点具有字段值 以下是一个示例:将moodle XML解析为C#(dotnet)对象,c#,xml,deserialization,moodle,moodle-api,C#,Xml,Deserialization,Moodle,Moodle Api,我正在尝试反序列化从moodle web服务收到的XML响应 如果它有不同的命名属性,如id、shortname、idnumber等,我可以将其解析为dotnet对象。但它有一个关键属性数组,实际字段名作为值,在该数组中,有另一个节点具有字段值 以下是一个示例: <?xml version="1.0" encoding="UTF-8" ?> <RESPONSE> <MULTIPLE> &l
<?xml version="1.0" encoding="UTF-8" ?>
<RESPONSE>
<MULTIPLE>
<SINGLE>
<KEY name="id">
<VALUE>2</VALUE>
</KEY>
<KEY name="shortname">
<VALUE>CS-101</VALUE>
</KEY>
<KEY name="fullname">
<VALUE>CS-101</VALUE>
</KEY>
<KEY name="enrolledusercount">
<VALUE>2</VALUE>
</KEY>
<KEY name="idnumber">
<VALUE></VALUE>
</KEY>
<KEY name="visible">
<VALUE>1</VALUE>
</KEY>
<KEY name="summary">
<VALUE><p>CS-101<br /></p></VALUE>
</KEY>
<KEY name="summaryformat">
<VALUE>1</VALUE>
</KEY>
<KEY name="format">
<VALUE>weeks</VALUE>
</KEY>
<KEY name="showgrades">
<VALUE>1</VALUE>
</KEY>
<KEY name="lang">
<VALUE></VALUE>
</KEY>
<KEY name="enablecompletion">
<VALUE>0</VALUE>
</KEY>
</SINGLE>
</MULTIPLE>
</RESPONSE>
有没有一种直接的方法,或者我应该为每个字段编写一个带有切换案例的解析器方法?您需要使用XmlReader编写自定义解析器,没有任何默认的反序列化程序可以通过任何预设来完成
另外,您不需要使用switch/cases,您可以使用反射来填充您的道具。您需要使用XmlReader编写自定义解析器,没有任何默认的反序列化程序可以通过任何预设来完成
另外,您不需要使用switch/cases,您可以使用反射来填充道具。据我所知,此结构没有默认的反序列化程序。 正如@Nigrimist所说,您不需要使用开关盒 您可以使用
XmlReader
读取xml,也可以使用XmlDocument
进行读取。下面是解析的示例代码。我没有测试过,所以请小心使用
public T ConvertFromXml<T>(string yourXml, params object[] activationData)
where T : new() //if your type has default constructor
{
var resultType = typeof(T);
//if your type has not default constructor
var result = (T)Activator.CreateInstance(typeof(T), activationData);
//if it has default constructor
var result = new T();
//create an instance of xml reader
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(yourXml);
//expecting that your xml response will always have the same structure
if (xmlDocument.SelectSingleNode("RESPONSE/SINGLE") != null)
{
foreach(XmlNode node in xmlDocument.SelectNodes("RESPONSE/SINGLE/KEY"))
{
var prop = resultType.GetProperty(node.Attributes["name"].Value);
if (prop != null)
{
var value = prop.SelectSingleNode("Value").Value;
//if value does not exist - check if null value can be assigned
if (value == null && (!prop.PropertyType.IsValueType || (Nullable.GetUnderlyingType(prop.PropertyType) != null)))
{
prop.SetValue(result, value); //explicitly setting the required value
}
else if (value != null)
{
//we receiving the string, so for number parameters we should parse it
if (IsNumberType(prop.PropertyType))
{
prop.SetValue(result, double.Parse(value));
}
else
{
prop.SetValue(result, value); //will throw an exception if property type is not a string
}
//need some additional work for DateTime, TimeSpan, arrays and other
}
}
else
{
//remove next line if you do not need a validation for property presence
throw new ArgumentException("Could not find the required property " + node.Attributes["name"].Value);
}
}
}
else
{
throw new ArgumentException("Xml has invalid structure");
}
return result;
}
private bool IsNumberType(Type t)
{
var numberTypes = new[] {
typeof(byte), typeof(short), typeof(int), typeof(long),
typeof(float), typeof(double), typeof(decimal),
typeof(byte?), typeof(short?), typeof(int?), typeof(long?),
typeof(float?), typeof(double?), typeof(decimal?)
};
return numberTypes.Contains(t);
}
public T ConvertFromXml(字符串yourXml,参数对象[]activationData)
其中T:new()//如果您的类型具有默认构造函数
{
var resultType=typeof(T);
//如果您的类型没有默认构造函数
var result=(T)Activator.CreateInstance(typeof(T),activationData);
//如果它有默认构造函数
var结果=新的T();
//创建xml读取器的实例
var xmlDocument=新的xmlDocument();
LoadXml(yourXml);
//希望您的xml响应始终具有相同的结构
if(xmlDocument.SelectSingleNode(“响应/单个”)!=null)
{
foreach(xmlDocument.SelectNodes(“RESPONSE/SINGLE/KEY”)中的XmlNode节点)
{
var prop=resultType.GetProperty(node.Attributes[“name”].Value);
如果(prop!=null)
{
var value=prop.SelectSingleNode(“value”).value;
//如果值不存在-检查是否可以分配空值
if(value==null&(!prop.PropertyType.IsValueType | | |)(Nullable.getUnderlineType(prop.PropertyType)!=null)))
{
prop.SetValue(result,value);//显式设置所需的值
}
else if(值!=null)
{
//我们正在接收字符串,因此对于数字参数,我们应该解析它
if(IsNumberType(prop.PropertyType))
{
prop.SetValue(result,double.Parse(value));
}
其他的
{
prop.SetValue(result,value);//如果属性类型不是字符串,则将引发异常
}
//需要对DateTime、TimeSpan、数组和其他
}
}
其他的
{
//如果不需要验证属性是否存在,请删除下一行
抛出新ArgumentException(“找不到所需的属性”+node.Attributes[“name”].Value);
}
}
}
其他的
{
抛出新ArgumentException(“Xml具有无效结构”);
}
返回结果;
}
私有布尔IsNumberType(类型t)
{
var numberTypes=new[]{
typeof(字节)、typeof(短)、typeof(int)、typeof(长),
typeof(浮点)、typeof(双精度)、typeof(十进制),
typeof(字节?),typeof(短?),typeof(int?),typeof(长,
类型化(浮点?),类型化(双精度?),类型化(十进制?)
};
返回数字类型。包含(t);
}
和示例用法:
var xml = /*your method to get string representing a xml*/;
return ConvertFromXml<Course>(xml);
var xml=/*获取表示xml的字符串的方法*/;
返回ConvertFromXml(xml);
如果您可以使用json表示而不是xml获得响应,请查看
json.Net
库,它使用起来很简单。据我所知,此结构没有默认的反序列化程序。
正如@Nigrimist所说,您不需要使用开关盒
您可以使用XmlReader
读取xml,也可以使用XmlDocument
进行读取。下面是解析的示例代码。我没有测试过,所以请小心使用
public T ConvertFromXml<T>(string yourXml, params object[] activationData)
where T : new() //if your type has default constructor
{
var resultType = typeof(T);
//if your type has not default constructor
var result = (T)Activator.CreateInstance(typeof(T), activationData);
//if it has default constructor
var result = new T();
//create an instance of xml reader
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(yourXml);
//expecting that your xml response will always have the same structure
if (xmlDocument.SelectSingleNode("RESPONSE/SINGLE") != null)
{
foreach(XmlNode node in xmlDocument.SelectNodes("RESPONSE/SINGLE/KEY"))
{
var prop = resultType.GetProperty(node.Attributes["name"].Value);
if (prop != null)
{
var value = prop.SelectSingleNode("Value").Value;
//if value does not exist - check if null value can be assigned
if (value == null && (!prop.PropertyType.IsValueType || (Nullable.GetUnderlyingType(prop.PropertyType) != null)))
{
prop.SetValue(result, value); //explicitly setting the required value
}
else if (value != null)
{
//we receiving the string, so for number parameters we should parse it
if (IsNumberType(prop.PropertyType))
{
prop.SetValue(result, double.Parse(value));
}
else
{
prop.SetValue(result, value); //will throw an exception if property type is not a string
}
//need some additional work for DateTime, TimeSpan, arrays and other
}
}
else
{
//remove next line if you do not need a validation for property presence
throw new ArgumentException("Could not find the required property " + node.Attributes["name"].Value);
}
}
}
else
{
throw new ArgumentException("Xml has invalid structure");
}
return result;
}
private bool IsNumberType(Type t)
{
var numberTypes = new[] {
typeof(byte), typeof(short), typeof(int), typeof(long),
typeof(float), typeof(double), typeof(decimal),
typeof(byte?), typeof(short?), typeof(int?), typeof(long?),
typeof(float?), typeof(double?), typeof(decimal?)
};
return numberTypes.Contains(t);
}
public T ConvertFromXml(字符串yourXml,参数对象[]activationData)
其中T:new()//如果您的类型具有默认构造函数
{
var resultType=typeof(T);
//如果您的类型没有默认构造函数
var result=(T)Activator.CreateInstance(typeof(T),activationData);
//如果它有默认构造函数
var结果=新的T();
//创建xml读取器的实例
var xmlDocument=新的xmlDocument();
LoadXml(yourXml);
//希望您的xml响应始终具有相同的结构
if(xmlDocument.SelectSingleNode(“响应/单个”)!=null)
{
foreach(xmlDocument.SelectNodes(“RESPONSE/SINGLE/KEY”)中的XmlNode节点)
{
var prop=resultType.GetProperty(node.Attributes[“name”].Value);
如果(prop!=null)
{
var value=prop.SelectSingleNode(“value”).value;
//如果值不存在-检查是否可以分配空值
if(value==null&(!prop.PropertyType.IsValueType | | |)(Nullable.getUnderlineType(prop.PropertyType)!=null)))
{
prop.SetValue(result,value);//显式设置所需的值
}
else if(值!=null)
{
//我们正在接收字符串,因此对于数字参数,我们应该解析它
if(IsNumberType(prop.PropertyType))
{
prop.SetValue(result,double.Parse(value));
}
其他的
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
Course course = new Course();
course.ReadXML(FILENAME);
}
}
public class Course
{
public static List<Course> courses = new List<Course>();
public int id { get; set; }
public string shortname { get; set; } //short name of course
public string fullname { get; set; } //long name of course
public int enrolledusercount { get; set; } //Number of enrolled users in this course
public string idnumber { get; set; } //id number of course
public int visible { get; set; } //1 means visible, 0 means hidden course
public string summary { get; set; }
public int summaryformat { get; set; } //summary format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN)
public string format { get; set; } //course format: weeks, topics, social, site
public int showgrades { get; set; } //true if grades are shown, otherwise false
public string lang { get; set; } //forced course language
public int enablecompletion { get; set; } //true if completion is enabled, otherwise false
public void ReadXML(string filename)
{
XDocument doc = XDocument.Load(filename);
courses = doc.Descendants("SINGLE").Select(x => ReadKeys(x)).ToList();
}
public Course ReadKeys(XElement single)
{
Course newCourse = new Course();
foreach(XElement key in single.Descendants("KEY"))
{
switch(key.Attribute("name").Value)
{
case "id" :
newCourse.id = (int)key.Element("VALUE");
break;
}
}
return newCourse;
}
}
}