我遇到了一个问题,我需要对此进行基本反序列化:
<?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个会话元素,可能有4个,20个或0个,我现在拥有的代码只是被破坏了,我是想知道什么是让这种方法发挥作用的好方法?
目前我已经达到了XDocument类的目的,所有这些都被加载了。 我需要返回一个包含这些数据的多维数组。
编辑:
当前代码,已完全破解:
var xmlSessions = xmlDATA.Descendants("api_data").Elements("sessions").Select(x => x);
result = new string[xmlDATA.Descendants("api_data").Count(), 7];
编辑2: 更多信息
我认为MultiDimensional Array的方式如下:
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.
答案 0 :(得分:3)
您可以定义以下类表示:
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; }
}
密钥是[XmlElement]
属性上的sessions
标记,它将指示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属性来转移到一些更好的命名约定,我们也可以List<Session>
启动而不是数组:
[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; }
}
编辑:刚刚注意到你需要把它变成一个多维数组(不知道为什么,但是你指定了它的遗产)。那么在这一点上,你有一个很好的对象模型,你可以从中进行这种数据传输。不知道你是如何进行输入的,但我们现在只假设object
类型数组:
ApiData apiData = DeserializeMyApiData(); // from above
array[0][0] = apiData.Status;
for(int i = 1; i <= apiData.Sessions.Count; i++)
{
var session = apiData.Sessions[i - 1];
array[i] = new object[8];
array[i][0] = session.ID;
array[i][1] = session.SessionID;
array[i][2] = session.GameID;
array[i][3] = session.MaxPlayers;
array[i][4] = session.HostIP;
array[i][5] = session.HostPort;
array[i][6] = session.InProgress;
array[i][7] = session.TimeStamp;
}
无论你有多少会话,都会经历并建立你的数组。
答案 1 :(得分:0)
你可以将'sessions'标签包装在'session_list'标签内吗?
如果是这样,你可以使用这样的东西加载它:
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;
}
}
如果无法更改xml文件的格式,则可能需要在其自己的步骤中加载状态,然后加载会话,就像api-data是列表变量一样,尽管状态存在,但可能给你一个错误。
答案 2 :(得分:0)
如果你真的只想要一个多维数组,你可以用一行(有点长的)代码从那个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" }
}