Reading my XML with JAXB - java

I have an xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<measures>
<measure isapplicationaggregated="true" errorseverity="none" servicecontext="SERVER" userdefined="false" id=".NET % Time in Jit" calculatepercentiles="false" createdtimestamp="1478709202942" errortype="none" rate="purepath" description="Percentage of elapsed time spent in JIT compilation since the last JIT compilation phase." ischartable="true" metricid=".NET % Time in Jit" measuretype="PerfMonMeasure" isaggregated="false" metricgroupid=".NET Common Language Runtime" displayaggregations="7" calculatebaseline="false" displayunit="percent">
<perfmonperformancecounter performanceobject=".NET CLR Jit" instance="{monitored_process}" performancecounter="% Time in Jit" />
<color color.blue="64" color.green="0" color.red="64" />
</measure>
<measure isapplicationaggregated="true" errorseverity="none" servicecontext="SERVER" userdefined="false" id=".NET Garbage Collection (# Gen 0)" calculatepercentiles="false" createdtimestamp="1478709202942" errortype="none" rate="purepath" description="Number of times the generation 0 objects were garbage collected (Gen 0 GC) per interval." ischartable="true" metricid=".NET Garbage Collection (# Gen 0)" measuretype="PerfMonMeasure" isaggregated="false" metricgroupid=".NET Common Language Runtime" displayaggregations="31" calculatebaseline="false" displayunit="number">
<perfmonperformancecounter performanceobject=".NET CLR Memory" instance="{monitored_process}" performancecounter="# Gen 0 Collections" />
<color color.blue="64" color.green="192" color.red="128" />
</measure>
</measures>
I need to translate it using the JAXB reader except it keeps saying it cannot read it.
I only need the userdefined , id , and measuretype properties from the measure object.
The code below is what I have so far:
XML
#XmlRootElement(name = "measures")
public class MeasureListWrapper {
private List<Property> measureProperties = new ArrayList<Property>();
#XmlElement(name="measure")
public List<Property> getMeasures() {
return measureProperties;
}
}
MainApp:
JAXBContext context = JAXBContext.newInstance(MeasureListWrapper.class);
Unmarshaller um = context.createUnmarshaller();
// Reading XML from the file and unmarshalling.
MeasureListWrapper wrapper = (MeasureListWrapper) um.unmarshal(file);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "file:///C:/Users/mydesk/Desktop/FirstXSD.xml");
marshaller.marshal(wrapper, System.out);
I am new to JAXB and can't get this to work. Really I just need to export the preferred properties to a text file after I pull them from this xml.
I would also like to store the ID's and measuretypes to display in a table in my applet window.
Any help?
Thanks!

This worked for me:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class MeasureParser {
#XmlRootElement(name = "measure")
public static class Measure {
#XmlAttribute(name = "id")
private String id;
#XmlAttribute(name = "measuretype")
private String measureType;
#XmlAttribute(name = "userdefined")
private boolean userDefined;
}
#XmlRootElement(name = "measures")
public static class MeasureListWrapper {
private List<Measure> measureProperties = new ArrayList<>();
#XmlElement(name = "measure")
public List<Measure> getMeasures() {
return measureProperties;
}
}
public static void main(String[] args) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(MeasureListWrapper.class);
Unmarshaller um = context.createUnmarshaller();
// Reading XML from the file and unmarshalling.
MeasureListWrapper wrapper = (MeasureListWrapper) um.unmarshal(new File("test.xml"));
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "file:///C:/Users/mydesk/Desktop/FirstXSD.xml");
marshaller.marshal(wrapper, System.out);
}
}

Related

How to marshall a List to an XML file with JAXB?

