6

I am new to JAXB and for the beginning I am marshaling some simple Java files like Hello, world!.

I want to marshal whole file, even with my comments lines placed like this:

/*
* some comment
*/

//another comment

And get them in XML in comment block:

<!--
some comment
-->

<!-- another comment -->

Is there any way to marshal java files with comments?

Sarpens
  • 298
  • 3
  • 9
  • Have you seen [this link](http://stackoverflow.com/a/25720364/3364187)? – Xstian Nov 07 '14 at 13:55
  • There is piece of great code but from XML to Java (unmarshaling). There is an option to do it in opposite way - from Java in input to XML on output? – Sarpens Nov 07 '14 at 14:09
  • 1
    There is a way.. but if you want put in the middle the comment you can't use JAXB.. [See Here](http://stackoverflow.com/a/16959146/3364187) – Xstian Nov 07 '14 at 14:24
  • I am open for new tools, there is any other option to do it without using JAXB? – Sarpens Nov 07 '14 at 14:32
  • You could use StAX, [see here a tutorial](http://docs.oracle.com/javase/tutorial/jaxp/stax/example.html#bnbgq). [And see here a benchmark](http://java.dzone.com/articles/xml-unmarshalling-benchmark) – Xstian Nov 07 '14 at 14:42
  • I guess my last question - all solutions that you have posted here let add some predefined comment lines - there is some way to get in-file comments? – Sarpens Nov 07 '14 at 14:59

1 Answers1

17

There are a few hurdles to overcome with your use case:

  1. The comments aren't stored in the byte code for a class, so you will need to make them available some where else.
  2. The JAXB API doesn't provide a way to map to a content node.

That being said, below is an approach that may work for you using: StAX with JAXB and leveraging a Marshaller.Listener.

Java Model

Customer

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlType(propOrder={"name", "address"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

    private String name;
    private Address address;

    public Customer() {
    }

    public Customer(String name, Address address) {
        this.name = name;
        this.address = address;
    }

}

Address

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Address {

    String street;

    public Address() {
    }

    public Address(String street) {
        this.street = street;
    }

}

Demo Code

MyMarshalListener

import javax.xml.bind.Marshaller;
import javax.xml.stream.*;

public class MyMarshallerListener extends Marshaller.Listener {

    private XMLStreamWriter xsw;

    public  MyMarshallerListener(XMLStreamWriter xsw) {
        this.xsw = xsw;
    }

    @Override
    public void beforeMarshal(Object source)  {
        try {
            xsw.writeComment("Before:  " + source.toString());
        } catch(XMLStreamException e) {
            // TODO: handle exception
        }
    }

    @Override
    public void afterMarshal(Object source) {
        try {
            xsw.writeComment("After:  " + source.toString());
        } catch(XMLStreamException e) {
            // TODO: handle exception
        }
    }

}

Demo

import javax.xml.bind.*;
import javax.xml.stream.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        Address address = new Address("123 A Street");
        Customer customer = new Customer("Jane", address);

        XMLOutputFactory xof = XMLOutputFactory.newFactory();
        XMLStreamWriter xsw = xof.createXMLStreamWriter(System.out);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setListener(new MyMarshallerListener(xsw));
        marshaller.marshal(customer, xsw);
        xsw.close();;
    }

}

Real Output

<?xml version="1.0" ?><!--Before:  forum26802450.Customer@18de9738--><!--Before:  forum26802450.Customer@18de9738--><customer><name>Jane</name><!--Before:  forum26802450.Address@43e47e37--><address><street>123 A Street</street><!--After:  forum26802450.Address@43e47e37--></address><!--After:  forum26802450.Customer@18de9738--></customer><!--After:  forum26802450.Customer@18de9738-->

Formatted Output

Here is what the output looks like formatted:

<?xml version="1.0" ?>
<!--Before:  forum26802450.Customer@18de9738-->
<!--Before:  forum26802450.Customer@18de9738-->
<customer>
    <name>Jane</name>
    <!--Before:  forum26802450.Address@43e47e37-->
    <address>
        <street>123 A Street</street>
        <!--After:  forum26802450.Address@43e47e37-->
    </address>
    <!--After:  forum26802450.Customer@18de9738-->
 </customer>
 <!--After:  forum26802450.Customer@18de9738-->
bdoughan
  • 147,609
  • 23
  • 300
  • 400