XmlPath mapping problems using eclipselink MOXy - java

I don't see why the XmlPath mappings I have made below are coming out as null. Is there something wrong with my syntax? I used similar syntax elsewhere without problem.
Thanks for any clues.. John
<clip lane="-1" offset="2591065664/720000s" name="Music" duration="22304160/240000s" start="176794/48000s" enabled="0" format="r5">
<adjust-volume amount="1dB">
<param name="amount">
<fadeIn type="easeIn" duration="1220/262144s"/>
</param>
</adjust-volume>
<audio ref="r9" name="VoiceOver-26 - audio" duration="4639346/48000s" role="dialogue"/>
</clip>
#XmlRootElement(name = "clip")
#XmlAccessorType(XmlAccessType.FIELD)
public class Clip extends StoryElement {
#XmlPath("adjust-volume/#amount")
#XmlJavaTypeAdapter(DecibelValueAdapter.class)
private Double adjustVolume;
#XmlPath("adjust-volume/param[#name='amount']/fadeIn/#duration")
#XmlJavaTypeAdapter(TimeValueAdapter.class)
private TimeValue fadeIn;
#XmlPath("adjust-volume/param[#name='amount']/fadeOut/#duration")
#XmlJavaTypeAdapter(TimeValueAdapter.class)
private TimeValue fadeOut;

I have not been able to reproduce the issue that you are seeing using EclipseLink 2.4.0. Below is what I have tried.
Clip
Your mappings appear to be ok.
package forum11937980;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement(name = "clip")
#XmlAccessorType(XmlAccessType.FIELD)
public class Clip extends StoryElement {
#XmlPath("adjust-volume/#amount")
#XmlJavaTypeAdapter(DecibelValueAdapter.class)
private Double adjustVolume;
#XmlPath("adjust-volume/param[#name='amount']/fadeIn/#duration")
#XmlJavaTypeAdapter(TimeValueAdapter.class)
private TimeValue fadeIn;
#XmlPath("adjust-volume/param[#name='amount']/fadeOut/#duration")
#XmlJavaTypeAdapter(TimeValueAdapter.class)
private TimeValue fadeOut;
}
jaxb.properties
Do you have a jaxb.properties file in the same package as your domain model with the following entry to specify MOXy as your JAXB provider?
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
input.xml
<clip lane="-1" offset="2591065664/720000s" name="Music" duration="22304160/240000s"
start="176794/48000s" enabled="0" format="r5">
<adjust-volume amount="1dB">
<param name="amount">
<fadeIn type="easeIn" duration="1220/262144s" />
<fadeOut duration="I/Added/This"/>
</param>
</adjust-volume>
<audio ref="r9" name="VoiceOver-26 - audio" duration="4639346/48000s"
role="dialogue" />
</clip>
Demo
package forum11937980;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Clip.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum11937980/input.xml");
Clip clip = (Clip) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(clip, System.out);
}
}
Output
Below is the output from running the demo code. Note that only the mapped portions from the input appear in the output.
<?xml version="1.0" encoding="UTF-8"?>
<clip>
<adjust-volume amount="1.0dB">
<param name="amount">
<fadeIn duration="1220/262144s"/>
<fadeOut duration="I/Added/This"/>
</param>
</adjust-volume>
</clip>
SUPPORTING FILES
Below are the rest of the files needed to make this example run:
StoryElement
package forum11937980;
public class StoryElement {
}
DecibalValueAdapter
package forum11937980;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class DecibelValueAdapter extends XmlAdapter<String, Double> {
#Override
public String marshal(Double v) throws Exception {
return String.valueOf(v) + "dB";
}
#Override
public Double unmarshal(String v) throws Exception {
return Double.valueOf(v.substring(0, v.length() - 2));
}
}
TimeValue
package forum11937980;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class TimeValue {
#XmlValue
private String value;
}
TimeValueAdapter
package forum11937980;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class TimeValueAdapter extends XmlAdapter<TimeValue, TimeValue> {
#Override
public TimeValue marshal(TimeValue v) throws Exception {
return v;
}
#Override
public TimeValue unmarshal(TimeValue v) throws Exception {
return v;
}
}

Related

Reading my XML with JAXB

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);
}
}

JAXB unmarshall element children as plain text [duplicate]

