I have the following code,
JAXBContext jc = JAXBContext.newInstance(TestResults.class);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
OutputStream os = new FileOutputStream( "nosferatu.xml" );
TestResults tr = new TestResults();
tr.setUuid(new JAXBElement<String>(new QName("uuid"),String.class, "uuidcontent"));
//ObjectFactory objectFactory = new ObjectFactory();
m.marshal(new JAXBElement<TestResults>(new QName("uri","local"),TestResults.class,new TestResults()), System.out);
in which I am trying to wrap the Java String Class as a jaxb element, since if I do not I get
the
unable to marshal type “java.lang.String” error.
However when I try wrap the java.lang.string in a jaxb element, I get the following error
The method setUuid(String) in the type TestResults is not applicable for the arguments (JAXBElement<String>)
The setUuid method looks as follows
public void setUuid(java.lang.String value) {
this.uuid = value;
}
How can I then wrap my String as a jaxb element where this error will not be thrown?
When marshalled as the root object an instance of String needs to be wrapped in a JAXBElement to provide the root element information (same as for any class without an #XmlRootElement annotation.
When marshalled as a field or property value the containing element is normally derived from the containing field/property so a JAXBElement by default is not required.
Related
Below is an xml File that i have to parse..
<dataroot>
<PARM>
<P1>123</P1>
<P2>abc</P2>
</PARM>
<PARM>
<P1>456</P1>
<P2>def</P2>
</PARM>
<PARM>
<P1>789</P1>
<P2>ghi</P2>
</PARM>
.......(15times)
</dataroot>
my goal is to get the child nodes (ie p1,p2 not the values inside) and compare those names with a template.
say if p2 is not present i have to append that particular tag to that particular position in the xml file. The problem is when i use getElementsByTagNames() and store that in an array and then compare it with the template it includes dataroot and PARM as well which i don't want.
so how can i get just p1 and p2 (for upto 15times) only.
For me, the simplest approach would be to use JAXB to unmarshal and marshal, thus adding the missing elements of PARM. You need to add a few annotations in the classes for dataroot and PARM if the XML element names require different case, but then it's a matter of a few lines of code for unmarshalling and marshalling.
#XmlRootElement(name="dataroot")
#XmlType(propOrder = {"parm"})
public class Data {
#XmlElement(name="PARM")
private List<Parm> parm = new ArrayList<>();
public List<Parm> getParm(){ return parm; }
}
#XmlRootElement(name="PARM")
public class Parm {
private String p1="";
#XmlElement(name="P1")
public String getP1(){ return p1; }
public void setP1( String v ){ p1 = v; }
}
In the same package, add a file jaxb.index containing a single line:
Data
The main program:
JAXBContext jc = JAXBContext.newInstance( PACKAGE ); // dir path
Unmarshaller u = jc.createUnmarshaller();
Data data = (Data)u.unmarshal( new File( XMLIN ) ); // file path
Marshaller m = jc.createMarshaller();
Writer sw = ...; // whatever you need
m.marshal( data, sw );
Note the initialisation for field p1. This ensures that the element will show up with an empty string. A null results in omitting the element.
I'm having some issue while converting String object to JAXBElement string object where I need to set this one
This is the target method where I need to set the value
public void setData(JAXBElement<String> value) {
this.data = ((JAXBElement<String> ) value);
}
For this one, I have written code something like this
ObjectFactory factory = new ObjectFactory();
JAXBElement<ApplicationIngestionRequest> jaxbElement = new JAXBElement(
new QName(ApplicationIngestionRequest.class.getSimpleName()), ApplicationIngestionRequest.class, request);
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance(ApplicationIngestionRequest.class);
context.createMarshaller().marshal(jaxbElement, writer);
LOG.info("JAXBElement object :\n"+ writer.toString());
Unmarshaller u = context.createUnmarshaller();
JAXBElement<ApplicationIngestionRequest> o = (JAXBElement<ApplicationIngestionRequest>) u.unmarshal(new StringReader(writer));
Log gives me following output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ApplicationIngestionRequest><BranchCode></BranchCode><SourceCode>0000005511</SourceCode></ApplicationIngestionRequest>
Now when I try to set into the method as
losRequest.setData(o.toString());
It doesn't allow me to set as its expecting as JAXBElement format. Any ideas would be greatly appreciated.
As per the code snippet [setData(JAXBElement value)] , setData , accept instance of '(JAXBElement'). But here , you are trying to set a string value [losRequest.setData(o.toString())] . Here you have to set an instance of 'JAXBElement' .This could be the issue.
I am getting an 832edi file with namespaces as xml string, i need to extract elements from this xml string. So i have generated jaxb classes based on 832edi file. When i am trying to store the contents of the xml string i am getting the following exception
javax.xml.bind.JAXBElement cannot be cast to org.bam.jaxb.Transaction834
I am using the following code to parse the xml string
JAXBContext jaxbContext = JAXBContext.newInstance("org.bam.jaxb");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(im.getPayload());
Transaction834 edi = (Transaction834) unmarshaller.unmarshal(reader);
List<Loop2000> loop2000=edi.getLoop2000();
System.out.println(loop2000.get(10));
where im.getPayload() will return an xml string . Here is the fragment of the xml.
<?xml version = '1.0' encoding = 'UTF-8'?><Transaction-834 xmlns:zcha="http://www.edifecs.com/xdata/200" XDataVersion="2.0" Standard="X12" Version="V5010" GUID="{C7846049-8C91-4E59-B0BA-4B24CEE69FBB}" CreatedBy="XEngine_4016" CreatedDate="2013-09-05T12:36:12" xmlns="http://www.edifecs.com/xdata/200"><zcha:Segment-ISA><zcha:Element-I01 Offset="4" Size="2">00</zcha:Element-I01><zcha:Element-I02 Offset="7" Size="10">Authorizat</zcha:Element-I02><zcha:Element-I03 Offset="18" Size="2">00</zcha:Element-I03><zcha:Element-I04 Offset="21" Size="10">Security I</zcha:Element-I04><zcha:Element-I05 Offset="32" Size="2">01</zcha:Element-I05><zcha:Element-I06 Offset="35" Size="15">Interchange Sen</zcha:Element-I06><zcha:Element-I05_1 Offset="51" Size="2">01</zcha:Element-I05_1><zcha:Element-I07 Offset="54" Size="15">Interchange Rec</zcha:Element-I07><zcha:Element-I08 Offset="70" Size="6">130905</zcha:Element-I08><zcha:Element-I09 Offset="77" Size="4">1236</zcha:Element-I09><zcha:Element-I65 Offset="82" Size="1">*</zcha:Element-I65><zcha:Element-I11 Offset="84" Size="5">00501</zcha:Element-I11><zcha:Element-I12 Offset="90" Size="9">000000001</zcha:Element-I12><zcha:Element-I13 Offset="100" Size="1">0</zcha:Element-I13><zcha:Element-I14 Offset="102" Size="1">I</zcha:Element-I14><zcha:Element-I15 Offset="104" Size="1">\</zcha:Element-I15></zcha:Segment-ISA><zcha:Segment-GS><zcha:Element-479 Offset="110" Size="2">BE</zcha:Element-479><zcha:Element-142 Offset="113" Size="15">Application Sen</zcha:Element-142><zcha:Element-124 Offset="129" Size="15">Application Rec</zcha:Element-124><zcha:Element-373 Offset="145" Size="8">20130905</zcha:Element-373><zcha:Element-337 Offset="154" Size="6">123602</zcha:Element-337><zcha:Element-28 Offset="161" Size="1">1</zcha:Element-28><zcha:Element-455 Offset="163" Size="1">T</zcha:Element-455><zcha:Element-480 Offset="165" Size="6">005010</zcha:Element-480></zcha:Segment-GS><zcha:Segment-ST><zcha:Element-143 Offset="176" Size="3">834</zcha:Element-143><zcha:Element-329 Offset="180" Size="4">0001</zcha:Element-329></zcha:Segment-ST><zcha:Segment-BGN><zcha:Element-353 Offset="190" Size="2">00</zcha:Element-353><zcha:Element-127 Offset="193" Size="24">Reference Identification</zcha:Element-127><zcha:Element-373 Offset="218" Size="8">20130905</zcha:Element-373></zcha:Segment-BGN><zcha:Loop-1000><zcha:Segment-N1><zcha:Element-98 Offset="231" Size="2">00</zcha:Element-98><zcha:Element-93 Offset="234" Size="4">Name</zcha:Element-93></zcha:Segment-N1><zcha:Segment-N4/></zcha:Loop-1000><zcha:Segment-SE><zcha:Element-96 Offset="243" Size="1">4</zcha:Element-96><zcha:Element-329 Offset="245" Size="4">0001</zcha:Element-329></zcha:Segment-SE><zcha:Segment-GE><zcha:Element-97 Offset="254" Size="1">1</zcha:Element-97><zcha:Element-28 Offset="256" Size="1">1</zcha:Element-28></zcha:Segment-GE><zcha:Segment-IEA><zcha:Element-I16 Offset="263" Size="1">1</zcha:Element-I16><zcha:Element-I12 Offset="265" Size="9">000000001</zcha:Element-I12></zcha:Segment-IEA></Transaction-834>
Here Transaction834 is the root element of the xsd.Please could you suggest me where am i doing the mistake ?
thanks for your patience.
Most likely the class Transaction834 doesn't specify the XmlRootElement annotation (probably because it's a top-level type rather than an anonymous type).
In this case you have to use something like:
JAXBElement<Transaction834> ediElement = unmarshaller.unmarshal(new StreamSource(reader), Transaction834.class);
Transaction834 edi = ediElement.getValue();
When you aren't sure whether the result returned from JAXB will be you can use JAXBInstropector to do any unwrapping of the JAXBElement if necessary.
JAXBContext jaxbContext = JAXBContext.newInstance("org.bam.jaxb");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(im.getPayload());
Transaction834 edi = (Transaction834) JAXBIntrospector.getValue(unmarshaller.unmarshal(reader));
For More Information
http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html
I have a method like this.
public void myMethod(String xml){
...
File file=convertStringToFile(xml) // I need to convert xml string to File
object.fileDemandingMethod(file);
}
fileDemandingMethod(file) is expecting File but my input is string.
How can I get my xml string in the form of File object?
I need this for this JAXB Validation
Schema schema = schemaFactory.newSchema(new File("C:\\schema.xsd"));
unmarshaller.setSchema(schema );
Since you can also work with a StreamSource, you can construct a javax.xml.transform.Source from the String with:
new StreamSource(new StringReader(xml))
You don't need a file, you surely don't want the overhead of writing to a file.
setSchema() can take any object implementing javax.xml.transform.Source
StreamSource is one such class, and that can be constructed from an InputStream or Reader.
Reader reader = new StringReader(myString);
Source source = new StreamSource(reader);
unmarshaller.setSchema(spource);
The best way to do that is to create/generate a class in e.g. Employee
from your Schema (C:\Schema.xsd)
After that the rest is easy
JAXBContext context = JAXBContext.newInstance(Employee.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Employee object = new Employee();
object.setCode("CA");
object.setName("Cath");
object.setSalary(300);
m.marshal(object, new FileOutputStream("result.xml"));
}
I've got a database full of objects, along with user-defined properties. For example:
class Media {
String name;
String duration;
Map<String,String> custom_tags;
}
Media:
Name: day_at_the_beach.mp4
Length: 4:22
Custom Tags:
Videographer: Charles
Owner ID #: 17a
Our users can come up with their own custom properties to attach to media, and fill in values accordingly. However, when I try to marshall the object into XML, I run into problems:
<media>
<name>day_at_the_beach.mp4</name>
<length>4:22</length>
<custom_tags>
<Videographer>Charles</videographer>
<Owner_ID_#>17a</Owner_ID_#>
</custom_tags>
</media>
Owner_ID_# is an illegal tag name in XML, because it contains a # so JAXB throws an org.w3c.dom.DOMException: INVALID_CHARACTER_ERR: An invalid or illegal XML character is specified.
I know that the preferred, correct way to solve this problem would be to reformat the xml to something along the lines of:
<custom_tags>
<custom_tag>
<name>Owner ID #</name>
<value>17z</value>
</custom_tag>
</custom_tags>
However, I'm required to return the former, invalid XML, to maintain legacy behavior from a previous, less-picky implementation of the code. Is there any way to tell JAXB not to worry about the illegal XML character, or am I going to be stuck doing a string replace before/after encoding? My current implementation is simply:
public static <T> String toXml(Object o, Class<T> z) {
try {
StringWriter sw = new StringWriter();
JAXBContext context = JAXBContext.newInstance(z);
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(o, sw);
return sw.toString();
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
I built a XmlAdapter for this specific object, then:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
document.setStrictErrorChecking(false); // <--- This one. This accomplished it.