Looking to marshall and unmarshall objects with XML.
This is fine for one customer, which is created as:
thufir#dur:~/jaxb$
thufir#dur:~/jaxb$ ls
jaxbexample.xml
thufir#dur:~/jaxb$
thufir#dur:~/jaxb$ cat jaxbexample.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer id="0">
<age>44</age>
<name>mkyong</name>
</customer>
thufir#dur:~/jaxb$
How do I go about creating a List of Customer objects and write those to an xml file?
package helloWorldSaxon;
import java.io.File;
import java.util.List;
import java.util.logging.Logger;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.Result;
import javax.xml.transform.dom.DOMResult;
//https://stackoverflow.com/q/17059227/262852
public class JaxBExample {
private static final Logger LOG = Logger.getLogger(JaxBExample.class.getName());
private String pathToFile = "/home/thufir/jaxb/jaxbexample.xml";
private int id = 0;
public JaxBExample() {
}
public Customer readCustomerFromFile() throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File(pathToFile);
Customer customer = (Customer) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "/tmp/bla-bla.xsd"); //???
Result result = new DOMResult(); //what to do with result?? nothing?
marshaller.marshal(customer, result);
return customer;
}
public Customer dummyCustomer() throws Exception {
Customer customer = new Customer();
customer.setId(id);
customer.setName("mkyong");
customer.setAge((int) (Math.random() * 100));
id++;
return customer;
}
public void writeCustomersTofile(List<Customer> customers) {
//new file, overwrite old file.
//write a collection to the file
//so that each customer can then be read in.
//import to basex
}
public void writeCustomerToFile(Customer customer) throws Exception {
File file = new File(pathToFile);
JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(customer, file);
}
}
in the context of a database of Customer in BaseX:
thufir#dur:~/jaxb$
thufir#dur:~/jaxb$ basex
[warning] /usr/bin/basex: Unable to locate /usr/share/java/jing.jar in /usr/share/java
BaseX 9.0.1 [Standalone]
Try 'help' to get more information.
>
> CREATE DB customers jaxbexample.xml
Database 'customers' created in 367.3 ms.
>
> XQUERY /
<customer id="0">
<age>44</age>
<name>mkyong</name>
</customer>
Query executed in 213.83 ms.
>
> exit
Enjoy life.
thufir#dur:~/jaxb$
However, not looking to use the BaseX API at the moment, strictly staying with JAXB for this.
Just looking to build a file of multiple Customer objects which is well formed. (I don't think it even has to be valid.)
The "simplest" solution I found so far:
package com.danibuiza.jaxb.ultimate.marshal;
import java.io.File;
import java.time.LocalDate;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import com.danibuiza.jaxb.ultimate.business.Countries;
import com.danibuiza.jaxb.ultimate.business.Country;
/**
* Simple example of usage of jaxb marshaling functionalities showing how to manage lists
*
* #author dgutierrez-diez
*/
public class JaxBExampleList
{
public static void main( String[] args )
{
try
{
/* init a list with a couple of countries to marshal */
Country spain = new Country();
spain.setName( "Spain" );
spain.setCapital( "Madrid" );
spain.setContinent( "Europe" );
spain.setFoundation( LocalDate.of( 1469, 10, 19 ) );
Country usa = new Country();
usa.setName( "USA" );
usa.setCapital( "Washington" );
usa.setContinent( "America" );
usa.setFoundation( LocalDate.of( 1776, 7, 4 ) );
Countries countries = new Countries();
countries.add( spain );
countries.add( usa );
/* init jaxb marshaler */
JAXBContext jaxbContext = JAXBContext.newInstance( Countries.class );
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
/* set this flag to true to format the output */
jaxbMarshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, true );
/* marshaling of java objects in xml (output to file and standard output) */
jaxbMarshaller.marshal( countries, new File( "list_countries.xml" ) );
jaxbMarshaller.marshal( countries, System.out );
}
catch( JAXBException e )
{
e.printStackTrace();
}
}
}

Can't unmarshal marshalled document when default namespace used

