如何从 XML 的特定部分将 XML 序列化为对象?
Posted
技术标签:
【中文标题】如何从 XML 的特定部分将 XML 序列化为对象?【英文标题】:How to serialize XML to object from particular part of XML? 【发布时间】:2021-12-10 15:51:02 【问题描述】:我有问题如何将 XML 序列化为对象列表,但只能从一个大 XML 的特定部分。我的意思是这样的:
仅从项目中获取数据并制作项目对象列表。
<tXML>
<nameOfUser>MK</nameOfUser>
<amouthOfPO>14</amouthOfPO>
<todayDate></todayDate>
<warehouses>
<warehouse id="1">
<name>AD1</name>
</warehouse>
<warehouse id="2">
<name>AD2</name>
</warehouse>
<warehouse id="3">
<name>AD3</name>
</warehouse>
</warehouses>
<items>
<warehause id="1">
<items>
<item>
<name>item1</name>
<protectionLevel>AMB</protectionLevel>
<description>DescAMB1FORID1</description>
</item>
<item>
<name>item2</name>
<protectionLevel>CHL</protectionLevel>
<description>DescCHL1FORID1</description>
</item>
<item>
<name>item3</name>
<protectionLevel>AMB</protectionLevel>
<description>3</description>
</item>
</items>
</warehause>
<warehause id="3">
<items>
<item>
<name>item1AMB2222</name>
<protectionLevel>AMBB222222</protectionLevel>
<description>DESCRIPTIONITEM1AM222222B</description>
</item>
<item>
<name>item222222CHL</name>
<protectionLevel>C222222222LL</protectionLevel>
<description>ITEM2CH22ILLERAD1</description>
</item>
<item>
<name>2222222222223</name>
<protectionLevel>222222223</protectionLevel>
<description>3222222222222</description>
</item>
</items>
</warehause>
<warehause id="3">
<items>
<item>
<name>item1333333AMB</name>
<protectionLevel>AM3333BB</protectionLevel>
<description>DESCR333IPTIONITEM1AMB</description>
</item>
<item>
<name>item233333CHL</name>
<protectionLevel>C33333HLL</protectionLevel>
<description>ITEM2CHI333LLERAD1</description>
</item>
<item>
<name>33</name>
<protectionLevel>33</protectionLevel>
<description>33</description>
</item>
</items>
</warehause>
</items>
</tXML>
我的物品类别如下所示:
namespace UseFiles
public class Item
public string Name get; set;
public string ProtectionLevel get; set;
public string Description get; set;
为对象更改 XML(仅从)的最佳(最佳)方法是什么?我想了两个办法:
-
xmlSerializer
或者只是从 XMLNodeList 循环分配值..
【问题讨论】:
【参考方案1】:首先best (optimally) way
可以解释为:1 - 最佳性能,2 - 更多(易于)可读的代码。
我认为最好的性能应该是使用 FileStream
和 XmlReader
和 XmlWriter
。但在你的情况下,这可能会导致一些额外的复杂性,因为items
位于wherehouses
内,任何item
都应该在特定的“wherehouse”内。所以你应该在具体的wherehouse
中找到项目,并在一些更新后将这些项目保存在相同的wherehouse
中。任何项目都可以:1 - 更新,2 - 添加,3 - 删除,来自wherehouse
,因此现有 xml 文档的更新变得更加复杂。
基于以上,我推荐使用LinqToXml
,它的性能效率不高,但足够快在大多数情况下,有你需要的任何工具(搜索和替换具体xml中的元素列表-tag) 并且更具可读性。
你可以这样使用它:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace TestProgram
class Program
private const string _PATH = @"path to xml-file";
static void Main(string[] args)
const string myWherehouseId = "3";
var document = XDocument.Load(_PATH);
var itemsElement = document.Root.Element("items");
List<Item> myItems = null;
foreach (XElement wherehause in itemsElement.Elements())
if (wherehause.Attribute("id").Value == myWherehouseId)
myItems = FromXml(wherehause.Element("items").Elements());
// Do some things
myItems[0].Name += "1";
myItems[0].Description += "2";
myItems.RemoveAt(1);
myItems.Add(
new Item
Name = "Name212",
Description = "Sometext123213",
ProtectionLevel = "CHL"
);
XElement[] updatedElements = ToXml(myItems);
// replace old xml nodes with new ones
wherehause.Element("items").ReplaceNodes(updatedElements);
break;
document.Save(_PATH);
public static List<Item> FromXml(IEnumerable<XElement> elements)
// you could use any custom mapper for conversion from XElement to Item
return elements.Select(el => new Item
Name = el.Element("name").Value,
ProtectionLevel = el.Element("protectionLevel").Value,
Description = el.Element("description").Value
).ToList();
public static XElement[] ToXml(List<Item> items)
// you could use any custom mapper for conversion from Item to XElement
return items
.Select(item =>
new XElement("item",
new XElement("name", item.Name),
new XElement("protectionLevel", item.ProtectionLevel),
new XElement("description", item.Description)))
.ToArray();
public class Item
public string Name get; set;
public string ProtectionLevel get; set;
public string Description get; set;
在我看来,best (optimally) way
在性能和代码可读性之间做出了合理的折衷。
这是我最好的方法;)
【讨论】:
非常感谢您的回答!您能否也谈谈反序列化?例如如何从这个 xml 中只获取项目括号中的项目? 简而言之:如果您使用XmlSerializer
某些Deserialize
方法包含读取器参数,因此您需要将该读取器移动到标记,而不是需要反序列化,然后调用@987654336 @。反序列化应该没那么难,但序列化应该是。【参考方案2】:
嗯,解析大型 xml 文件的 XmlReader 方法。或者,您可以尝试Cinchoo ETL - 一个开源库,只需几行代码即可解析如此大的文件。
using (var r = ChoXmlReader<Item>.LoadText(xml)
.WithXPath("//item")
)
foreach (var rec in r)
rec.Print();
小提琴样例:https://dotnetfiddle.net/otYq5j
免责声明:我是这个库的作者。
【讨论】:
以上是关于如何从 XML 的特定部分将 XML 序列化为对象?的主要内容,如果未能解决你的问题,请参考以下文章
XML 文档中存在错误 (0, 0) - 将 XML 反序列化为对象时出错
如何将复杂的 C# 类序列化为 XML 并将其作为 .net 核心 API 的响应发送?