0

I'm looking for a good clean way of writing XML to a configuration file and being able to read it back into the Application.

I have an Array of properties that each contain a list of fields.

For example a list of Camera Properties.

Each property has Name, Value, Category, Type, Description.

I would like my XML Config to look like this

<Camera_Properties>
    <Property Name="Height" Value="40" Category="Dimensions" Type="Int" Description="The height of the box">
    <Property Name="Width" Value="40" Category="Dimensions" Type="Int" Description="The width of the box">
</Camera_Properties>

Firstly is this possible, or practical?

I Can't seem to find a way of writing this and more impotently being able to parse it in such a way that it can be pulled apart so I could read the Config file and as each element is found call code like this

SetProperty(xmlelement.name, xmlelement.Value, xmlelement.Type);

So far i have managed to get this output

<Camera_Properties>
    <Property>
        <Name> Height</Name>
        <Value> 100 </Value>
        <Category> Dimensions </Category>
        <Type> Int </Type>
        <Description> Height of the box </Description>
    </Property>
 </Camera_Properties>

But this is not practical for how i need to use the configuration file.

I have used System.Xml.XmlDocument to get this far. If there is a better alternative i would appreciate suggestions.

But as there are hundreds of properties this is too messy and hard to read.

If anyone can help or knows where there may be a relevant example i could use as a guide it would greatly help.

Thanks

EDIT

I would like to loop through and generate an XML file with these properties from an array. The idea is that this file can be used to load in proprieties and set properties as the change each time the hardware is powered off.

public void CreateXML()
{
   // Setup document and header tags

    foreach(Property prop in propertyArray)
    {
       create single element here with prop.Name, Prop.Age etc as attributes
    }

    SaveXml(Filename);
}

The SDK i use for the hardware has an Array of parameters so i would prefer to generate the file from this instead of a dataset.

Colm Clarke
  • 480
  • 1
  • 7
  • 23

3 Answers3

1

It looks like you're adding nodes instead of one node with attributes on it.

Try adding one node named Properties, then set the attributes on that node to the key/values you want.

Here's an example: Microsoft XML Attributes Documentation

Tim
  • 4,051
  • 10
  • 36
  • 60
1

I've been doing a lot of work using Serialization at my job.

XmlSerializer

You can create some classes to store the information. Write to the objects properties and then serialize it using the following:

XmlSerializer xsSubmit = new XmlSerializer(typeof(Claim));

            var subReq = Claim;
            using (StringWriter sww = new Utf8StringWriter())
            {
                XmlWriterSettings xmlWriterSettings = new XmlWriterSettings
                {
                    Indent = true,
                    OmitXmlDeclaration = false,
                    Encoding = Encoding.Unicode
                };

                using (XmlWriter writer = XmlWriter.Create(sww, xmlWriterSettings))
                {
                    xsSubmit.Serialize(writer, subReq);
                    var xml = sww.ToString();
                    PrintOutput(xml);


                    File.WriteAllText("out.xml", text);

                    Console.WriteLine(xml);
                }
            }

This is my working example. Note on the first line I have typeof(Claim) Claim is a parent object of mine which contains my child objects.

Think of each object nested in another object as each nesting of the XML:

 public class Claim
    {
        public Accident Accident { get; set; }

        public Driver Driver { get; set; }

        public Insurer Insurer { get; set; }

        public Owner Owner { get; set; }

        public Policy Policy { get; set; }

        public Solicitor Solicitor { get; set; }

        public Source Source { get; set; }

}

You can see my question last week regarding something similar here: XMLSerialization Nesting

DataSet Serialization

DataSet ds = new Dataset();
DataTable dt = new DataTable();
ds.Tables.Add(dt);
System.IO.StringWriter writer = new System.IO.StringWriter();
Case.WriteXml(writer, XmlWriteMode.WriteSchema);

See here if you're adamant about using attributes: Serialize Property as Xml Attribute in Element

Edit: You can read them back in using both methods. You can read the data back into the objects with XMLSerializer or you can deserialize a dataset.

Community
  • 1
  • 1
ZeroBased_IX
  • 2,667
  • 2
  • 25
  • 46
1

You can use XmlSerializer to automatically serialize and deserialize your property collection. If you do, you must mark your properties with the [XmlAttribute] attribute to inform the serializer that they are to be serialized as XML attributes.

For instance, given the classes:

public class Property
{
    [XmlAttribute]
    public string Name { get; set; }
    [XmlAttribute]
    public string Value { get; set; }
    [XmlAttribute]
    public string Category { get; set; }
    [XmlAttribute]
    public string Type { get; set; }
    [XmlAttribute]
    public string Description { get; set; }
}

[XmlRoot("Camera_Properties")]
public class CameraPropertyList
{
    [XmlElement("Property")]
    public List<Property> Properties { get; set; }
}

You can test reading and writing them as follows:

        string xml = @"<Camera_Properties>
            <Property Name=""Height"" Value=""40"" Category=""Dimensions"" Type=""Int"" Description=""The height of the box""/>
            <Property Name=""Width"" Value=""40"" Category=""Dimensions"" Type=""Int"" Description=""The width of the box""/>
        </Camera_Properties>
        ";
        CameraPropertyList properties;
        using (StringReader reader = new StringReader(xml))
        {
            properties = (CameraPropertyList)(new XmlSerializer(typeof(CameraPropertyList))).Deserialize(reader);
        }

        string xmlOut;
        using (var textWriter = new StringWriter())
        {
            var settings = new XmlWriterSettings() { Indent = true, IndentChars = "    " }; // For cosmetic purposes.
            using (var xmlWriter = XmlWriter.Create(textWriter, settings))
                (new XmlSerializer(typeof(CameraPropertyList))).Serialize(xmlWriter, properties);
            xmlOut = textWriter.ToString();
        }

        Debug.WriteLine(xmlOut);

The resulting XML output looks like:

<Camera_Properties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Property Name="Height" Value="40" Category="Dimensions" Type="Int" Description="The height of the box" />
    <Property Name="Width" Value="40" Category="Dimensions" Type="Int" Description="The width of the box" />
</Camera_Properties>

If, for some reason, you want to suppress the standard xsi and xsd namespaces, you can do:

        using (var textWriter = new StringWriter())
        {
            var settings = new XmlWriterSettings() { Indent = true, IndentChars = "    " }; // For cosmetic purposes.
            var ns = new XmlSerializerNamespaces();
            ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
            using (var xmlWriter = XmlWriter.Create(textWriter, settings))
                (new XmlSerializer(typeof(CameraPropertyList))).Serialize(xmlWriter, properties, ns);
            xmlOut = textWriter.ToString();
        }

Alternatively, if you prefer to do it manually by creating an XmlDocument, you can do:

    XmlDocument ToXmlDocument(CameraPropertyList list)
    {
        var doc = new XmlDocument();
        var rootNode = doc.CreateElement("Camera_Properties");
        doc.AppendChild(rootNode);

        foreach (var property in list.Properties)
        {
            var element = doc.CreateElement("Property");
            element.SetAttribute("Name", property.Name);
            element.SetAttribute("Value", property.Value);
            element.SetAttribute("Category", property.Category);
            element.SetAttribute("Type", property.Type);
            element.SetAttribute("Description", property.Description);
            rootNode.AppendChild(element);
        }

        return doc;
    }
dbc
  • 104,963
  • 20
  • 228
  • 340