I set up a repo which shows my problem: https://github.com/Waxolunist/stackoverflow.34392476
I try to unmarshal a simple xml document:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<for:document xmlns:for="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx">
<Export xmlns="urn:adcubum:Syrius">
<ExportInhalt/>
<ExportKopf>
<Quelle>lokal</Quelle>
</ExportKopf>
<SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</SchemaVersion>
</Export>
</for:document>
This is the document I get from following code:
Document document = new Document();
Export export = new Export();
ExportKopf exportKopf = new ExportKopf();
exportKopf.setQuelle("lokal");
export.setExportKopf(exportKopf);
ExportInhalt exportInhalt = new ExportInhalt();
export.setExportInhalt(exportInhalt);
export.setSchemaVersion("bec811a9807a8c8da403d70b9b5e22ad");
document.setExport(export);
JAXBContext jaxbContext = JAXBContext.newInstance(Document.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(document, System.out);
Document looks as follows:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "document", namespace = "http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx")
public class Document {
#XmlElement(name = "Export", namespace = "urn:adcubum:Syrius")
private vo.dom.common_service.modul_bl.syrius.Export export;
}
package-info.java
#XmlSchema(
namespace = "urn:adcubum:Syrius",
xmlns = {
#XmlNs(prefix = "for", namespaceURI = "http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx"),
#XmlNs(prefix = "", namespaceURI = "urn:adcubum:Syrius")
},
elementFormDefault = XmlNsForm.UNQUALIFIED)
When I try to unmarshal it, I don't get the data mapped:
JAXBContext jaxbContext = JAXBContext.newInstance(Document.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InputStream is = this.getClass().getResourceAsStream("/requests/document_simple3.xml");
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader xmlsr = factory.createXMLStreamReader(is);
Document document = unmarshaller.unmarshal(xmlsr, Document.class).getValue();
ExportKopf and ExportInhalt are returning null.
Instead following xml works. The only difference is the namespace prefix:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<for:document xmlns:for="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx">
<ns3:Export xmlns:ns3="urn:adcubum:Syrius">
<ExportInhalt/>
<ExportKopf>
<Quelle>lokal</Quelle>
</ExportKopf>
<SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</SchemaVersion>
</ns3:Export>
</for:document>
I am using eclipselink moxy.
What do I have to change, so that unmarshaling the marshaled document works.
I think it's always a good idea to see the actual XSD schema of your mapping whenever something strange like this is happening in JAXB. You could easily do that with the following code.
JAXBContext jaxbContext = JAXBContext.newInstance(Document.class);
jaxbContext.generateSchema(new SchemaOutputResolver() {
#Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
StreamResult streamResult = new StreamResult(new PrintWriter(System.err) {
#Override
public void close() {
}
});
streamResult.setSystemId(suggestedFileName);
return streamResult;
}
});
That will print the schema(s) that should reflect your JAXB model (you can use another writer to write them to a file). The XSD files are usually very revealing about these kind of issues. I think the problem in your case is the #XmlSchema mapping. You should try to use elementFormDefault = XmlNsForm.QUALIFIED instead. It's always a good idea to use QUALIFIED whenever you're working with multiple namespaces in your mapping.
EDIT: while the main problem with your JAXB mapping was the wrong and/or missing value for the elementFormDefault there were other things that had to be fixed for the code in your repo to work.
the Export element in the Document was missing a namespace declaration (from your example, the Document and Export elements are parts of different namespaces)
missing elementFormDefault = XmlNsForm.QUALIFIED from the export package
wrong namespace value for your main package #XmlSchema annotation (was urn:stackoverflow:exportnamespace instead of urn:stackoverflow:documentnamespace in which the Document element should be)
wrong import for jdk_jaxb/UnmarshallerTest.java - it was importing the model.eclipselink.Document instead of model.sun.Document
EDIT: Here's the updated code https://github.com/MojoJojo/stackoverflow.34392476
Okay, here's the working version with all moxy_jaxb test passing. Because you said you are using moxy, I left out the changes for model.sun.* packages. If you understand the concept below, you should be able to fix it easily on your own.
First, I cleaned up namespace declarations in your mode.* packages. Most of the times, the declarations and bindings inside package-info.java suffice. Declaring them over and over again on package, entities, fields will add to complexity and unwanted behavior. Check out this link for details. There is no need to re-declare them on the individual Models/Entities themselves, unless there is a strong reason to do otherwise. Next, the test xml itself was a little broken. Fixed the test xml with proper prefixes wherever necessary:
First, model.eclipselink.Document.java
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "document")
public class Document {
#XmlElement(name = "Export", namespace="urn:adcubum:Syrius")
private Export export;
public Export getExport() {
return export;
}
public void setExport(Export export) {
this.export = export;
}
}
model.eclipselink.package-info.java:
#XmlSchema(namespace = "http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx",
elementFormDefault = XmlNsForm.QUALIFIED)
package model.eclipselink;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Similar refactoring on model.eclipselink.export.packageinfo.java:
#XmlSchema(namespace = "urn:adcubum:Syrius",
elementFormDefault = XmlNsForm.QUALIFIED)
package model.eclipselink.export;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.Xml
And on Export.java:
package model.eclipselink.export;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.eclipse.persistence.oxm.annotations.XmlElementNillable;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "Export")
#XmlType(name = "Export", propOrder = {
"exportInhalt",
"exportKopf",
"schemaVersion"
})
public class Export {
#XmlElement(name = "ExportKopf", required = true)
private ExportKopf exportKopf;
#XmlElement(name = "ExportInhalt", required = true)
private ExportInhalt exportInhalt;
#XmlElement(name = "SchemaVersion", required = true)
private String schemaVersion;
public ExportKopf getExportKopf() {
return exportKopf;
}
public void setExportKopf(ExportKopf exportKopf) {
this.exportKopf = exportKopf;
}
public ExportInhalt getExportInhalt() {
return exportInhalt;
}
public void setExportInhalt(ExportInhalt exportInhalt) {
this.exportInhalt = exportInhalt;
}
public String getSchemaVersion() {
return schemaVersion;
}
public void setSchemaVersion(String schemaVersion) {
this.schemaVersion = schemaVersion;
}
}
And the few tweaks to your xml files for prefixes.Here's document_prefix.xml
<?xml version="1.0" encoding="UTF-8"?>
<for:document xmlns:for="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx">
<ns1:Export xmlns:ns1="urn:adcubum:Syrius">
<ns1:ExportKopf>
<ns1:Quelle>lokal</ns1:Quelle>
</ns1:ExportKopf>
<ns1:ExportInhalt/>
<ns1:SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</ns1:SchemaVersion>
</ns1:Export>
</for:document>
document.xml:
<?xml version="1.0" encoding="UTF-8"?>
<for:document
xmlns:for="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx" xmlns="urn:adcubum:Syrius">
<Export>
<ExportKopf>
<Quelle>lokal</Quelle>
</ExportKopf>
<ExportInhalt />
<SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</SchemaVersion>
</Export>
</for:document>
and document_realnamespace.xml (Not sure what the purpose of this file is):
<?xml version="1.0" encoding="UTF-8"?>
<for:document xmlns:ns1="urn:adcubum:Syrius" xmlns:for="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx">
<ns1:Export>
<ns1:ExportKopf>
<ns1:Quelle>lokal</ns1:Quelle>
</ns1:ExportKopf>
<ns1:ExportInhalt/>
<ns1:SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</ns1:SchemaVersion>
</ns1:Export>
</for:document>
And you run mvn clean test:
Running moxy_jaxb.MarshallerTest
Context class: class org.eclipse.persistence.jaxb.JAXBContext
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrend
erer/forwktbx" xmlns:ns0="urn:adcubum:Syrius">
<ns0:Export>
<ns0:ExportInhalt/>
<ns0:ExportKopf>
<ns0:Quelle>lokal</ns0:Quelle>
</ns0:ExportKopf>
<ns0:SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</ns0:SchemaVersion>
</ns0:Export>
</document>
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.044 sec
Running moxy_jaxb.UnmarshallerTest
Context class: class org.eclipse.persistence.jaxb.JAXBContext
lokal
Context class: class org.eclipse.persistence.jaxb.JAXBContext
lokal
Context class: class org.eclipse.persistence.jaxb.JAXBContext
lokal
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.033 sec

