Java Architecture for XML Binding (JAXB) provides a fast and convenient way to bind XML schemas and Java representations, making it easy for Java developers to incorporate XML data and processing functions in Java applications. As part of this process, JAXB provides methods for unmarshalling (reading) XML instance documents into Java content trees, and then marshalling (writing) Java content trees back into XML instance documents. JAXB also provides a way to generate XML schema from Java objects.
Ref: Trail: Java Architecture for XML Binding
Marshal/UnMarshall with JAXB Example
Marshalling to XML is very easy through the use of annotations like:- @XmlRootElement(name = "Livro") on your objects
- @XmlElementWrapper(name = "autor") and @XmlElement(name = "nome") to wrap collections (like List; ArrayList; etc.)
Check this great article for more information on JAXB and collection properties.
JaxbTest.java
package test.jaxb; package test.jaxb; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.transform.stream.StreamSource; /** * @author Antero Mano */ @XmlRootElement(name = "myRootElement") public class JaxbTest { //NOTE: The List field below is annotated with JAXB tags bc it doesnt have //set/get (not a property). //It doesnt have set/get on purpose bc we dont want to set/get the entire //list - we just want to add objects to it: @XmlElementWrapper(name = "myListElementWrapper") @XmlElement(name = "myListElement") private List<Other> lista = new ArrayList<Other>(); //Properties (= fields with set/get) are automatically mapped: private String greating = "Hello "; //fields with (no JAXB tags) and (no set/get) are ignored: private static final String FILENAME = "myxml.xml"; //FINAL NOTE: dont tag fields that have set/get (properties). Since it has //set/get it will automatically be mapped. If you tag the field you can get //double output or a JAXB compile error. //like any JavaBean, JAXB needs the class to have a no-arg default constructor. public JaxbTest() { } private JaxbTest(String someString, Other myObj) { this.greating += someString; this.lista.add(myObj); } public String getGreating() { return greating; } public void setGreating(String greating) { this.greating = greating; } public void add(Other obj) { this.lista.add(obj); } public boolean marshallToXmlFile() { try { JAXBContext context = JAXBContext.newInstance(JaxbTest.class); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); //if you want you can add a XSL to the resulting xml doc (Java 6): //m.setProperty("com.sun.xml.internal.bind.xmlHeaders", // "<?xml-stylesheet type=\"text/xsl\" href=\"my_xslt.xsl\"?>"); //if you want you can add a XSL to the resulting xml doc (Java 5): //m.setProperty("com.sun.xml.bind.xmlHeaders", // "<?xml-stylesheet type=\"text/xsl\" href=\"my_xslt.xsl\"?>"); //print XML doc on screen: m.marshal(this, System.out); //save XML doc to file: m.marshal(this, new File(JaxbTest.FILENAME)); return true; } catch (JAXBException ex) { ex.printStackTrace(); } return false; } public static JaxbTest unMarshallFromXmlFile() { try { JAXBContext jc = JAXBContext.newInstance(JaxbTest.class); Unmarshaller u = jc.createUnmarshaller(); //print all known type for this JAXBContext String allJAXBContextKnownTypes = jc.toString(); System.out.println(allJAXBContextKnownTypes); File file = new File(JaxbTest.FILENAME); JAXBElement<JaxbTest> root = u.unmarshal(new StreamSource(file), JaxbTest.class); return root.getValue(); } catch (JAXBException e) { //e.printStackTrace(); } return null; } public static void main(String args[]) { JaxbTest jaxbTest = JaxbTest.unMarshallFromXmlFile(); if (jaxbTest == null) { System.out.println("xml file doesnt exist yet. A new one will be created."); jaxbTest = new JaxbTest("World", new Other(0.5, "1/2")); } jaxbTest.add(new Other(1.5, "one and a half")); jaxbTest.add(new Other(2.2, "two something... who cares?!")); jaxbTest.marshallToXmlFile(); } }
Other.java
package test.jaxb; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; /** * @author Antero Mano */ @XmlRootElement(name = "myInnerClassRootElement") public class Other { //fields with no set/get and no JAXB annotation are ignored: private String example = "will be ignored by JAXB!"; //next field has set/get (a property) so its automatically mapped: private double number; //next field needs the @XmlElement tag bc it doesn't have set/get (not a property): @XmlElement private String txt; //like any JavaBean JAXB needs the class to have a no-arg default constructor. public Other() { } public Other(double number, String txt) { this.number = number; this.txt = txt; } public double getNumber() { return number; } public void setNumber(double number) { this.number = number; } @Override public String toString() { return Double.toString(this.number); } }
Resulting xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <myRootElement> <myListElementWrapper> <myListElement> <txt>1/2</txt> <number>0.5</number> </myListElement> <myListElement> <txt>one and a half</txt> <number>1.5</number> </myListElement> <myListElement> <txt>two something... who cares?!</txt> <number>2.2</number> </myListElement> </myListElementWrapper> <greating>Hello World</greating> </myRootElement>
Things to test:
If you remove @XmlElementWrapper(name = "myListElementWrapper")
JAXB wont put any wrapper around the list elements:
<myRootElement> <myListElement> <txt>1/2</txt> <number>0.5</number> </myListElement> <myListElement> <txt>one and a half</txt> <number>1.5</number> </myListElement> <myListElement> <txt>two something... who cares?!</txt> <number>2.2</number> </myListElement> <greating>Hello World</greating> </myRootElement>If you remove @XmlElement(name = "myListElement")
JAXB will use the field variable name as default:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <myRootElement> <myListElementWrapper> <lista> <txt>1/2</txt> <number>0.5</number> </lista> <lista> <txt>one and a half</txt> <number>1.5</number> </lista> <lista> <txt>two something... who cares?!</txt> <number>2.2</number> </lista> </myListElementWrapper> <greating>Hello World</greating> </myRootElement>If you remove the @XmlRootElement(name = "myInnerClassRootElement")
Nothing will change. The annotation is not necessary for our result.
It would only be usefull if you wanted to map this class directly using a method like marshallToXmlFile().
Mapping Enumerations
Ref: how to use enum in jaxb unmarshalling@XmlEnum public enum Estado { @XmlEnumValue("pending") PENDING, @XmlEnumValue("aproved") APROVED, @XmlEnumValue("canceled") CANCELLED, @XmlEnumValue("notfound") NOT_FOUND }
Mapping List, ArrayList, and other Collection objects
Option 1:
@XmlElementWrapper(name = "myListElementWrapper") @XmlElement(name = "myListElement") private List<Other> lista = new ArrayList<Other>();
Option 2 (for ex. when you have a object that extends a Collection):
Ref. stackoverflow
Ref. stackoverflow
@XmlRootElement(name = "db") class Database extends ArrayList<Encomenda> { @XmlElement(name = "encomenda") public List<Encomenda> getDatabase() { return this; //"self-getter" } }Then in another class we could do (Recal that Database extends an ArrayList so it already implements interface List):
public class DaoImpl implements IDao { private final String FILENAME = "dbMock.xml"; private List<Encomenda> db; public DaoImpl() { db = unMarshallFromXmlFile();; } private List<Encomenda> unMarshallFromXmlFile() { try { JAXBContext jc = JAXBContext.newInstance(Database.class); Unmarshaller u = jc.createUnmarshaller(); File file = new File(this.FILENAME); JAXBElement<Database> root = u.unmarshal(new StreamSource(file), Database.class); return root.getValue(); } catch (JAXBException e) { //e.printStackTrace(); } return null; } ... }
JAXB
Tutorials and Documentation:- Java and XML Binding: straight to the point tutorial;
- JAXB annotations for soa/ioc: straight to the point JABX annotations guide:
@XmlAccessorType
@XmlAttribute
@XmlElement
@XmlElements
@XmlElementWrapper
@XmlJavaTypeAdapter
@XmlRootElement
@XmlTransient
@XmlValue - Java-XML mapping made easy with JAXB 2.0: a more in dept tutorial;
- Official JAXB documentation: click the "learn" link to get to the documentation;
- Official Java XML technologies
- JAXP(SAX & DOM) vs JAXB: A discussion about different XML technologies that you can use in Java
Using only annotations you can easily marshal and unmarshal objects to and from XML
Another Example: Marshall (Serialize/write) Java Objects to a XML doc
The main class (BookSearchXML) has a List of Livro objects:@XmlRootElement(name = "Biblioteca") public class BookSearchXML { //@XmlElementWrapper(name = "Biblioteca") @XmlElement(name = "Livro") private List<Livro> livros = new ArrayList<Livro>(); ... private void marshallToXmlFile(String fileName) { try { JAXBContext context = JAXBContext.newInstance(BookSearchXML.class); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); //if you want to add an XSL to the generated XML doc: m.setProperty("com.sun.xml.internal.bind.xmlHeaders", "<?xml-stylesheet type=\"text/xsl\" href=\"my_xslt.xsl\"?>"); m.marshal(this, System.out);//prints XML doc to screen m.marshal(this, new File(fileName)); //saves XML doc to file } catch (JAXBException ex) { Logger.getLogger(BookSearchXML.class.getName()).log(Level.SEVERE, null, ex); } } }
Class Livro is a very basic JavaBean:
@XmlRootElement(name = "Livro") public class Livro { private String titulo, ano, editora, paginas, isbn, descricao, url, capa; @XmlElementWrapper(name = "autor") @XmlElement(name = "nome") ArrayList<String> autores; ... }
Generated XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml-stylesheet type="text/xsl" href="my_xslt.xsl"?> <Biblioteca> <Livro> <autor> <nome>James Gosling</nome> </autor> <ano>2000</ano> <capa>http://</capa> <descricao>For nearly five years..</descricao> <editora>Addison-Wesley Professional</editora> <ISBN>9780201310085</ISBN> <paginas>505</paginas> <titulo>The Java Language Specification</titulo> <URL>http://books.google.co.uk/books?id=Ww1B9O_yVGsC&amp;dq=java&amp</URL> </Livro> <Livro> <autor> <nome>Herbert Schildt</nome> </autor> <ano>2002</ano> <capa>http://</capa> <descricao></descricao> <editora>McGraw-Hill Professional</editora> <ISBN>9780072225136</ISBN> <paginas>565</paginas> <titulo>Java 2</titulo> <URL>http://books.google.co.uk/books?id=YWDJJGYaLG4C&amp;dq=java&amp</URL> </Livro> </Biblioteca>
Add a xml-stylesheet (XSL) to the generated XML doc
You just need to set a property on your Marshaller object:m.setProperty("com.sun.xml.internal.bind.xmlHeaders", "<?xml-stylesheet type=\"text/xsl\" href=\"my_xslt.xsl\"?>");
Note: There are different names to accomplish this in Java5 and Java 6
Lets consider an object Marshaller m:
- Java5:
m.setProperty("com.sun.xml.bind.xmlHeaders",
- Java6:
m.setProperty("com.sun.xml.internal.bind.xmlHeaders",
todo
codetodo
codetodo
codetodo
codetodo
code
1 comentário:
Thanks for your sharing,i learn a lot from your post.There is a lot of very useful knowledge in your post.I enjoy reading it and hope to see more.There is guy here swearing up and down that JAXB is the greatest thing since sliced bread. I am curious to see what stackoverflow users think the use case is for JAXB and what makes it a good or a bad solution for that case.
java barcode maker
Enviar um comentário