Consider this example -
I have a class called Report that has a field of type Message. The Message class has a field called "body" which is a string. "body" can be any string, but sometimes it contains properly formatted XML content. How can I ensure that when the "body" contains XML content, the serialization takes the form of an XML structure rather than what it gives at present?
Here is the code with the output -
Report class
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlRootElement(name = "Report")
#XmlType(propOrder = { "message"})
public class Report
{
private Message message;
public Message getMessage() { return message; }
public void setMessage(Message m) { message = m; }
}
Message class
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
#XmlType(propOrder = { "body" })
public class Message
{
private String body;
public String getBody() { return body; }
#XmlElement
public void setBody(String body) { this.body = body; }
}
Main
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class SerializationTest
{
public static void main(String args[]) throws Exception
{
JAXBContext jaxbContext = JAXBContext.newInstance(Report.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Report report = new Report();
Message message = new Message();
message.setBody("Sample report message.");
report.setMessage(message);
jaxbMarshaller.marshal(report, System.out);
message.setBody("<rootTag><body>All systems online.</body></rootTag>");
report.setMessage(message);
jaxbMarshaller.marshal(report, System.out);
}
}
The output is as follows -
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Report>
<message>
<body>Sample report message.</body>
</message>
</Report>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Report>
<message>
<body><rootTag><body>All systems online.</body></rootTag></body>
</message>
</Report>
As you can see in the above output, for the second instance of "body", the serialization produced
<body><rootTag><body>All systems online.</body></rootTag></body>
instead of
<body><rootTag><body>All systems online.</body></rootTag></body>
How to solve this problem?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
This use case is mapped using the #XmlAnyElement annotation and specifying a DOMHandler. There appears to be bug when doing this with the JAXB RI, but the following use case works with EclipseLink JAXB (MOXy).
BodyDomHandler
By default a JAXB impleemntation will represent unmapped content as a DOM node. You can leverage a DomHandler to an alternate representation of the DOM, In this case we will represent the DOM as a String.
import java.io.*;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.DomHandler;
import javax.xml.transform.Source;
import javax.xml.transform.stream.*;
public class BodyDomHandler implements DomHandler<String, StreamResult> {
private static final String BODY_START_TAG = "<body>";
private static final String BODY_END_TAG = "</body>";
private StringWriter xmlWriter = new StringWriter();
public StreamResult createUnmarshaller(ValidationEventHandler errorHandler) {
return new StreamResult(xmlWriter);
}
public String getElement(StreamResult rt) {
String xml = rt.getWriter().toString();
int beginIndex = xml.indexOf(BODY_START_TAG) + BODY_START_TAG.length();
int endIndex = xml.indexOf(BODY_END_TAG);
return xml.substring(beginIndex, endIndex);
}
public Source marshal(String n, ValidationEventHandler errorHandler) {
try {
String xml = BODY_START_TAG + n.trim() + BODY_END_TAG;
StringReader xmlReader = new StringReader(xml);
return new StreamSource(xmlReader);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
Message
Below is how you would specify the #XmlAnyElement annotation on your Message class.
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlType;
#XmlType(propOrder = { "body" })
public class Message
{
private String body;
public String getBody() { return body; }
#XmlAnyElement(BodyDomHandler.class)
public void setBody(String body) { this.body = body; }
}
Output
Below is the output from running your SerialziationTest:
<?xml version="1.0" encoding="UTF-8"?>
<Report>
<message>
<body>Sample report message.</body>
</message>
</Report>
<?xml version="1.0" encoding="UTF-8"?>
<Report>
<message>
<body>
<rootTag>
<body>All systems online.</body>
</rootTag>
</body>
</message>
</Report>
For More Information
http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
NOTE - Bug in JAXB RI
There appears to be a bug in the JAXB reference implementation, and the example code will result in a stack trace like the following:
Exception in thread "main" javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.internal.SAXException2: unable to marshal type "java.lang.String" as an element because it is missing an #XmlRootElement annotation]
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:317)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:243)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:75)
at forum12428727.SerializationTest.main(SerializationTest.java:20)
Caused by: com.sun.istack.internal.SAXException2: unable to marshal type "java.lang.String" as an element because it is missing an #XmlRootElement annotation
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:216)
at com.sun.xml.internal.bind.v2.runtime.LeafBeanInfoImpl.serializeRoot(LeafBeanInfoImpl.java:126)
at com.sun.xml.internal.bind.v2.runtime.property.SingleReferenceNodeProperty.serializeBody(SingleReferenceNodeProperty.java:100)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:306)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:664)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:141)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:306)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:561)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:290)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:462)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:314)
... 3 more
If its only for Marshalling, and to ignore the < and >,
We can use the following:
marshaller.setProperty("com.sun.xml.bind.marshaller.CharacterEscapeHandler",
new CharacterEscapeHandler() {
#Override
public void escape(char[] ac, int i, int j, boolean flag,
Writer writer) throws IOException {
writer.write(ac, i, j);
}
});
3 different solutions 1), 2) 3), here below :
1) Following post is a the description of your solution Loresh :
http://anna-safronova.livejournal.com/2524.html?thread=9180
This is still missing limitations details.
With embeeded html, we need a <![CDATA block
JAXB's dependancy
com.sun.xml.bind.marshaller.CharacterEscapeHandler
Needs import jaxb-impl for compilation / and may be required for excution, e.g.
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.4</version>
Limitation : this solution is Container-specific and may not run because of class-loading policy.
2) Another similar approach is JDK's rt.jar dependancy
com.sun.xml.internal.bind.CharacterEscapeHandler
http://theopentutorials.com/tutorials/java/jaxb/jaxb-marshalling-and-unmarshalling-cdata-block/
Same limitation / dependends on target JDK, and some tweaks on Eclipse/Maven are necessary (bad alternative / My opinion)
3) Finally, the best solution was found on another post of Reg Whitton :
https://stackoverflow.com/a/12637295/560410
and this is the detailed reciepe :
http://javacoalface.blogspot.co.uk/2012/09/outputting-cdata-sections-with-jaxb.html
Worked perfect for me !

