C# 具有多个子元素且具有相同名称的多个元素

C# 具有多个子元素且具有相同名称的多个元素,c#,xml,children,C#,Xml,Children,我遇到了一个问题,我需要对其进行基本的反序列化: <?xml version="1.0" encoding="UTF-8"?> <api_data> <status>ok</status> <sessions> <id>2</id> <sessionID>6bfd1f1a7e87a8a6ed476234ad1d6e86</sessionID> <gam

我遇到了一个问题,我需要对其进行基本的反序列化:

<?xml version="1.0" encoding="UTF-8"?>
<api_data>
  <status>ok</status>
  <sessions>
    <id>2</id>
    <sessionID>6bfd1f1a7e87a8a6ed476234ad1d6e86</sessionID>
    <gameID>1</gameID>
    <maxPlayers>8</maxPlayers>
    <hostIP>12.0.0.1</hostIP>
    <hostPort>1993</hostPort>
    <inProgress>0</inProgress>
    <timestamp>1358894690</timestamp>
  </sessions>
  <sessions>
    <id>3</id>
    <sessionID>eeb4dc2df32f885c2b7d13f28a246830</sessionID>
    <gameID>1</gameID>
    <maxPlayers>8</maxPlayers>
    <hostIP>12.0.0.1</hostIP>
    <hostPort>1993</hostPort>
    <inProgress>0</inProgress>
    <timestamp>1358894732</timestamp>
  </sessions>
</api_data>
编辑2: 更多信息

我认为多维数组的方式如下所示:

array[0,0] "ok" //Status
array[1,0 to 7] //First Session details go here
array[2,0 to 7] //Second session details go here, and so forth.

您能将“会话”标记包装在“会话列表”标记中吗

如果是这样,您可以使用类似这样的方式来加载它:

public class api_data {

    public class sessions {
        public string id { get; set; }
        public string sessionID { get; set; }
        // put all the other vars in here ...
    }

    public string status { get; set; }           
    public List<sessions> session_list { get; set; }

