Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I conditionally write out XML in a less verbose way?

I want to write a xml file with C#. It is a basic file like that :

<EmployeeConfiguration>
  <Bosses>
    <Boss name="BOB">
      <Employees>
        <Employee Id="#0001" />
        <Employee Id="#0002" />
      </Employees>
    <Boss>
  </Bosses>
</EmployeeConfiguration>

and I don't want have an Employees node if there is not Employee node...

I want use XElement but I can't because of that... So I used XmlWriter. it works fine but I find it's very verbose to write XML :

EmployeeConfiguration config = EmployeeConfiguration.GetConfiguration();

using (XmlWriter writer = XmlWriter.Create(_fileUri, settings))
{
  writer.WriteStartDocument();

  // <EmployeeConfiguration>
  writer.WriteStartElement("EmployeeConfiguration");

  if (config.Bosses.Count > 0)
  {
    // <Bosses>
    writer.WriteStartElement("Bosses");

    foreach (Boss b in config.Bosses)
    {
      // Boss
      writer.WriteStartElement("Boss");
      writer.WriteStartAttribute("name");
      writer.WriteString(b.Name);
      writer.WriteEndAttribute();

      if (b.Employees.Count > 0)
      {
        writer.WriteStartElement("Employees");

        foreach (Employee emp in b.Employees)
        {
            writer.WriteStartElement(Employee);
            writer.WriteStartAttribute(Id);
            writer.WriteString(emp.Id);
            writer.WriteEndAttribute();
            writer.WriteEndElement();
        }
      }
    }
  }
}

Is there another (and fastest) way to write this kind of xml file ?

like image 325
Florian Avatar asked Feb 21 '23 00:02

Florian


2 Answers

If you mean "fastest" as the fastest way to write some code to do it (and the simplest), then creating a custom class and serializing it using the XmlSerializer is the way to go...

Create your classes as follows:

[XmlRoot("EmployeeConfiguration")]
public class EmployeeConfiguration
{
    [XmlArray("Bosses")]
    [XmlArrayItem("Boss")]
    public List<Boss> Bosses { get; set; }
}

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

    [XmlArray("Employees")]
    [XmlArrayItem("Employee")]
    public List<Employee> Employees { get; set; }
}

public class Employee
{
    [XmlAttribute]
    public string Id { get; set; }
}

and then you can serialize these out with this:

// create a serializer for the root type above
var serializer = new XmlSerializer(typeof (EmployeeConfiguration));

// by default, the serializer will write out the "xsi" and "xsd" namespaces to any output.
// you don't want these, so this will inhibit it.
var namespaces = new XmlSerializerNamespaces(new [] { new XmlQualifiedName("", "") });

// serialize to stream or writer
serializer.Serialize(outputStreamOrWriter, config, namespaces);

As you can see - using various attributes on the classes instruct the serializer in how it should serialize the class. Some of the ones I've included above are actually the default settings and don't explicitly need to be stated - but I've included them to show you how it is done.

like image 84
Rob Levine Avatar answered Feb 23 '23 13:02

Rob Levine


You might want to look at XML serialization, using the XmlElement, XmlAttribute (and so on) attributes. I think this gives you the level of control you want, and a very quick, safe and easy to maintain call to do the XML conversion.

like image 24
David M Avatar answered Feb 23 '23 12:02

David M