XML to POJO Mapping

I have a service that does the following:
receives different XML requests
turns them into JIBX-generated Java objects
maps the JIBX-generated Java objects into POJOs
sends the POJOs to another service
gets a POJO response back
maps POJO back into JIBX-generated Java objects
turns JIBX-generated Java objects back into XML
returns XML to client.
I'd like to make this process more efficient. Can anyone suggest how? Can JIBX map directly into my POJOs?
Yes Jibx can map directly to your POJOs using Jibx mapping files. I think the below link will be very helpful to understand Jibx binding.
Jibx Introduction
In this you needed library which is available in the url(4shared.com) commented in comments.
package com.xml.Sample.MainP;
import java.io.File;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import com.xml.Sample.Actions.XMLAction;
import com.xml.Sample.Model.States;
public class Retrieve {
public static String XMLModelName = "com.xml.Sample.Model.States";
private static String cities = "E:\\Webeclipseworkspace\\Samples\\src\\Srates.xml";
public static void main(String[] args) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
File f = new File(cities);
Document doc = db.parse(f);
doc.getDocumentElement().normalize();
XMLAction xmla = new XMLAction();
List<States> listXML = xmla.readData(XMLModelName, doc);
// System.out.println(listXML);
String xmlData = xmla.writtingData(listXML);
System.out.println(xmlData);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
}
}
}
package com.xml.Sample.Model;
import com.xml.Sample.XMLAnn.XMLColumn;
import com.xml.Sample.XMLAnn.XMLReport;
#XMLReport(reportName = "row")
public class Directory {
private String city_id;
private String city_name;
private String state_id;
#XMLColumn(label = "city_id")
public String getCity_id() {
return city_id;
}
public void setCity_id(String city_id) {
this.city_id = city_id;
}
#XMLColumn(label = "city_name")
public String getCity_name() {
return city_name;
}
public void setCity_name(String city_name) {
this.city_name = city_name;
}
#XMLColumn(label = "state_id")
public String getState_id() {
return state_id;
}
public void setState_id(String state_id) {
this.state_id = state_id;
}
}
Here I Created Own Library For Converting Pojo classes to xml and xml to pojo classes.
Use Below Link(4Shared.com) at Comments to download Library to add for The Above Code.
String(XML in String) to List
1. FolderItem.java
<code>
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
#XmlAccessorType(XmlAccessType.FIELD)
public class FolderItem {
long itemId ;
String itemName;
String itemType;
String description;
String[] tags;
String path;
/* setters and getters
Annotations not required*/
}
</code>
2. FolderItems.java
<code>
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class FolderItems {
#XmlElement
private List<FolderItem> folderItem;
/* setter and getter */
}
</code>
3. Testing--main method
<code>
class Test{
public static void main(String[] args) throws Exception {
FolderItems f = (FolderItems)strToVo(content, FolderItems.class);
System.out.println(f);
}
static Object strToVo(String content, Class c) throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = jc.createUnmarshaller();
return unmarshaller.unmarshal(new InputSource(new StringReader(content)));
}
}
</code>
4. XML in String
<code>
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<FolderItems>
<folderItem>
<description>Lapse notice invoice for additional interests/additional insureds</description>
<itemId>480004439</itemId>
<itemName>Lapse_Invoice_AI</itemName>
<itemType>application/x-thunderhead-ddv</itemType>
<path>/Templates/Billing Center/Lapse_Invoice_AI</path>
<tags></tags>
</folderItem>
</FolderItems>
</code>

