Вопрос

In C# I need to use XmlNode to get values from these attributes as follows:

Root element (ServerConfig):

  • type

  • version

  • createDate

Child nodes (Items):

  • name

  • source

  • destination

XML:

<?xml version="1.0" encoding="utf-8"?>
<ServerConfig type="ProjectName" version ="1.1.1.2" createDate ="2013-07-30T15:07:19.3859287+02:00" >
<items>
    <item  name="fs" type="directory" source="C:\temp\source" destination="C:\temp\target" action="Create" />
    <item  name="testdoc.txt" type="file" source="C:\temp\source" destination="C:\temp\target" action="Update" />
</items>
</ServerConfig>

C#:

        XmlTextReader reader = new XmlTextReader(fileManager.ConfigFile);
        XmlDocument doc = new XmlDocument();
        XmlNode node = doc.ReadNode(reader);

        // failed to get values here
        var Version = node.Attributes["version"].Value;
        var Type = node.Attributes["type"].Value;
        var Date = node.Attributes["createDate"].Value;

        //how to get values from items/item attributes here?

Your example code much appreciated thanks :)

Это было полезно?

Решение

You can use LINQ to XML (which is preferable in latest .Net versions)

var xdoc = XDocument.Load(fileManager.ConfigFile);
var serverConfig = xdoc.Root;
string version = (string)serverConfig.Attribute("version");
DateTime date = (DateTime)serverConfig.Attribute("createDate");
string type = (string)serverConfig.Attribute("type");

var items = from item in serverConfig.Element("items").Elements()
            select new {
                Name = (string)item.Attribute("name"),
                Type = (string)item.Attribute("type"),
                Source = (string)item.Attribute("source"),
                Destination = (string)item.Attribute("destination")
            };

Take a look - few lines of code and file parsed into strongly-typed variables. Even date is a DateTime object instead of string. And items are collection of anonymous objects with properties corresponding to xml attributes.

Другие советы

You could use the XmlSerializer:

Classes:

public class ServerConfig
{
    public ServerConfig()
    {
        Items = new List<Item>();
    }

    [XmlAttribute("type")]
    public string Type { get; set; }

    [XmlAttribute("version")]
    public string Version { get; set; }

    [XmlAttribute("createDate")]
    public DateTime CreateDate { get; set; }

    [XmlArray("items")]
    [XmlArrayItem("item")]
    public List<Item> Items { get; set; }
}

public class Item
{
    [XmlAttribute("name")]
    public string Name { get; set; }

    [XmlAttribute("type")]
    public string Type { get; set; }

    [XmlAttribute("source")]
    public string Source { get; set; }

    [XmlAttribute("destination")]
    public string Destination { get; set; }

    [XmlAttribute("action")]
    public string Action { get; set; }
}

Example:

var data = @"<?xml version=""1.0"" encoding=""utf-8""?>
    <ServerConfig type=""ProjectName"" version =""1.1.1.2"" createDate =""2013-07-30T15:07:19.3859287+02:00"" >
    <items>
        <item  name=""fs"" type=""directory"" source=""C:\temp\source"" destination=""C:\temp\target"" action=""Create"" />
        <item  name=""testdoc.txt"" type=""file"" source=""C:\temp\source"" destination=""C:\temp\target"" action=""Update"" />
    </items>
    </ServerConfig>";

var serializer = new XmlSerializer(typeof(ServerConfig));

ServerConfig config;

using(var stream = new StringReader(data))
using(var reader = XmlReader.Create(stream))
{
    config = (ServerConfig)serializer.Deserialize(reader);
}

You should use XPath to get items and loop on the result ;)

Something like this:

foreach (XmlNode item in doc.DocumentElement.SelectNodes("items/item"))
{
  var Name = item.Attributes["name"].Value;
  var Source= item.Attributes["source"].Value;
  var Destination = item.Attributes["destination"].Value;
} 

To get your root element you can use doc.DocumentElement ;)

Load your document:

XmlDocument doc = new XmlDocument();
doc.Load(fileManager.ConfigFile);

Then you will be able to select anything using XPath:

doc.SelectSingleNode(XPath); 
doc.SelectNodes(XPath);

Instead of using XmlNode, I'd use XmlElement, as it has a nice method called GetAttribute(string attributeName) that's a little easier to work with than the Attributes indexer property on XmlNode. And, since XmlElement derives from XmlNode, you get added functionality while retaining the functionality of the base XmlNode class..

var items = doc.DocumentElement.SelectNodes("items/item").Cast<XmlElement>().ToList();

// You can iterate over the list, here's how you'd get your attributes:
var Name = items[0].GetAttribute("name"); // Returns null if attribute doesn't exist, doesn't throw exception
var Source = items[0].GetAttribute("source");
var Destination = items[0].GetAttrubite("destination");

HTH.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top