representing an XML config file with an IXmlSerializable class

Posted by Sarah Vessels on Stack Overflow See other posts from Stack Overflow or by Sarah Vessels
Published on 2010-06-15T14:01:51Z Indexed on 2010/06/15 14:22 UTC
Read the original article Hit count: 223

I'm writing in C# and trying to represent an XML config file through an IXmlSerializable class. I'm unsure how to represent the nested elements in my config file, though, such as logLevel:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <logging>
    <logLevel>Error</logLevel>
  </logging>
  <credentials>
    <user>user123</user>
    <host>localhost</host>
    <password>pass123</password>
  </credentials>
  <credentials>
    <user>user456</user>
    <host>my.other.domain.com</host>
    <password>pass456</password>
  </credentials>
</configuration>

There is an enum called LogLevel that represents all the possible values for the logLevel tag. The tags within credentials should all come out as strings. In my class, called DLLConfigFile, I had the following:

[XmlElement(ElementName="logLevel", DataType="LogLevel")]
public LogLevel LogLevel;

However, this isn't going to work because <logLevel> isn't within the root node of the XML file, it's one node deeper in <logging>. How do I go about doing this?

As for the <credentials> nodes, my guess is I will need a second class, say CredentialsSection, and have a property such as the following:

[XmlElement(ElementName="credentials", DataType="CredentialsSection")]
public CredentialsSection[] AllCredentials;

Edit: okay, I tried Robert Love's suggestion and created a LoggingSection class. However, my test fails:

var xs = new XmlSerializer(typeof(DLLConfigFile));

using (var stream = new FileStream(_configPath, FileMode.Open,
    FileAccess.Read, FileShare.Read))
{
    using (var streamReader = new StreamReader(stream))
    {
        XmlReader reader = new XmlTextReader(streamReader);
        var file = (DLLConfigFile)xs.Deserialize(reader);
        Assert.IsNotNull(file);
        LoggingSection logging = file.Logging;
        Assert.IsNotNull(logging); // fails here
        LogLevel logLevel = logging.LogLevel;
        Assert.IsNotNull(logLevel);
        Assert.AreEqual(EXPECTED_LOG_LEVEL, logLevel);
    }
}

The config file I'm testing with definitely has <logging>. Here's what the classes look like:

[Serializable]
[XmlRoot("logging")]
public class LoggingSection : IXmlSerializable
{
    public XmlSchema GetSchema()
    {
        return null;
    }

    [XmlElement(ElementName="logLevel", DataType="LogLevel")]
    public LogLevel LogLevel;

    public void ReadXml(XmlReader reader)
    {
        LogLevel = (LogLevel)Enum.Parse(typeof(LogLevel),
            reader.ReadString());
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteString(Enum.GetName(typeof(LogLevel), LogLevel));
    }
}

[Serializable]
[XmlRoot("configuration")]
public class DLLConfigFile : IXmlSerializable
{
    [XmlElement(ElementName="logging", DataType="LoggingSection")]
    public LoggingSection Logging;
}

© Stack Overflow or respective owner

Related posts about c#

Related posts about configuration