I haven't been able to find a question related to my specific problem.
我无法找到与我的具体问题相关的问题。
What I am trying to do is take a list of Xml nodes, and directly deserialize them to a List without having to create a class with attributes.
我要做的是获取Xml节点列表,并直接将它们反序列化为List,而不必创建具有属性的类。
So the xml (myconfig.xml) would look something like this...
所以xml(myconfig.xml)看起来像这样......
<collection>
<item>item1</item>
<item>item2</item>
<item>item3</item>
<item>etc...</item>
</collection>
In the end I would like a list of items as strings.
最后,我想要一个项目列表作为字符串。
The code would look like this.
代码看起来像这样。
XmlSerializer serializer = new XmlSerializer( typeof( List<string> ) );
using (XmlReader reader = XmlReader.Create( "myconfig.xml" )
{
List<string> itemCollection = (List<string>)serializer.Deserialize( reader );
}
I'm not 100% confident that this is possible, but I'm guessing it should be. Any help would be greatly appreciated.
我不是百分之百地确信这是可能的,但我猜它应该是。任何帮助将不胜感激。
3 个解决方案
#1
3
Are you married to the idea of using a serializer? If not, you can try Linq-to-XML. (.NET 3.5, C# 3 [and higher])
你嫁给了使用序列化器的想法吗?如果没有,您可以尝试Linq-to-XML。 (.NET 3.5,C#3 [及更高版本])
Based on your provided XML file format, this is the simple code.
根据您提供的XML文件格式,这是简单的代码。
// add 'using System.Xml.Linq' to your code file
string file = @"C:\Temp\myconfig.xml";
XDocument document = XDocument.Load(file);
List<string> list = (from item in document.Root.Elements("item")
select item.Value)
.ToList();
#2
1
Ok, interestingly enough I may have found half the answer by serializing an existing List.
好的,有趣的是,通过序列化现有的List,我可能找到了一半的答案。
The result I got is as follows...
我得到的结果如下......
This following code:
以下代码:
List<string> things = new List<string> { "thing1", "thing2" };
XmlSerializer serializer = new XmlSerializer(typeof(List<string>), overrides);
using (TextWriter textWriter = new StreamWriter("things.xml"))
{
serializer.Serialize(textWriter, things);
}
Outputs a result of:
输出结果:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>thing1</string>
<string>thing2</string>
</ArrayOfString>
I can override the root node by passing an XmlAttributeOverrides instance to the second parameter of the XmlSerializer constructor. It is created like this:
我可以通过将XmlAttributeOverrides实例传递给XmlSerializer构造函数的第二个参数来覆盖根节点。它是这样创建的:
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attributes = new XmlAttributes { XmlRoot = new XmlRootAttribute("collection") };
overrides.Add( typeof(List<string>), attributes );
This will change "ArrayOfString" to "collection". I still have not figured out how to control the name of the string element.
这会将“ArrayOfString”更改为“collection”。我还没弄明白如何控制字符串元素的名称。
#3
1
To customize List element names using XmlSerializer, you have to wrap the list.
要使用XmlSerializer自定义List元素名称,必须包装列表。
[XmlRoot(Namespace="", ElementName="collection")]
public class ConfigWrapper
{
[XmlElement("item")]
public List<string> Items{ get; set;}
}
Usage:
用法:
var itemsList = new List<string>{"item1", "item2", "item3"};
var cfgIn = new ConfigWrapper{ Items = itemsList };
var xs = new XmlSerializer(typeof(ConfigWrapper));
string fileContent = null;
using (var sw = new StringWriter())
{
xs.Serialize(sw, cfgIn);
fileContent = sw.ToString();
Console.WriteLine (fileContent);
}
ConfigWrapper cfgOut = null;
using (var sr = new StringReader(fileContent))
{
cfgOut = xs.Deserialize(sr) as ConfigWrapper;
// cfgOut.Dump(); //view in LinqPad
if(cfgOut != null)
// yields 'item2'
Console.WriteLine (cfgOut.Items[1]);
}
Output:
输出:
// fileContent:
<?xml version="1.0" encoding="utf-16"?>
<collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<item>item1</item>
<item>item2</item>
<item>item3</item>
</collection>
If you don't want to wrap the list, the DataContractSerializer will allow you to custom name the elements if you subclass it:
如果您不想包装列表,DataContractSerializer将允许您在子类化时自定义元素的名称:
[CollectionDataContract(Name = "collection", ItemName = "item", Namespace = "")]
public class ConfigWrapper : List<string>
{
public ConfigWrapper() : base() { }
public ConfigWrapper(IEnumerable<string> items) : base(items) { }
public ConfigWrapper(int capacity) : base(capacity) { }
}
Usage And Output:
用法和输出:
var cfgIn = new ConfigWrapper{ "item1", "item2", "item3" };
var ds = new DataContractSerializer(typeof(ConfigWrapper));
string fileContent = null;
using (var ms = new MemoryStream())
{
ds.WriteObject(ms, cfgIn);
fileContent = Encoding.UTF8.GetString(ms.ToArray());
Console.WriteLine (fileContent);
}
// yields: <collection xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><item>item1</item><item>item2</item><item>item3</item></collection>
ConfigWrapper cfgOut = null;
using (var sr = new StringReader(fileContent))
{
using(var xr = XmlReader.Create(sr))
{
cfgOut = ds.ReadObject(xr) as ConfigWrapper;
// cfgOut.Dump(); //view in LinqPad
if(cfgOut != null)
// yields 'item2'
Console.WriteLine (cfgOut[1]);
}
}
#1
3
Are you married to the idea of using a serializer? If not, you can try Linq-to-XML. (.NET 3.5, C# 3 [and higher])
你嫁给了使用序列化器的想法吗?如果没有,您可以尝试Linq-to-XML。 (.NET 3.5,C#3 [及更高版本])
Based on your provided XML file format, this is the simple code.
根据您提供的XML文件格式,这是简单的代码。
// add 'using System.Xml.Linq' to your code file
string file = @"C:\Temp\myconfig.xml";
XDocument document = XDocument.Load(file);
List<string> list = (from item in document.Root.Elements("item")
select item.Value)
.ToList();
#2
1
Ok, interestingly enough I may have found half the answer by serializing an existing List.
好的,有趣的是,通过序列化现有的List,我可能找到了一半的答案。
The result I got is as follows...
我得到的结果如下......
This following code:
以下代码:
List<string> things = new List<string> { "thing1", "thing2" };
XmlSerializer serializer = new XmlSerializer(typeof(List<string>), overrides);
using (TextWriter textWriter = new StreamWriter("things.xml"))
{
serializer.Serialize(textWriter, things);
}
Outputs a result of:
输出结果:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>thing1</string>
<string>thing2</string>
</ArrayOfString>
I can override the root node by passing an XmlAttributeOverrides instance to the second parameter of the XmlSerializer constructor. It is created like this:
我可以通过将XmlAttributeOverrides实例传递给XmlSerializer构造函数的第二个参数来覆盖根节点。它是这样创建的:
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attributes = new XmlAttributes { XmlRoot = new XmlRootAttribute("collection") };
overrides.Add( typeof(List<string>), attributes );
This will change "ArrayOfString" to "collection". I still have not figured out how to control the name of the string element.
这会将“ArrayOfString”更改为“collection”。我还没弄明白如何控制字符串元素的名称。
#3
1
To customize List element names using XmlSerializer, you have to wrap the list.
要使用XmlSerializer自定义List元素名称,必须包装列表。
[XmlRoot(Namespace="", ElementName="collection")]
public class ConfigWrapper
{
[XmlElement("item")]
public List<string> Items{ get; set;}
}
Usage:
用法:
var itemsList = new List<string>{"item1", "item2", "item3"};
var cfgIn = new ConfigWrapper{ Items = itemsList };
var xs = new XmlSerializer(typeof(ConfigWrapper));
string fileContent = null;
using (var sw = new StringWriter())
{
xs.Serialize(sw, cfgIn);
fileContent = sw.ToString();
Console.WriteLine (fileContent);
}
ConfigWrapper cfgOut = null;
using (var sr = new StringReader(fileContent))
{
cfgOut = xs.Deserialize(sr) as ConfigWrapper;
// cfgOut.Dump(); //view in LinqPad
if(cfgOut != null)
// yields 'item2'
Console.WriteLine (cfgOut.Items[1]);
}
Output:
输出:
// fileContent:
<?xml version="1.0" encoding="utf-16"?>
<collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<item>item1</item>
<item>item2</item>
<item>item3</item>
</collection>
If you don't want to wrap the list, the DataContractSerializer will allow you to custom name the elements if you subclass it:
如果您不想包装列表,DataContractSerializer将允许您在子类化时自定义元素的名称:
[CollectionDataContract(Name = "collection", ItemName = "item", Namespace = "")]
public class ConfigWrapper : List<string>
{
public ConfigWrapper() : base() { }
public ConfigWrapper(IEnumerable<string> items) : base(items) { }
public ConfigWrapper(int capacity) : base(capacity) { }
}
Usage And Output:
用法和输出:
var cfgIn = new ConfigWrapper{ "item1", "item2", "item3" };
var ds = new DataContractSerializer(typeof(ConfigWrapper));
string fileContent = null;
using (var ms = new MemoryStream())
{
ds.WriteObject(ms, cfgIn);
fileContent = Encoding.UTF8.GetString(ms.ToArray());
Console.WriteLine (fileContent);
}
// yields: <collection xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><item>item1</item><item>item2</item><item>item3</item></collection>
ConfigWrapper cfgOut = null;
using (var sr = new StringReader(fileContent))
{
using(var xr = XmlReader.Create(sr))
{
cfgOut = ds.ReadObject(xr) as ConfigWrapper;
// cfgOut.Dump(); //view in LinqPad
if(cfgOut != null)
// yields 'item2'
Console.WriteLine (cfgOut[1]);
}
}