Maintain whitespace in JAXB with xs:any and mixed content

I have a schema with an xs:any element. This element may contain other elements that have mixed content. I'm trying to use JAXB to unmarshall it into Java objects (with the 'any' as an Element).
From the schema:
<xs:element name="a">
<xs:complexType>
<xs:sequence>
<xs:any processContents="lax"/>
</xs:sequence>
</xs:complexType>
</xs:element>
In general, this works. But when handling elements with mixed content, whitespace between nested nodes is lost.
test.xml:
<a><foo><b>Hello</b> <i>World</i></foo></a>
Unmarshalling like this:
JAXBContext jc = JAXBContext.newInstance(A.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
InputStream inputStream = this.getClass().getResourceAsStream("/data/test.xml");
A a = (A) unmarshaller.unmarshal(inputStream);
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(a, System.out);
Results in this:
<a><foo><b>Hello</b><i>World</i></foo></a>
I lose the space between the child tags of the <foo> element. I'm certain that it's the unmarshal step that takes the whitespace out here, but I do need it to survive the round trip.
Note that it's only whitespace-only text content that's removed. This works as desired:
<a><foo><b>Hello</b> to you <i>World</i></foo></a>
I tried adding xml:space="preserve" (see, for example, JAXB: How to keep consecutive spaces as they are in source XML during unmarshalling), but that has no effect on whitespace between elements. I've tried with processContents set to each of strict, lax, and skip, none of which helped.
After facing a similar issue I could come up with the following solution (to this specific scenario, as for some other complex XML structures it doesn't work perfectly).
package com.stackoverflow.answers;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
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.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlMixed;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.transform.stream.StreamSource;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.w3c.dom.Element;
public class XmlAnyElementWithWhiteSpacesTest {
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "a")
private static class A {
#XmlAnyElement
#XmlMixed
private List<Element> elements;
}
private static final String SAMPLE = "<a><foo><b>Hello</b> <i>World</i></foo></a>";
#Test
public void shouldParseAndSerializeKeepingWhiteSpaceElements() throws JAXBException {
// given
JAXBContext jc = JAXBContext.newInstance(A.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
InputStream inputStream = new ByteArrayInputStream(SAMPLE.getBytes(StandardCharsets.UTF_8));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
// when
JAXBElement<A> a = unmarshaller.unmarshal(new StreamSource(inputStream), A.class);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
marshaller.marshal(a.getValue(), outputStream);
String actual = new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
// then
assertEquals(SAMPLE, actual);
}
}
The key points here are:
Usage of #XmlMixed annotation
Usage of StreamSource
You can use either List<Object> or List<Element> for your "XML any content" property.

java xml annotation get field with namespace, <aaa:bbb>value</aaa:bbb>

I'm working on a project that has no schema and I have to parsing the xml response manually.
My problem is i can't get some value using the xml annotation.
For example , the xml is like:
<?xml version='1.0' encoding='UTF-8' ?>
<autnresponse>
<action>QUERY</action>
<response>SUCCESS</response>
<responsedata>
<autn:numhits>7</autn:numhits>
</responsedata>
</autnresponse>
And the java class is :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "autnresponse")
public class AutonomyResponse {
private String action;
private String response;
private ResponseData responsedata;
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "responsedata")
public class ResponseData {
#XmlElement(name = "numhits",namespace = "autn")
private String numhits;
#XmlElement(name = "totalhits")
private String totalhits;
}
I can get the action and the response, but can't get the numhits in the responsedata,
Can anyone tell me how to handle the <autn:numhits> using annotation?
Too much Thanks !!!
Another issue is : I have multi <autn:numhits> in the responsedata....how can i get all the value in the Java code.
--> I solve this multi same tags, just set List and the annotation will automatically generate the list
The fact is autn - is only prefix, not namespace. For correct processing of the XML document, namespace must be declared.
Right namespace declaration:
<?xml version='1.0' encoding='UTF-8' ?>
<autnresponse xmlns:autn="http://namespace.here">
<action>QUERY</action>
<response>SUCCESS</response>
<responsedata>
<autn:numhits>7</autn:numhits>
</responsedata>
</autnresponse>
You also need to change the annotation:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "responsedata")
public class ResponseData {
#XmlElement(name = "numhits",namespace = "http://namespace.here")
private String numhits;
#XmlElement(name = "totalhits")
private String totalhits;
}
And finnaly advice for you. If you have a xsd scheme for this xml document, use the XJC utilit for java code generation.
http://docs.oracle.com/javaee/5/tutorial/doc/bnbah.html
JAXB and other XML processors that are capable of processing XML Schema are going to treat everything before a : as a namespace prefix. If the colon is then you can do the following.
Java Model
You need to specify that your element name contains the : character.
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class ResponseData {
#XmlElement(name = "autn:numhits")
private String numhits;
private String totalhits;
}
Demo
import javax.xml.bind.*;
import javax.xml.parsers.*;
import org.xml.sax.XMLReader;
public class Demo {
public static void main(String[] args) throws Exception {
// Create a SAXParser that is not namespace aware
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
// Create the JAXBContext
JAXBContext jc = JAXBContext.newInstance(AutonomyResponse.class);
// Instead of Unmarshaller we will use an UnmarshallerHandler
Unmarshaller unmarshaller = jc.createUnmarshaller();
UnmarshallerHandler unmarshallerHandler = unmarshaller.getUnmarshallerHandler();
// Do a SAX parse with the UnmarshallerHanlder as the ContentHandler
xr.setContentHandler(unmarshallerHandler);
xr.parse("src/forum20062536/input.xml");
// Get the result of the unmarshal
AutonomyResponse autonomyResponse = (AutonomyResponse) unmarshallerHandler.getResult();
// Marshal the object back to XML
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(autonomyResponse, System.out);
}
}

