Xml in Dart

Here’s the translation of the XML example from Go to Dart, formatted in Markdown suitable for Hugo:

Our first example demonstrates how to work with XML in Dart using the xml package. Here’s the full source code:

import 'package:xml/xml.dart';

// Plant will be mapped to XML. Field annotations contain directives for the
// encoder and decoder. Here we use some special features of the XML package:
// the `XmlElement` annotation dictates the name of the XML element representing
// this class; `XmlAttribute` means that the field is an XML attribute rather
// than a nested element.
class Plant {
  @XmlElement(name: 'plant')
  final String name;

  @XmlAttribute(name: 'id')
  final int id;

  @XmlElement(name: 'origin')
  final List<String> origin;

  Plant(this.id, this.name, this.origin);

  @override
  String toString() {
    return 'Plant id=$id, name=$name, origin=$origin';
  }
}

void main() {
  var coffee = Plant(27, 'Coffee', ['Ethiopia', 'Brazil']);

  // Create an XML document representing our plant
  var document = XmlDocument([
    XmlElement(XmlName('plant'), [
      XmlAttribute(XmlName('id'), coffee.id.toString()),
      XmlElement(XmlName('name'), [], [XmlText(coffee.name)]),
      ...coffee.origin.map((o) => XmlElement(XmlName('origin'), [], [XmlText(o)]))
    ])
  ]);

  // Emit XML representing our plant; using a StringBuffer for output
  var buffer = StringBuffer();
  document.writePrettyTo(buffer, indent: '  ');
  print(buffer.toString());

  // To add a generic XML header to the output, prepend it explicitly
  print('<?xml version="1.0" encoding="UTF-8"?>\n${buffer.toString()}');

  // Use XmlDocument.parse to parse a string of XML into a document structure.
  // If the XML is malformed or cannot be mapped onto Plant, a descriptive error
  // will be thrown.
  var parsedDocument = XmlDocument.parse(buffer.toString());
  var parsedPlant = Plant(
    int.parse(parsedDocument.rootElement.getAttribute('id')!),
    parsedDocument.findAllElements('name').first.text,
    parsedDocument.findAllElements('origin').map((e) => e.text).toList(),
  );
  print(parsedPlant);

  var tomato = Plant(81, 'Tomato', ['Mexico', 'California']);

  // The nesting structure demonstrates how to create nested XML elements
  var nesting = XmlDocument([
    XmlElement(XmlName('nesting'), [
      XmlElement(XmlName('parent'), [
        XmlElement(XmlName('child'), [
          XmlElement(XmlName('plant'), [
            XmlAttribute(XmlName('id'), coffee.id.toString()),
            XmlElement(XmlName('name'), [], [XmlText(coffee.name)]),
            ...coffee.origin.map((o) => XmlElement(XmlName('origin'), [], [XmlText(o)]))
          ]),
          XmlElement(XmlName('plant'), [
            XmlAttribute(XmlName('id'), tomato.id.toString()),
            XmlElement(XmlName('name'), [], [XmlText(tomato.name)]),
            ...tomato.origin.map((o) => XmlElement(XmlName('origin'), [], [XmlText(o)]))
          ])
        ])
      ])
    ])
  ]);

  buffer.clear();
  nesting.writePrettyTo(buffer, indent: '  ');
  print(buffer.toString());
}

To run this program, you’ll need to add the xml package to your pubspec.yaml file:

dependencies:
  xml: ^6.1.0

Then, you can run the program using:

$ dart run xml_example.dart

This will output:

<plant id="27">
  <name>Coffee</name>
  <origin>Ethiopia</origin>
  <origin>Brazil</origin>
</plant>
<?xml version="1.0" encoding="UTF-8"?>
<plant id="27">
  <name>Coffee</name>
  <origin>Ethiopia</origin>
  <origin>Brazil</origin>
</plant>
Plant id=27, name=Coffee, origin=[Ethiopia, Brazil]
<nesting>
  <parent>
    <child>
      <plant id="27">
        <name>Coffee</name>
        <origin>Ethiopia</origin>
        <origin>Brazil</origin>
      </plant>
      <plant id="81">
        <name>Tomato</name>
        <origin>Mexico</origin>
        <origin>California</origin>
      </plant>
    </child>
  </parent>
</nesting>

This example demonstrates how to create XML structures, serialize objects to XML, parse XML back into objects, and work with nested XML elements in Dart.