Xml in Karel

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

Our program demonstrates working with XML in Java using the JAXB (Java Architecture for XML Binding) API. Here’s the full source code:

import jakarta.xml.bind.*;
import jakarta.xml.bind.annotation.*;
import java.util.List;

// Plant will be mapped to XML. Field annotations contain directives for the
// marshaller and unmarshaller. Here we use some special features of JAXB:
// @XmlRootElement specifies the name of the XML element representing this class;
// @XmlAttribute means that the Id field is an XML attribute rather than a nested element.
@XmlRootElement(name = "plant")
class Plant {
    @XmlAttribute
    private int id;
    
    @XmlElement
    private String name;
    
    @XmlElement
    private List<String> origin;

    // Default constructor is needed for JAXB
    public Plant() {}

    public Plant(int id, String name, List<String> origin) {
        this.id = id;
        this.name = name;
        this.origin = origin;
    }

    @Override
    public String toString() {
        return String.format("Plant id=%d, name=%s, origin=%s", id, name, origin);
    }
}

public class XMLExample {
    public static void main(String[] args) throws Exception {
        Plant coffee = new Plant(27, "Coffee", List.of("Ethiopia", "Brazil"));

        // Create a JAXB context and instantiate a marshaller
        JAXBContext context = JAXBContext.newInstance(Plant.class);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        // Marshal the plant object to XML and print to console
        System.out.println("Marshalled XML:");
        marshaller.marshal(coffee, System.out);

        // To add a generic XML header to the output, we need to use a StringWriter
        // and prepend the header manually
        java.io.StringWriter sw = new java.io.StringWriter();
        marshaller.marshal(coffee, sw);
        System.out.println("\nXML with header:");
        System.out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + sw.toString());

        // Use Unmarshaller to parse XML back into a Plant object
        Unmarshaller unmarshaller = context.createUnmarshaller();
        Plant p = (Plant) unmarshaller.unmarshal(new java.io.StringReader(sw.toString()));
        System.out.println("\nUnmarshalled object:");
        System.out.println(p);

        // Create a nested structure
        @XmlRootElement(name = "nesting")
        class Nesting {
            @XmlElement(name = "parent")
            private List<Plant> plants;

            public Nesting(List<Plant> plants) {
                this.plants = plants;
            }

            // Default constructor needed for JAXB
            public Nesting() {}
        }

        Plant tomato = new Plant(81, "Tomato", List.of("Mexico", "California"));
        Nesting nesting = new Nesting(List.of(coffee, tomato));

        // Marshal the nested structure
        context = JAXBContext.newInstance(Nesting.class);
        marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        System.out.println("\nNested structure:");
        marshaller.marshal(nesting, System.out);
    }
}

To run this program, you’ll need to have the Jakarta XML Binding API in your classpath. You can add it to your project using Maven or download the JAR files manually.

When you run this program, it will output:

Marshalled XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<plant id="27">
    <name>Coffee</name>
    <origin>Ethiopia</origin>
    <origin>Brazil</origin>
</plant>

XML with header:
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<plant id="27">
    <name>Coffee</name>
    <origin>Ethiopia</origin>
    <origin>Brazil</origin>
</plant>

Unmarshalled object:
Plant id=27, name=Coffee, origin=[Ethiopia, Brazil]

Nested structure:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nesting>
    <parent>
        <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>
    </parent>
</nesting>

This example demonstrates how to use JAXB for XML marshalling and unmarshalling in Java. It covers creating XML from objects, parsing XML into objects, and working with nested structures.