将XML文档转换为对象

时间:2015-07-16 16:32:44

标签: c# xml converter xmldocument

我已经看过几篇关于同一类问题的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#对象?

3 个答案:

答案 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; }
    }


}
​