Xml in Chapel

Here’s the translation of the XML example from Go to Chapel:

Our example demonstrates XML handling in Chapel. We’ll use the XML module to work with XML data.

use XML;
use IO;

// Plant will be mapped to XML. We use a record to represent the structure.
record Plant {
  var id: int;
  var name: string;
  var origin: [1..0] string;

  // Custom string representation of the Plant record
  proc toString() {
    return "Plant id=" + this.id:string + ", name=" + this.name + ", origin=" + this.origin:string;
  }
}

proc main() {
  var coffee = new Plant(27, "Coffee");
  coffee.origin.push_back("Ethiopia");
  coffee.origin.push_back("Brazil");

  // Emit XML representing our plant
  var xmlDoc = new xmlDocument();
  var plantElem = xmlDoc.createElement("plant");
  plantElem.setAttribute("id", coffee.id:string);
  
  var nameElem = xmlDoc.createElement("name");
  nameElem.setNodeValue(coffee.name);
  plantElem.appendChild(nameElem);

  for origin in coffee.origin {
    var originElem = xmlDoc.createElement("origin");
    originElem.setNodeValue(origin);
    plantElem.appendChild(originElem);
  }

  xmlDoc.appendChild(plantElem);
  
  // Print the XML
  writeln(xmlDoc);

  // To add a generic XML header to the output, we can prepend it
  writeln("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
  writeln(xmlDoc);

  // Parse XML string back into a Plant record
  var parsedPlant = new Plant();
  var parsedXml = parseXml(xmlDoc.toString());
  
  if parsedXml.isValid() {
    var plantNode = parsedXml.getFirstChild();
    parsedPlant.id = plantNode.getAttribute("id"):int;
    parsedPlant.name = plantNode.getChildText("name");
    var originNodes = plantNode.getChildren("origin");
    for originNode in originNodes {
      parsedPlant.origin.push_back(originNode.getText());
    }
  }
  
  writeln(parsedPlant.toString());

  // Create another plant
  var tomato = new Plant(81, "Tomato");
  tomato.origin.push_back("Mexico");
  tomato.origin.push_back("California");

  // Create a nested structure
  var nestingDoc = new xmlDocument();
  var nestingElem = nestingDoc.createElement("nesting");
  var parentElem = nestingDoc.createElement("parent");
  var childElem = nestingDoc.createElement("child");

  for plant in [coffee, tomato] {
    var plantElem = nestingDoc.createElement("plant");
    plantElem.setAttribute("id", plant.id:string);
    
    var nameElem = nestingDoc.createElement("name");
    nameElem.setNodeValue(plant.name);
    plantElem.appendChild(nameElem);

    for origin in plant.origin {
      var originElem = nestingDoc.createElement("origin");
      originElem.setNodeValue(origin);
      plantElem.appendChild(originElem);
    }

    childElem.appendChild(plantElem);
  }

  parentElem.appendChild(childElem);
  nestingElem.appendChild(parentElem);
  nestingDoc.appendChild(nestingElem);

  writeln(nestingDoc);
}

This Chapel code demonstrates XML handling, including creating XML structures, parsing XML, and working with nested XML elements. Note that Chapel’s XML support might not be as extensive as Go’s, so some adaptations were made to achieve similar functionality.

To run this program, save it as xml_example.chpl and use the Chapel compiler:

$ chpl xml_example.chpl
$ ./xml_example

The output will show the XML representations of the plant data structures and the nested XML structure.