我已经看过几篇关于同一类问题的SO帖子,但我似乎无法让它发挥作用。
我有这个XML文件(完整的):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="StationsSection" type="AcmeTV_EcFtpClient.StationConfigurationSection, AcmeTV_EcFtpClient"/>
</configSections>
<StationsSection>
<Stations>
<add Comment="My comment goes here"
DestinationFolderPath="C:\TestInstallation"
FtpHostname="ftp://upload.servername.com/"
FtpFolderPath="myFolderPath/"
FtpUsername="myUserName"
FtpPassword="myFtpPassword"
FtpTimeoutInSeconds="20" />
</Stations>
</StationsSection>
<startup>
<supportedRuntime version="v2.0.50727"/>
</startup>
<appSettings>
<add key="NameOfService" value="AcmeECClient"/>
<add key="PollingFrequencyInSeconds" value="60"/>
</appSettings>
</configuration>
以下是StationConfiguration的代码:
public class StationConfiguration
{
readonly Regex OnlyAlphaNumericWithNoSpaces = new Regex("^[a-zA-Z0-9]*$");
public StationConfiguration() { }
public StationConfiguration(string comment, string ftpUsername, string ftpPassword, string destinationFolderPath)
{
Comment = comment;
FtpUsername = ftpUsername;
FtpPassword = ftpPassword;
DestinationFolderPath = destinationFolderPath;
}
public bool IsValidStation()
{
return OnlyAlphaNumericWithNoSpaces.IsMatch(Comment);
}
public bool IsValidUsername()
{
return OnlyAlphaNumericWithNoSpaces.IsMatch(FtpUsername);
}
public bool IsValidPassword()
{
return FtpPassword.Contains(' ') == false;
}
public bool IsValidFolderPath()
{
return Directory.Exists(DestinationFolderPath);
}
private string _comment;
public string Comment
{
get
{
return _comment;
}
set
{
_comment = value.ToUpper();
}
}
public string FtpUsername { get; set; }
public string FtpPassword { get; set; }
public string DestinationFolderPath { get; set; }
}
这是我尝试解析的C#代码:
const string hardCodedConfigFilePath = @"C:\Program Files (x86)\MyApp.exe.config";
string xmlDocumentText = File.ReadAllText(hardCodedConfigFilePath);
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlDocumentText);
XmlNodeReader reader = new XmlNodeReader(doc.DocumentElement["StationsSection"]);
string firstStationConfiguration = doc.DocumentElement["StationsSection"].ChildNodes[0].InnerXml; //here's the chunk that contains my data
XmlSerializer ser = new XmlSerializer(typeof(StationConfiguration));
object obj = ser.Deserialize(reader);
名为firstStationConfiguration
的字符串包含:
<add Comment="My comment goes here"
DestinationFolderPath="C:\TestInstallation"
FtpHostname="ftp://upload.servername.com/"
FtpFolderPath="myFolderPath/"
FtpUsername="myUsername"
FtpPassword="abcdefg" FtpTimeoutInSeconds="20" />
当执行最后一个C#行时,抛出此内容:
类型'System.InvalidOperationException'的未处理异常 发生在System.Xml.dll中附加信息:出错 在XML文档中。
请...如何将Stations
节点(可能包含多个节点)转换为C#对象?
答案 0 :(得分:2)
您尝试仅反序列化Xml文档的一部分,这就是为什么它被视为无效的Xml文档。要使其工作,您需要使用根元素创建一个新的Xml文档并添加一个Xml声明。这需要额外的课程。需要使用XMLAttribute属性修饰StationConfiguration类中的属性。(在示例中,test.xml文件与配置文件相同)
更快的方法可能是直接从节点获取属性并创建类的实例(solution2)
最后,您可以使用Linq来完成工作(解决方案3)
public class Stations
{
[XmlElement(ElementName = "add", Namespace = "")]
public StationConfiguration StationConfiguration { get; set; }
}
[XmlType(AnonymousType = true, Namespace = "")]
public class StationConfiguration
{
readonly Regex OnlyAlphaNumericWithNoSpaces = new Regex("^[a-zA-Z0-9]*$");
public StationConfiguration() { }
public StationConfiguration(string comment, string ftpUsername, string ftpPassword, string destinationFolderPath)
{
Comment = comment;
FtpUsername = ftpUsername;
FtpPassword = ftpPassword;
DestinationFolderPath = destinationFolderPath;
}
public bool IsValidStation()
{
return OnlyAlphaNumericWithNoSpaces.IsMatch(Comment);
}
public bool IsValidUsername()
{
return OnlyAlphaNumericWithNoSpaces.IsMatch(FtpUsername);
}
public bool IsValidPassword()
{
return FtpPassword.Contains(' ') == false;
}
public bool IsValidFolderPath()
{
return Directory.Exists(DestinationFolderPath);
}
private string _comment;
[XmlAttribute]
public string Comment
{
get
{
return _comment;
}
set
{
_comment = value.ToUpper();
}
}
[XmlAttribute]
public string FtpUsername { get; set; }
[XmlAttribute]
public string FtpPassword { get; set; }
[XmlAttribute]
public string DestinationFolderPath { get; set; }
}
class Program
{
private static void Main(string[] args)
{
const string hardCodedConfigFilePath = @"test.xml";
sol1(hardCodedConfigFilePath);
sol2(hardCodedConfigFilePath);
sol3(hardCodedConfigFilePath);
}
public static void sol1(string hardCodedConfigFilePath)
{
string xmlDocumentText = File.ReadAllText(hardCodedConfigFilePath);
var doc = new XmlDocument();
doc.LoadXml(xmlDocumentText);
var docElem = new XmlDocument();
docElem.CreateXmlDeclaration("1.0", "utf-8", "yes");
var node = doc.DocumentElement["StationsSection"];
//Create a document fragment.
var docFrag = docElem.CreateDocumentFragment();
//Set the contents of the document fragment.
docFrag.InnerXml = node.InnerXml;
//Add the document fragment to the
// document.
docElem.AppendChild(docFrag);
var reader = new XmlNodeReader(docElem);
var ser = new XmlSerializer(typeof(Stations));
object obj = ser.Deserialize(reader);
}
public static void sol2(string hardCodedConfigFilePath)
{
string xmlDocumentText = File.ReadAllText(hardCodedConfigFilePath);
var doc = new XmlDocument();
doc.LoadXml(xmlDocumentText);
var attr = doc.DocumentElement["StationsSection"].ChildNodes[0].ChildNodes[0].Attributes;
// Check that attributes exist ...
var stationConfiguration = new StationConfiguration(attr["Comment"].Value
, attr["FtpUsername"].Value
, attr["FtpPassword"].Value
, attr["DestinationFolderPath"].Value);
}
public static void sol3(string hardCodedConfigFilePath)
{
var xdoc = XElement.Load(hardCodedConfigFilePath);
var config = xdoc.Descendants("Stations").Elements("add").FirstOrDefault();
// Check that attributes exist ...
var stationConfiguration = new StationConfiguration(config.Attribute("Comment").Value
, config.Attribute("FtpUsername").Value
, config.Attribute("FtpPassword").Value
, config.Attribute("DestinationFolderPath").Value);
}
答案 1 :(得分:1)
在有限的时间内无法确定这一点。但也许你可以继续努力;似乎该节点被称为站点,因此它正在寻找一个Stations类而不是StationConfiguration。但我还没有将属性作为XML属性部分获取。
Private Async Function tempWorker1() As Task
For i = 1 To 5000
If i Mod 100 = 0 Then
Console.WriteLine("From 1:{0}", i)
End If
Next
End Function
Private Async Function tempWorker2() As Task
For i = 1 To 5000
If i Mod 100 = 0 Then
Console.WriteLine("From 2:{0}", i)
End If
Next
End Function
答案 2 :(得分:1)
试试这个
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
Configuration config = new Configuration() {
configSections = new ConfigSections() {
section = new List<Section>() {
new Section() { name = "StationsSection", type="AcmeTV_EcFtpClient.StationConfigurationSection, AcmeTV_EcFtpClient"}
}
},
stationsSection = new StationsSection() {
station = new List<Station>() {
new Station() {
add = new StationAdd() {
comment ="My comment goes here",
destinationFolderPath = "C:\\TestInstallation",
ftpHostname = "ftp://upload.servername.com/",
ftpFolderPath = "myFolderPath/",
ftpUsername = "myUserName",
ftpPassword = "myFtpPassword",
ftpTimeoutInSeconds = 20
}
}
}
},
startup = new Startup() {
supportedRuntime = new SupportedRuntime() {
version = "v2.0.50727"
}
},
appSettings = new AppSettings() {
appSettingAdd = new List<AppSettingAdd>() {
new AppSettingAdd() { key= "NameOfService", value="AcmeECClient"},
new AppSettingAdd() { key="PollingFrequencyInSeconds", value="60"}
}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(Configuration));
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, config);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer xs = new XmlSerializer(typeof(Configuration));
XmlTextReader reader = new XmlTextReader(FILENAME);
Configuration newConfig = (Configuration)xs.Deserialize(reader);
}
}
[XmlRoot("configuration")]
public class Configuration
{
[XmlElement("configSections")]
public ConfigSections configSections { get; set; }
[XmlElement("StationsSection")]
public StationsSection stationsSection { get; set; }
[XmlElement("startup")]
public Startup startup { get; set; }
[XmlElement("appSettings")]
public AppSettings appSettings { get; set; }
}
[XmlRoot("configSections")]
public class ConfigSections
{
[XmlElement("section")]
public List<Section> section { get; set; }
}
[XmlRoot("section")]
public class Section
{
[XmlAttribute("name")]
public string name { get; set;}
[XmlAttribute("type")]
public string type { get; set; }
}
[XmlRoot("StationsSection")]
public class StationsSection
{
[XmlElement("Stations")]
public List<Station> station { get; set; }
}
[XmlRoot("Stations")]
public class Station
{
[XmlElement("add")]
public StationAdd add { get; set; }
}
[XmlRoot("add")]
public class StationAdd
{
[XmlAttribute("Comment")]
public string comment { get; set; }
[XmlAttribute("DestinationFolderPath")]
public string destinationFolderPath { get; set; }
[XmlAttribute("FtpHostname")]
public string ftpHostname { get; set; }
[XmlAttribute("FtpFolderPath")]
public string ftpFolderPath { get; set; }
[XmlAttribute("FtpUsername")]
public string ftpUsername { get; set; }
[XmlAttribute("FtpPassword")]
public string ftpPassword { get; set; }
[XmlAttribute("FtpTimeoutInSeconds")]
public int ftpTimeoutInSeconds { get; set; }
}
[XmlRoot("startup")]
public class Startup
{
[XmlElement("supportedRuntime")]
public SupportedRuntime supportedRuntime { get; set; }
}
[XmlRoot("supportedRuntime")]
public class SupportedRuntime
{
[XmlAttribute("version")]
public string version { get; set; }
}
[XmlRoot("appSettings")]
public class AppSettings
{
[XmlElement("add")]
public List<AppSettingAdd> appSettingAdd { get; set;}
}
[XmlRoot("add")]
public class AppSettingAdd
{
[XmlAttribute("key")]
public string key { get; set; }
[XmlAttribute("value")]
public string value { get; set; }
}
}