How to use hashmap properties with JAXB?

I've been fiddling around with JAXB for a while now, I need to generate xml like below
<Root attr1="" attr2="" .. attrn="" >
<CNode attr1="" attr2="" />
.
.
.
<CNode .. />
</Root>
The attributes of Root element is dynamic and would come from either a properties file or a template. What is the best way to get it into the structure as shown above? I'm using hashmaps for dynamic variables and then tried mapping it with XmlJavaTypeAdapter, the best I could do is
<Root>
<Attribs>
<entry key="attr1">Value</entry>
</Attribs>
<CNode .. />
</Root>
Is there a way in jaxb to say use hashmap's key as the attribute name and the value for that key as the value for that attribute in xml? Or if you think there is a better way to do it, I'm open for suggestions. I'm quite thinking about using jaxb's marshaller to add the Root node separately. However it would be nicer if I can just use jaxb's adapter. Thanks!
#XmlAnyAttribute is along the lines of what you need:
Root
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
#XmlRootElement(name="Root")
public class Root {
private Map<QName, String> extension;
private List<CNode> cnodes;
#XmlAnyAttribute
public Map<QName, String> getExtension() {
return extension;
}
public void setExtension(Map<QName, String> extension) {
this.extension = extension;
}
#XmlElement(name="CNode")
public List<CNode> getCnodes() {
return cnodes;
}
public void setCnodes(List<CNode> cnodes) {
this.cnodes = cnodes;
}
}
CNode
import java.util.Map;
import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.namespace.QName;
public class CNode {
private Map<QName, String> extension;
#XmlAnyAttribute
public Map<QName, String> getExtension() {
return extension;
}
public void setExtension(Map<QName, String> extension) {
this.extension = extension;
}
}
Demo
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(new File("input.xml"));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
input.xml
<?xml version="1.0" encoding="UTF-8"?>
<Root att1="A" att2="B">
<CNode att3="C" att4="D"/>
<CNode att5="E" att6="F"/>
</Root>

Categories