How do I map several elements to a single class in JAXB

I have following XML on input:
<root>
<response1></response1>
</root>
or
<root>
<response2></response2>
</root>
And there is possibly a lot of response tags each of which I need to map to a single Response class because they have almost the same structure.
Is it easy to do in JAXB?
Thanks.
This could be done with the #XmlElements annotation:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
#XmlElements({
#XmlElement(name="response1", type=Response.class),
#XmlElement(name="response2", type=Response.class),
#XmlElement(name="response3", type=Response.class)
})
private Response response;
}
http://blog.bdoughan.com/2010/10/jaxb-and-xsd-choice-xmlelements.html
http://blog.bdoughan.com/2011/04/xml-schema-to-java-xsd-choice.html
Well, sure. In XSD file, define a type first:
<xs:complexType name="response">
<!-- define type here -->
</xs:complexType>
Now define your elements using it:
<xs:element name="response1" type="response"/>
<xs:element name="response2" type="response"/>
<!-- and so on and so forth -->
I got it to work this way. It uses an XMLStreamReader as the source, and a StreamReaderDelegate to intercept and rewrite the element names before they reach jaxb.
The main test class:
package grimbo.test.jaxb;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.util.StreamReaderDelegate;
public class JaxbTest {
public static <T> T unmarshal(Class<T> clazz, InputStream inputStream) throws JAXBException, XMLStreamException,
FactoryConfigurationError {
XMLStreamReader r = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
MyXMLStreamReader my = new MyXMLStreamReader(r);
String packageName = clazz.getPackage().getName();
JAXBContext jc = JAXBContext.newInstance(packageName);
Unmarshaller u = jc.createUnmarshaller();
return (T) u.unmarshal(my);
}
public static void main(String[] args) throws Exception {
String xml1 = "<root>" + "<response1>test1</response1>" + "</root>";
String xml2 = "<root>" + "<response2>test2</response2>" + "</root>";
Object ob = unmarshal(Response.class, new ByteArrayInputStream(xml1.getBytes()));
System.out.println(ob);
ob = unmarshal(Response.class, new ByteArrayInputStream(xml2.getBytes()));
System.out.println(ob);
}
static class MyXMLStreamReader extends StreamReaderDelegate {
public MyXMLStreamReader(XMLStreamReader reader) {
super(reader);
}
public QName getName() {
QName qname = super.getName();
return qname;
}
public String getLocalName() {
String localName = super.getLocalName();
if (localName.matches("response\\d+")) {
return "response";
}
return localName;
}
}
}
The Response class is:
package grimbo.test.jaxb;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "root", namespace = "")
public class Response {
String response;
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
#Override
public String toString() {
return "Response [response=" + response + "]";
}
}
And there's a jaxb.index file in this package too, that declares the Response class:
Response
The output of the test is:
Response [response=test1]
Response [response=test2]
Is this any help?
The easiest thing to do imo would be to make the response element an unbounded list in your schema then once you have created your bindings you can iterate throught the list of response nodes.
I tried to map multiple tag to single class using JAXB with same format mention above.
Now define your elements using it:
<xs:element name="response1" type="response"/>
<xs:element name="response2" type="response"/>
<!-- and so on and so forth -->
While unmarshalling JAXB validates the XML(format) with response class format mentioned in XSD file ,but its is giving me JAXB.element class object instead of response object.
Please suugest with answer..

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