我正在使用标准的.NET XmlSerializer
反序列化以下xml:
<root>
<Element>
<Grouping1>
<Item1>First</Item1>
<Item2>Second</Item2>
</Grouping1>
<Grouping2>
<Item3>Third</Item3>
</Grouping2>
</Element>
</root>
我想将其序列化为以下类:
class Element
{
[XmlElement("Item1")]
public string Item1 { get; set; }
[XmlElement("Item2")]
public string Item2 { get; set; }
[XmlElement("Item3")]
public string Item3 { get; set; }
}
当然不起作用,因为-例如-<Item1>
不在<Element>
中,而是在逻辑容器<Grouping1>
中。
是否有一种方法可以告诉XmlSerializer
在Item1
元素中寻找<Grouping1>
?使[XmlElement("Grouping1.Item1")]
的行下降
PS:我不想创建Grouping1
类(如建议的here),因为分组只是逻辑容器,不应具有自己的类。
使用Xml Linq。自定义序列化器会复杂得多
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication4
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<Element> elements = doc.Descendants("Element").Select(x => new Element()
{
Item1 = (string)x.Descendants("Item1").FirstOrDefault(),
Item2 = (string)x.Descendants("Item2").FirstOrDefault(),
Item3 = (string)x.Descendants("Item3").FirstOrDefault()
}).ToList();
}
}
class Element
{
public string Item1 { get; set; }
public string Item2 { get; set; }
public string Item3 { get; set; }
}
}
这里是序列化器的外观
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Xml.Schema;
namespace ConsoleApplication4
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Root));
Root root = (Root)serializer.Deserialize(reader);
}
}
[XmlRoot("root")]
public class Root
{
[XmlElement("Element")]
public List<Element> Element { get; set; }
}
public class Element : IXmlSerializable
{
private string Item1 { get; set; }
private string Item2 { get; set; }
private string Item3 { get; set; }
public void WriteXml(XmlWriter writer)
{
XElement element = new XElement("Element", new object[] {
new XElement("Grouping1", new object[] {
new XElement("Item1", Item1),
new XElement("Item2", Item2)
}),
new XElement("Grouping2", new XElement("Item3", Item3))
});
element.WriteTo(writer);
}
public void ReadXml(XmlReader reader)
{
XElement element = (XElement)XElement.ReadFrom(reader);
Item1 = (string)element.Descendants("Item1").FirstOrDefault();
Item2 = (string)element.Descendants("Item2").FirstOrDefault();
Item3 = (string)element.Descendants("Item3").FirstOrDefault();
}
public XmlSchema GetSchema()
{
return (null);
}
}
}
我不想创建Grouping1类...
不确定在不创建输出该XML的对象的情况下使用序列化是否可行。
串行化的替代方法是使用XmlReader来提取所讨论的属性(Item1
,Item2
和Item3
),并创建Element
类型和XmlWriter的列表生成整个XML文件。
假设您的XML文件具有多个Element
条目,例如:
<root>
<Element>
<Grouping1>
<Item1>First1</Item1>
<Item2>Second1</Item2>
</Grouping1>
<Grouping2>
<Item3>Third1</Item3>
</Grouping2>
</Element>
<Element>
<Grouping1>
<Item1>First2</Item1>
<Item2>Second2</Item2>
</Grouping1>
<Grouping2>
<Item3>Third2</Item3>
</Grouping2>
</Element>
</root>
...和一个名为Element
:]的类
//The serializable attribute is not required here... public class Element { public Element() { } public string Item1 { get; set; } public string Item2 { get; set; } public string Item3 { get; set; } public override string ToString() => $"{Item1}, {Item2}, {Item3}"; }
[创建一个函数来读取文件,创建并返回
Element
项目的列表:
public List<Element> ReadElements(string xmlFile) { var elements = new List<Element>(); Element ele = null; using (var xr = XmlReader.Create(xmlFile)) while (xr.Read()) { if (xr.NodeType == XmlNodeType.Element) { if (xr.Name == "Element") ele = new Element(); else if (xr.Name == "Item1") { xr.Read(); ele.Item1 = xr.Value; } else if (xr.Name == "Item2") { xr.Read(); ele.Item2 = xr.Value; } else if (xr.Name == "Item3") { xr.Read(); ele.Item3 = xr.Value; } } else if (xr.NodeType == XmlNodeType.EndElement) if (xr.Name == "Element") elements.Add(ele); } return elements; }
...和一种写方法:
public void WriteElements(string xmlFile, IEnumerable<Element> elements) { var xmlSet = new XmlWriterSettings { Indent = true, NewLineOnAttributes = true, WriteEndDocumentOnClose = true, }; using (var xr = XmlWriter.Create(xmlFile, xmlSet)) { xr.WriteStartElement("root"); foreach(var ele in elements) { xr.WriteStartElement("Element"); xr.WriteStartElement("Grouping1"); xr.WriteStartElement("Item1"); xr.WriteString(ele.Item1); xr.WriteEndElement(); xr.WriteStartElement("Item2"); xr.WriteString(ele.Item2); xr.WriteEndElement(); xr.WriteEndElement(); xr.WriteStartElement("Grouping2"); xr.WriteStartElement("Item3"); xr.WriteString(ele.Item3); xr.WriteEndElement(); xr.WriteEndElement(); xr.WriteEndElement(); } } }
读取和写入文件的测试,如:
private void TheCaller() { var xmlFile = "XmlFile.xml"; var elements = ReadElements(xmlFile); elements.ForEach(x => Console.WriteLine(x)); //... WriteElements(xmlFile, elements); }
在我的输出窗口中打印:
First1, Second1, Third1
First2, Second2, Third2