通过 LINQ 从 XML 反序列化
Posted
技术标签:
【中文标题】通过 LINQ 从 XML 反序列化【英文标题】:DeSerialize From XML By LINQ 【发布时间】:2021-12-12 06:39:11 【问题描述】:所以,我有 XML 文件:
<?xml version="1.0" encoding="utf-8"?>
<RailwayStations>
<RailwayStation />
<RailwayStationName>Verdansk</RailwayStationName>
<RailwayStationCountOfWays>10</RailwayStationCountOfWays>
<RailwayStationCountOfLuggageRooms>3</RailwayStationCountOfLuggageRooms>
<RailwayStationLuggageRoomHeight>10</RailwayStationLuggageRoomHeight>
<RailwayStationLuggageRoomWidth>20</RailwayStationLuggageRoomWidth>
<RailwayStationLuggageRoomDepth>30</RailwayStationLuggageRoomDepth>
<RailwayStationLuggageRoomHeight>11</RailwayStationLuggageRoomHeight>
<RailwayStationLuggageRoomWidth>21</RailwayStationLuggageRoomWidth>
<RailwayStationLuggageRoomDepth>31</RailwayStationLuggageRoomDepth>
<RailwayStationLuggageRoomHeight>12</RailwayStationLuggageRoomHeight>
<RailwayStationLuggageRoomWidth>22</RailwayStationLuggageRoomWidth>
<RailwayStationLuggageRoomDepth>32</RailwayStationLuggageRoomDepth>
</RailwayStations>
而且,我想从中读取。我下面的代码将 null 返回到所有字段
var xDoc = XDocument.Load(fileName);
var obj = from xElement in xDoc.Element("RailwayStations")?.Elements("RailwayStation")
select new RailwayStation()
RailwayStationName = xElement.Element("RailwayStationName")?.Value,
RailwayStationCountOfWays = Convert.ToInt32(xElement.Element("RailwayStationCountOfWays")?.Value),
RailwayStationCountOfLuggageRooms =
Convert.ToInt32(xElement.Element("RailwayStationCountOfLuggageRooms")?.Value),
LuggageRooms = (from element in xDoc.Element("RailwayStations")?.Elements("RailwayStation")
select new LuggageRoom()
_luggageRoomHeight = Convert.ToInt32(element.Element("RailwayStationLuggageRoomHeight")?.Value),
_luggageRoomWidth = Convert.ToInt32(element.Element("RailwayStationLuggageRoomHeight")?.Value),
_luggageRoomDepth = Convert.ToInt32(element.Element("RailwayStationLuggageRoomHeight")?.Value),
).ToList()
;
return obj;
有什么建议吗?关于 XML 文件 - 用自制的方法创建,我将XElements
添加到XDocument
并保存。
【问题讨论】:
为什么要搜索RailwayStation
的inside 元素?该元素没有任何子元素,只有兄弟姐妹。
更好的问题,为什么RailwayStation
没有孩子?选择了节点名,为什么除了RailwayStation
之外还有来自RailwayStations
的其他子节点?
@gunr2171,序列化新手。在我发现的示例中,类似的结构。
@gunr2171,我想我明白了。
xml 看起来格式不正确,修复您的 XML,代码将更有可能工作
【参考方案1】:
根据您代码中的预期,您的 XML 格式似乎不正确,这就是您的代码所期望的:
<?xml version="1.0" encoding="utf-8"?>
<RailwayStations>
<RailwayStation>
<RailwayStationName>Verdansk</RailwayStationName>
<RailwayStationCountOfWays>10</RailwayStationCountOfWays>
<RailwayStationCountOfLuggageRooms>3</RailwayStationCountOfLuggageRooms>
<LuggageRooms>
<LuggageRoom>
<RailwayStationLuggageRoomHeight>10</RailwayStationLuggageRoomHeight>
<RailwayStationLuggageRoomWidth>20</RailwayStationLuggageRoomWidth>
<RailwayStationLuggageRoomDepth>30</RailwayStationLuggageRoomDepth>
</LuggageRoom>
<LuggageRoom>
<RailwayStationLuggageRoomHeight>11</RailwayStationLuggageRoomHeight>
<RailwayStationLuggageRoomWidth>21</RailwayStationLuggageRoomWidth>
<RailwayStationLuggageRoomDepth>31</RailwayStationLuggageRoomDepth>
</LuggageRoom>
<LuggageRoom>
<RailwayStationLuggageRoomHeight>12</RailwayStationLuggageRoomHeight>
<RailwayStationLuggageRoomWidth>22</RailwayStationLuggageRoomWidth>
<RailwayStationLuggageRoomDepth>32</RailwayStationLuggageRoomDepth>
</LuggageRoom>
</LuggageRooms>
</RailwayStation>
<RailwayStation>
<RailwayStationName>Number 2</RailwayStationName>
<RailwayStationCountOfWays>8</RailwayStationCountOfWays>
<RailwayStationCountOfLuggageRooms>1</RailwayStationCountOfLuggageRooms>
<LuggageRooms>
<LuggageRoom>
<RailwayStationLuggageRoomHeight>12</RailwayStationLuggageRoomHeight>
<RailwayStationLuggageRoomWidth>22</RailwayStationLuggageRoomWidth>
<RailwayStationLuggageRoomDepth>32</RailwayStationLuggageRoomDepth>
</LuggageRoom>
</LuggageRooms>
</RailwayStation>
</RailwayStations>
现在请注意,RailwayStations
(复数)现在有多个名为 RailwayStation
的子元素。行李室也是如此,代码实际上对这些做出了错误的假设,但数据的结构应该使每个行李室都包含在一个外部元素中,在这个例子中我称之为LuggageRooms
var xDoc = XDocument.Load(fileName);
var obj = from xElement in xDoc.Element("RailwayStations")?.Elements("RailwayStation")
select new RailwayStation()
RailwayStationName = xElement.Element("RailwayStationName")?.Value,
RailwayStationCountOfWays = Convert.ToInt32(xElement.Element("RailwayStationCountOfWays")?.Value),
RailwayStationCountOfLuggageRooms =
Convert.ToInt32(xElement.Element("RailwayStationCountOfLuggageRooms")?.Value),
LuggageRooms = (from element in xElement.Elements("LuggageRooms")
select new LuggageRoom()
_luggageRoomHeight = Convert.ToInt32(element.Element("RailwayStationLuggageRoomHeight")?.Value),
_luggageRoomWidth = Convert.ToInt32(element.Element("RailwayStationLuggageRoomWidth")?.Value),
_luggageRoomDepth = Convert.ToInt32(element.Element("RailwayStationLuggageRoomDepth")?.Value),
).ToList()
;
return obj;
看起来你这里有一个XY problem,如果你也在构造 XML,请检查那里的逻辑以确保它有意义。
如果您正在构建这个 XML,那么请考虑使用更简单的命名元素的模式:
<RailwayStation>
<Name>Number 2</Name>
<CountOfWays>8</CountOfWays>
<CountOfLuggageRooms>1</CountOfLuggageRooms>
<LuggageRooms>
<LuggageRoom>
<Height>12</Height>
<Width>22</Width>
<Depth>32</Depth>
</LuggageRoom>
</LuggageRooms>
</RailwayStation>
那么你的代码可能是这样的:
var xDoc = XDocument.Load(fileName);
var obj = from xElement in xDoc.Element("RailwayStations")?.Elements("RailwayStation")
select new RailwayStation()
Name = xElement.Element("Name")?.Value,
CountOfWays = Convert.ToInt32(xElement.Element("CountOfWays")?.Value),
CountOfLuggageRooms = Convert.ToInt32(xElement.Element("CountOfLuggageRooms")?.Value),
LuggageRooms = (from element in xElement.Elements("LuggageRooms")
select new LuggageRoom()
Height = Convert.ToInt32(element.Element("Height")?.Value),
Width = Convert.ToInt32(element.Element("Width")?.Value),
Depth = Convert.ToInt32(element.Element("Depth")?.Value),
).ToList()
;
return obj;
我意识到这是一个重大的结构变化,但它将简化所有未来的处理并减少通过网络传输的字节数。
【讨论】:
以上是关于通过 LINQ 从 XML 反序列化的主要内容,如果未能解决你的问题,请参考以下文章
如何反序列化 System.Xml.Linq.XElement?