    public static api_data LoadFromXML(string xmlFile) {

        api_data localApiData;

        // serialize from file
        try {
            var xs = new XmlSerializer(typeof(api_data),
                     new XmlRootAttribute("api_data"));
            using (TextReader tr = new StreamReader(xmlFile)) {
                localApiData= xs.Deserialize(tr) as api_data;
            }
        }
        catch (Exception ex) {
            Log.LogError(string.Format(
               "Error reading api_data file {0}: {1}",
               xmlFile, ex.Message));
            return null;
        }


        return localApiData;
    }
}
公共类api\u数据{
公开课{
公共字符串id{get;set;}
公共字符串sessionID{get;set;}
//把其他所有的Var都放在这里。。。
}
公共字符串状态{get;set;}
公共列表会话_List{get;set;}
公共静态api_数据LoadFromXML(字符串xmlFile){
api_数据本地api数据;
//从文件序列化
试一试{
var xs=新的XmlSerializer(typeof(api_数据),
新的XmlRootAttribute(“api_数据”);
使用(TextReader tr=新的StreamReader(xmlFile)){
localApiData=xs。反序列化(tr)为api_数据;
}
}
捕获(例外情况除外){
Log.LogError(string.Format(
“读取api_数据文件{0}:{1}时出错”,
xmlFile,ex.Message));
返回null;
}
返回本地数据;
}
}

如果无法更改xml文件的格式,则可能需要在其自己的步骤中加载状态,然后加载会话,就像api数据是列表变量一样,尽管状态存在,但这可能会给您带来错误。

您可以定义以下类表示:

public class api_data
{
    public string status { get; set; }

    [XmlElement]
    public session[] sessions { get; set; }
}

public class session
{
    public int id { get; set; }
    public string sessionID { get; set; }
    public int gameID { get; set; }
    public int maxPlayers { get; set; }
    public string hostIP { get; set; }
    public int hostPort { get; set; }
    public int inProgress { get; set; }
    public int timestamp { get; set; }
}
关键是
sessions
属性上的
[xmlement]
标记,它将指示
XmlSerializer
使用您提供的模式示例读取/写入XML。要对其进行反序列化,可以使用
XmlSerializer

//this might change, not sure how you obtain your xml, 
//but let's assume you already have it available as a string
byte[] xmlBytes = System.Text.Encoding.UTF8.GetBytes(xmlData); 

var stream = new MemoryStream(xmlBytes);
XmlSerializer serializer = new XmlSerializer(typeof(api_data));
api_data apidata = (api_data)serializer.Deserialize(stream);
不需要更多的XML装饰或设置就可以读入(测试和工作)

<>编辑:虽然您可能想考虑使用一些其他XML属性来传递一些更好的命名约定,我们也可以<代码>列表< /C> >引导而不是数组:

[XmlRoot("api_data")]
public class ApiData
{
    [XmlElement("status")]
    public string Status { get; set; }

    [XmlElement("sessions")]
    public List<Session> Sessions { get; set; }
}

public class Session
{
    [XmlElement("id")]
    public int ID { get; set; }

    [XmlElement("sessionID")]
    public string SessionID { get; set; }

    [XmlElement("gameID")]
    public int GameID { get; set; }

    [XmlElement("maxPlayers")]
    public int MaxPlayers { get; set; }

    [XmlElement("hostIP")]
    public string HostIP { get; set; }

    [XmlElement("hostPort")]
    public int HostPort { get; set; }

    [XmlElement("inProgress")]
    public int InProgress { get; set; }

    [XmlElement("timestamp")]
    public int TimeStamp { get; set; }
}
无论您有多少个会话,这都将贯穿并构建您的数组。

如果您真的只需要一个多维数组,您可以通过一行(稍微长一点的)代码从该XML获得它:

string[][] items = XDocument.Parse(xml).Root.Elements().Select(e => e.HasElements ? e.Elements().Select(ei => ei.Value).ToArray() : new string[]{ e.Value }).ToArray();
或者让同一条语句更具可读性:

string[][] items = 
    XDocument.Parse(xml).Root
             .Elements().Select(e => e.HasElements ? 
                 e.Elements().Select(ei => ei.Value).ToArray() : new string[]{ e.Value })
             .ToArray();
从该源XML生成如下数组:

string[][]
{
   { "ok" },
   { "2", "6bfd1f1a7e87a8a6ed476234ad1d6e86", "1", "8", "12.0.0.1", "1993", "0", "1358894690" },
   { "3", "eeb4dc2df32f885c2b7d13f28a246830", "1", "8", "12.0.0.1", "1993", "0", "1358894732" }
}
如果要单独获取状态,并将其他值放入多维数组中,可以执行以下操作:

XDocument doc = XDocument.Parse(xml);
string status = doc.XPathSelectElement("/*/status").Value;
string[][] items = 
    doc.Root.Elements().Where(e => e.HasElements)
       .Select(e => e.Elements().Select(ei => ei.Value).ToArray()).ToArray();
这将产生与上面相同的结果,除了status是一个单独的字符串,并且items中不会有第一个单元素数组:

string[][]
{
   { "2", "6bfd1f1a7e87a8a6ed476234ad1d6e86", "1", "8", "12.0.0.1", "1993", "0", "1358894690" },
   { "3", "eeb4dc2df32f885c2b7d13f28a246830", "1", "8", "12.0.0.1", "1993", "0", "1358894732" }
}

您当前的代码是什么样子的?为什么需要多维数组?看起来您需要一个具有多个属性的
Sessions
类,以及一个具有
Status
属性和
Session
s数组的
ApiData
类。无法更改多维数组的外观,基本上,我认为多维数组的方式如下:数组[0][0]“ok”//状态数组[1][0到7]//第一个会话详细信息转到此处数组[2][0到7]//第二个会话详细信息转到此处,依此类推。这听起来不是个好主意。那么数组[0][0]是一个状态值,而数组[1][0]是一个id?这不是很容易管理的。如果数据以类和对象的形式表示,那么它将更易于使用。这还允许将XML自动反序列化为对象。我建议您研究一下.NET从XML反序列化类的能力。我知道,我希望我可以更改它,但整个系统都是这样构建的(不是我的系统)。一个问题是,我没有从文件加载它,它是直接从网页获取的。您可以将字符串转换为流,并且仍然使用上面的代码。类似于:新的StreamReader(新的MemoryStream(Encoding.ASCII.GetBytes(incomingString));非常感谢你的工作就像一个符咒,因为你把状态放在对象中,我可以访问对象来检查状态,所以我不必把它放在多维数组中,我可以保留它只是为了会话数据,非常感谢,真的很有帮助!
XDocument doc = XDocument.Parse(xml);
string status = doc.XPathSelectElement("/*/status").Value;
string[][] items = 
    doc.Root.Elements().Where(e => e.HasElements)
       .Select(e => e.Elements().Select(ei => ei.Value).ToArray()).ToArray();
string[][]
{
   { "2", "6bfd1f1a7e87a8a6ed476234ad1d6e86", "1", "8", "12.0.0.1", "1993", "0", "1358894690" },
   { "3", "eeb4dc2df32f885c2b7d13f28a246830", "1", "8", "12.0.0.1", "1993", "0", "1358894732" }
}