使用具有多个 child 元素的 Linq 解析 XML
Parse XML with Linq with multiple child elements
这是我关于 SO 的第一个问题,如果我做错了什么请告诉我!
我正在尝试解析与此类似的 XML:
<LiveUpdate>
<CityID>F0A21EA2</CityID>
<CityName>CityTown</CityName>
<UserName>john</UserName>
<ApplicationDetails>
<ApplicationDetail
Application="AC"
Licensed="true"
Version="2015.2"
Patch="0001"
/>
<ApplicationDetail
Application="AP"
Licensed="true"
Version="2015.2"
Patch="0002"
/>
</ApplicationDetails>
</LiveUpdate>
我有 class 看起来像这样的:
public class Client
{
public string cityID { get; set; }
public string cityName { get; set; }
public string userName { get; set; }
public List<Apps> appList { get; set; }
}
public class Apps
{
public string app { get; set; }
public string licensed { get; set; }
public string version { get; set; }
public string patch { get; set; }
}
我需要能够让客户端 class 包含要迭代的所有应用程序详细信息的列表。
到目前为止我想到的最好的是:
XDocument xml = XDocument.Load(@"C:\blah\Desktop.xml");
var liveUpdate = xml.Root;
var clients = (from e in liveUpdate.Elements()
select new Client()
{
cityID = e.Element("CityID").Value,
cityName = e.Element("CityName").Value,
userName = e.Element("UserName").Value,
appList = e.Elements("ApplicationDetails")
.Select(a => new Apps()
{
app = a.Element("Application").Value,
licensed = a.Element("Licensed").Value,
version = a.Element("Version").Value,
patch = a.Element("Patch").Value
}).ToList()
});
但是,我目前 运行 遇到一个错误,指出 Object 引用未设置为 object 的实例。
我在这里看到了一些类似的例子,但不是在 multiple children.
之前处理数据
我对 XML 和 Linq 还很陌生,因此非常感谢您的帮助!
由于您已经定义了一个要反序列化的 class,您可以使用 XmlSerializer
为您反序列化它。
首先,让我们重命名您的一些 属性 名称,使其更接近 XML 和 c# naming conventions:
[XmlRoot("LiveUpdate")]
public class Client
{
public string CityID { get; set; }
public string CityName { get; set; }
public string UserName { get; set; }
[XmlArray("ApplicationDetails")]
[XmlArrayItem("ApplicationDetail")]
public List<Apps> AppList { get; set; }
}
public class Apps
{
[XmlAttribute]
public string Application { get; set; }
[XmlAttribute]
public bool Licensed { get; set; }
[XmlAttribute]
public string Version { get; set; }
[XmlAttribute]
public string Patch { get; set; }
}
然后添加以下扩展方法:
public static class XmlSerializationHelper
{
public static T LoadFromXML<T>(this string xmlString)
{
using (StringReader reader = new StringReader(xmlString))
{
object result = new XmlSerializer(typeof(T)).Deserialize(reader);
if (result is T)
{
return (T)result;
}
}
return default(T);
}
public static T LoadFromFile<T>(string filename)
{
using (var fs = new FileStream(filename, FileMode.Open))
{
object result = new XmlSerializer(typeof(T)).Deserialize(fs);
if (result is T)
{
return (T)result;
}
}
return default(T);
}
}
现在您可以从 XML 文件反序列化如下:
string fileName = @"C:\blah\Desktop.xml";
var client = XmlSerializationHelper.LoadFromFile<Client>(fileName);
我手动更新了您的 Client
class 以正确映射到所提供的 XML,但如果您想自动执行此操作,请参见此处:Generate C# class from XML。
- 您的 XML 仅包含一个 LiveUpdate 标记,因此您无需遍历其中的所有元素,只需查看 Root 元素即可。
- 在 ApplicationDetails 中,
Application
、Licensed
等是 属性 ,而不是 元素 。使用 .Attribute()
访问它们。
- ApplicationDetails 是一个单独的标签,里面有
ApplicationDetail
个标签。
- 您的 LiveUpdate 标记中没有 DateTime 元素。
这个有效:
var liveUpdate = xml.Root;
var e = liveUpdate;
var clients = new Client()
{
cityID = e.Element("CityID").Value,
cityName = e.Element("CityName").Value,
userName = e.Element("UserName").Value,
//dateTime = e.Element("DateTime").Value,
appList = e.Element("ApplicationDetails").Elements("ApplicationDetail")
.Select(a => new Apps()
{
app = a.Attribute("Application").Value,
licensed = a.Attribute("Licensed").Value,
version = a.Attribute("Version").Value,
patch = a.Attribute("Patch").Value
}).ToList()
};
这是我关于 SO 的第一个问题,如果我做错了什么请告诉我!
我正在尝试解析与此类似的 XML:
<LiveUpdate>
<CityID>F0A21EA2</CityID>
<CityName>CityTown</CityName>
<UserName>john</UserName>
<ApplicationDetails>
<ApplicationDetail
Application="AC"
Licensed="true"
Version="2015.2"
Patch="0001"
/>
<ApplicationDetail
Application="AP"
Licensed="true"
Version="2015.2"
Patch="0002"
/>
</ApplicationDetails>
</LiveUpdate>
我有 class 看起来像这样的:
public class Client
{
public string cityID { get; set; }
public string cityName { get; set; }
public string userName { get; set; }
public List<Apps> appList { get; set; }
}
public class Apps
{
public string app { get; set; }
public string licensed { get; set; }
public string version { get; set; }
public string patch { get; set; }
}
我需要能够让客户端 class 包含要迭代的所有应用程序详细信息的列表。
到目前为止我想到的最好的是:
XDocument xml = XDocument.Load(@"C:\blah\Desktop.xml");
var liveUpdate = xml.Root;
var clients = (from e in liveUpdate.Elements()
select new Client()
{
cityID = e.Element("CityID").Value,
cityName = e.Element("CityName").Value,
userName = e.Element("UserName").Value,
appList = e.Elements("ApplicationDetails")
.Select(a => new Apps()
{
app = a.Element("Application").Value,
licensed = a.Element("Licensed").Value,
version = a.Element("Version").Value,
patch = a.Element("Patch").Value
}).ToList()
});
但是,我目前 运行 遇到一个错误,指出 Object 引用未设置为 object 的实例。 我在这里看到了一些类似的例子,但不是在 multiple children.
之前处理数据我对 XML 和 Linq 还很陌生,因此非常感谢您的帮助!
由于您已经定义了一个要反序列化的 class,您可以使用 XmlSerializer
为您反序列化它。
首先,让我们重命名您的一些 属性 名称,使其更接近 XML 和 c# naming conventions:
[XmlRoot("LiveUpdate")]
public class Client
{
public string CityID { get; set; }
public string CityName { get; set; }
public string UserName { get; set; }
[XmlArray("ApplicationDetails")]
[XmlArrayItem("ApplicationDetail")]
public List<Apps> AppList { get; set; }
}
public class Apps
{
[XmlAttribute]
public string Application { get; set; }
[XmlAttribute]
public bool Licensed { get; set; }
[XmlAttribute]
public string Version { get; set; }
[XmlAttribute]
public string Patch { get; set; }
}
然后添加以下扩展方法:
public static class XmlSerializationHelper
{
public static T LoadFromXML<T>(this string xmlString)
{
using (StringReader reader = new StringReader(xmlString))
{
object result = new XmlSerializer(typeof(T)).Deserialize(reader);
if (result is T)
{
return (T)result;
}
}
return default(T);
}
public static T LoadFromFile<T>(string filename)
{
using (var fs = new FileStream(filename, FileMode.Open))
{
object result = new XmlSerializer(typeof(T)).Deserialize(fs);
if (result is T)
{
return (T)result;
}
}
return default(T);
}
}
现在您可以从 XML 文件反序列化如下:
string fileName = @"C:\blah\Desktop.xml";
var client = XmlSerializationHelper.LoadFromFile<Client>(fileName);
我手动更新了您的 Client
class 以正确映射到所提供的 XML,但如果您想自动执行此操作,请参见此处:Generate C# class from XML。
- 您的 XML 仅包含一个 LiveUpdate 标记,因此您无需遍历其中的所有元素,只需查看 Root 元素即可。
- 在 ApplicationDetails 中,
Application
、Licensed
等是 属性 ,而不是 元素 。使用.Attribute()
访问它们。 - ApplicationDetails 是一个单独的标签,里面有
ApplicationDetail
个标签。 - 您的 LiveUpdate 标记中没有 DateTime 元素。
这个有效:
var liveUpdate = xml.Root;
var e = liveUpdate;
var clients = new Client()
{
cityID = e.Element("CityID").Value,
cityName = e.Element("CityName").Value,
userName = e.Element("UserName").Value,
//dateTime = e.Element("DateTime").Value,
appList = e.Element("ApplicationDetails").Elements("ApplicationDetail")
.Select(a => new Apps()
{
app = a.Attribute("Application").Value,
licensed = a.Attribute("Licensed").Value,
version = a.Attribute("Version").Value,
patch = a.Attribute("Patch").Value
}).ToList()
};