Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将moodle XML解析为C#(dotnet)对象_C#_Xml_Deserialization_Moodle_Moodle Api - Fatal编程技术网

将moodle XML解析为C#(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

我正在尝试反序列化从moodle web服务收到的XML响应

如果它有不同的命名属性,如id、shortname、idnumber等,我可以将其解析为dotnet对象。但它有一个关键属性数组,实际字段名作为值,在该数组中,有另一个节点具有字段值

以下是一个示例:

    <?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>&lt;p&gt;CS-101&lt;br /&gt;&lt;/p&gt;</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;
        }
    }
}