`Java2XML` is a utility class that lets you turn objects into XML documents and vice versa. It's dead simple to use, yet quite powerful - you can create complex-looking XML from it.

`Java2XML` has advantages over existing Java XML bindings: it is simpler than Castor (for example, there is no need for a schema or DTD); unlike Digester, it can both read and write; unlike Bewitched, it gives clear and helpful error messages when a problem occurs. Since there are very few classes (3), it's relatively easy to track down problems.

### Example: Using Java2XML

Say you have an object `Person` that you want to turn into XML:

    public class Person {
        private int age = 50;
        public int getAge() { return age; }
        public void setAge(int i) { age = i; }

        private String name = "Charles";
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }

        private Collection nicknames = Arrays.asList(new String[]{"Charlie", "Chuck", "Chick"});
        public Collection getNicknames() { return Collections.unmodifiableCollection(nicknames); }
        public void addNickname(String nickname) { nicknames.add(nickname); }
    }

    Person person = new Person();

If you try `Java2XML`, you'll get a very short XML document:

    System.out.println(new Java2XML().write(person, "person"));

    Output:

    <person />

This is because you need to write a little mapping file that maps the Java fields to XML tags. Don't worry - it's easy! Just place the following file (`Person.java2xml`) right beside `Person.class`:

    Person.java2xml:

    <root>
    <element xml-name="age" java-name="age" />
    </root>

Now your XML document will contain a more complete representation:

    System.out.println(new Java2XML().write(person, "person"));
Output:
    <person>
      <age>50</age>
    </person>

As you can see, the `java2xml` file maps an xml tag to a java field. All you have to do is specify the name of each (they can be different).

Why could we just specify "age" for the Java field rather than "`getAge`" and "`setAge`"? `Java2XML` does a case-insensitive search for methods like "`setAge*`" and "`getAge*`" (and "`isAge*`").

Want to add an attribute? It's the same thing again, but you use "attribute" instead of "element":

    Person.java2xml:

    <root>
    <attribute xml-name="name" java-name="name" />
    <element xml-name="age" java-name="age" />
    </root>

    System.out.println(new Java2XML().write(person, "person"));

    Output:

    <person name="Charles">
      <age>50</age>
    </person>

If you nest the attribute inside the element, guess what the output looks like? "name" is nested inside "age"!

    Person.java2xml:
    <root>
    <element xml-name="age" java-name="age">
    <attribute xml-name="name" java-name="name" />
    </element>
    </root>

    System.out.println(new Java2XML().write(person, "person"));

    Output:

    <person>
      <age name="Charles">50</age>
    </person>

What about collections? Look at "nickname" below:

    Person.java2xml:

    <root>
    <element xml-name="age" java-name="age">
    <attribute xml-name="name" java-name="name" />
    </element>
    <element xml-name="nickname" java-name="nickname" />
    </root>

    System.out.println(new Java2XML().write(person, "person"));

    Output:

    <person>
      <age name="Charles">50</age>
      <nickname>Charlie</nickname>
      <nickname>Chuck</nickname>
      <nickname>Chick</nickname>
    </person>

`Java2XML` does a case-insensitive search for a getter like "`getNickname*`" and a setter like "`addNickname*`". Note that it's important to leave off the "s" in "`nickname`" - otherwise `Java2XML` will look for a setter like "`addNicknames*`" and of course there isn't one.

If you want to add some structure to your XML file, you can add tags that aren't mapped to anything. Look at "`aliases`" below and note that it isn't mapped to any java name:

    Person.java2xml:

    <root>
    <element xml-name="age" java-name="age">
    <attribute xml-name="name" java-name="name" />
    </element>
    <element xml-name="aliases">
    <element xml-name="nickname" java-name="nickname" />
    </element>
    </root>

    System.out.println(new Java2XML().write(person, "person"));

    Output:

    <person>
      <age name="Charles">50</age>
      <aliases>
        <nickname>Charlie</nickname>
        <nickname>Chuck</nickname>
        <nickname>Chick</nickname>
      </aliases>
    </person>

Want to turn your XML back into a Java object? There's a class called `XML2Java` that will let you do just that. Easy!

### Notes:

1. The Java class that you want to turn into XML must have a constructor without any parameters. Otherwise how could `XML2Java` know what to use as parameters?
2. You're not confined to storing simple types like Strings and ints in your XML files - you can also store other classes, but of course they too must have a little `.java2xml` file.
3. Your getters and setters can even get/set interfaces and abstract classes! How does XML2Java know which class to instantiate then when you read it back in? `Java2XML` stores the name of the actual class in the XML file.
4. `Java2XML` uses JDOM, which may not be appropriate for large XML files because the whole XML file gets loaded into memory

### Java2XML FAQ

1. My IDE often deletes the directory containing my `.class` files – how can I prevent my `.java2xml` files from being lost?

   Do the same thing as you do with `.gifs` and `.jpegs`: Have your IDE copy your `.java2xml` files from your source directory to your classes directory every time you do a build. All major IDEs, including JBuilder and Eclipse, will let you set up which filename extensions are copied over.

2. What if one of the objects I'd like to turn into XML is from a third party, e.g., a Swing class like `java.awt.Font`? I wouldn't want to modify the Swing jar to add a `.java2xml` file beside `Font.class`.

   Add a `CustomConverter` for the `Font` class. It's almost as easy as writing a `.java2xml` file. Check out `Java2XML#addCustomConverter`.

### To Do

- Setters and getters work with Maps
- `Java2XML` can't turn interfaces and abstract classes into attributes. It is possible to turn them into elements though.
- "`class`", "`null`" attributes are reserved.
- Wart: one can't pass a custom class (e.g., `HashMap`) into `Java2XML`. Workaround: can pass in an Object containing a custom class.

## Related Documentation

For overviews, tutorials, examples, guides, and tool documentation, please see:

- JUMP Workbench User's Guide
- JUMP Developer's Guide
- JUMP Technical Report
- JUMP Data Sheet