Take off namespace from Jaxb fields - java

I want to know how to type only one time namespace in jabx, because in every fields i need to put the namespace.
The code below show it.
#XmlRootElement(name = "nfeProc", namespace = "http://www.portalfiscal.inf.br/nfe")
#XmlAccessorType(XmlAccessType.FIELD)
class NFeProc {
#XmlElement(name = "NFe", namespace = "http://www.portalfiscal.inf.br/nfe")
private NFe nfe;
#XmlAttribute(name = "versao")
private String versao;
public NFe getNfe() {
return nfe;
}
public void setNfe(NFe nfe) {
this.nfe = nfe;
}
public String getVersao() {
return versao;
}
public void setVersao(String versao) {
this.versao = versao;
}
}
I just wanna to put one time.
Thanks

You can set it at the package level using the #XmlSchema annotation. By setting element form default to be qualified, all elements without a namespace specified via an annotation will belong to the given namespace.
package-info.java
#XmlSchema(
namespace = "http://www.portalfiscal.inf.br/nfe",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html

Related

How to JAXB-marshall JavaFX Property classes when class is XmlAccessType.NONE?

I would like a Java class containing JavaFX Property objects (DoubleProperty, StringProperty, IntegerProperty) to be written into an XML file using JAXB's marshall() method call. However, this class contains lots of data that I do not want written into the XML. This class is expected to be modified by developers often, so I prefer to mark the class "#XmlAccessorType(XmlAccessType.NONE)" and then add #XmlElement tags to anything I want written into the XML (so a developer doesn't add some new member variables into this class and then accidentally alter the XML file's format).
I see examples such as http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html, but none of them have "#XmlAccessorType(XmlAccessType.NONE) " for their main class. When I add this tag to my class, I get either runtime Exceptions (because JAXB cannot create a new object) or an empty XML tag in the output (because JAXB created a default object of ome kind but didn't put the desired value into it). I have experimentes with dozens of #Xml* tag combinations but I cannot find one that works.
Note that I cannot annotate any of the DoubleProperty/SimpleDoubleProperty classes because they are part of the standard Java API.
Here is a code example, demonstrating the troubles with getting the bankAccountBalance property into the XML file. (you can ignore the other data - I started with Blaise Doughan's code as a starting-point for this example).
package Demo2;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
public class Demo2 {
public static void main(String[] args) throws Exception {
Customer customer = new Customer();
Address address = new Address();
address.setStreet("1 A Street");
customer.setContactInfo(address);
customer.setBankAccountBalance(123.45);
JAXBContext jc = JAXBContext.newInstance(Customer.class, Address.class, PhoneNumber.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(customer, System.out);
}
}
abstract class ContactInfo {
}
class Address extends ContactInfo {
private String street;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
class PhoneNumber extends ContactInfo {
}
#XmlRootElement
#XmlAccessorType(XmlAccessType.NONE)
class Customer {
#XmlElement
private ContactInfo contactInfo;
// This tag runs OK but always outputs an empty XML tag ("<bankAccountBalance/>") regardless of the real value.
// #XmlElement
// This tag causes the following error:
// Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
// Invalid #XmlElementRef : Type "class javafx.beans.property.DoubleProperty" or any of its subclasses are not known to this context.
// #XmlElementRef
// This tag causes the following error:
// Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
// Invalid #XmlElementRef : Type "class javafx.beans.property.SimpleDoubleProperty" or any of its subclasses are not known to this context.
// #XmlElementRef(type=SimpleDoubleProperty.class)
private DoubleProperty bankAccountBalance;
public Customer() {
bankAccountBalance = new SimpleDoubleProperty(0);
}
public ContactInfo getContactInfo() {
return contactInfo;
}
public void setContactInfo(ContactInfo contactInfo) {
this.contactInfo = contactInfo;
}
public double getBankAccountBalance() {
return bankAccountBalance.get();
}
public void setBankAccountBalance(double bankAccountBalance) {
this.bankAccountBalance.set(bankAccountBalance);
}
}
Simply annotate the getter and not the DoubleProperty field, which nicely bypasses the javafx class. Don't forget to setValue so you see the result.
#XmlElement
public double getBankAccountBalance() {
return bankAccountBalance.get();
}

JAXB Unmarshal a list of objects

I have the following XML that I am trying to unmarshal:
<ListOfYear>
<Requests/>
<Payload>
<Year>
<Value>2013</Value>
</Year>
<Year>
<Value>2012</Value>
</Year>
<Year>
<Value>2011</Value>
</Year>
<Year>
<Value>2010</Value>
</Year>
<Year>
<Value>2009</Value>
</Year>
<Year>
<Value>2008</Value>
</Year>
</Payload>
</ListOfYear>
My java class looks like this:
#XmlRootElement(name = "ListOfYear")
public class YearOutput {
#XmlElementWrapper(name = "Payload")
#XmlElement(name = "Year")
private ArrayList<Year> Payload;
public ArrayList<Year> getPayload() {
return Payload;
}
public void setPayload(ArrayList<Year> payload) {
Payload = payload;
}
}
Payload should contain a list of year objects:
#XmlRootElement(name = "Year")
#XmlAccessorType(XmlAccessType.FIELD).
public class Year {
#XmlElement(name = "Value")
int Value;
public int getValue() {
return Value;
}
public void setValue(int value) {
Value = value;
}
}
I am unmarshaling the XML with the following code:
String r = response.getEntity(String.class);
JAXBContext jaxbContext = JAXBContext.newInstance(YearOutput.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
YearOutput output = (YearOutput) unmarshaller.unmarshal(new StringReader(r));
I get an output object back just fine, the payload object is always null. I have tried several different approaches with my XML annotation and have not been able to get anything to work. Any help would be much appreciated.
EDIT
I thought the name space was inconsequential so I didn't post that part of the code. But #Blaise Doughan suggested I marshal my model and it appears my namespace may be causing an issue...
Here is the full XML that I need:
<ListOfYear xmlns="http://something.com/">
<Requests/>
<Payload>
<Year>
<Value>2013</Value>
</Year>
<Year>
<Value>2012</Value>
</Year>
<Year>
<Value>2011</Value>
</Year>
<Year>
<Value>2010</Value>
</Year>
<Year>
<Value>2009</Value>
</Year>
<Year>
<Value>2008</Value>
</Year>
</Payload>
</ListOfYear>
Here is my full model:
#XmlRootElement(name = "ListOfYear", namespace = "http://something.com/")
public class YearOutput {
#XmlElementWrapper(name = "Payload")
#XmlElement(name = "Year")
private ArrayList<Year> Payload;
public ArrayList<Year> getPayload() {
return Payload;
}
public void setPayload(ArrayList<Year> payload) {
Payload = payload;
}
}
Now when I marshal my model I am getting:
<?xml version="1.0" encoding="UTF-8"?>
<ns2:ListOfYear xmlns:ns2="https://something.com/">
<Payload>
<Year>
<Value>2008</Value>
</Year>
</Payload>
</ns2:ListOfYear>
So what am I doing wrong with my namespace?
EDIT
After adding package-info.java everything works perfect!
#XmlSchema(
namespace = "https://something.com/",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Your annotations need to go on the property (get or set method) instead of the field. If you wish to have them on the field (instance variable), the you need to annotate your class with #XmlAccessorType(XmlAccessType.FIELD), like you have on your Year class.
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
UPDATE
Instead of specifying the namespace on #XmlRootElement you will need to leverage a package level #XmlSchema annotation (on a class called package-info) to match the namespace qualification.
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
Try adding a / to the ending Payload tag.
A it's already mentioned, the XML file should contain
</Payload>
instead of
<Payload>
in the last but one line
#XmlElement should be above attribute but not getter in Year class:
#XmlElement int Value;
The element name in XmlElement annotation on getValue is missing. JAXB default behavior is that getValue means 'value' element, not 'Value'. Add the annotation #XmlElement(name="Value")
Fix it as in your other code
#XmlRootElement(name = "Year")
public static Year {
...
#XmlElement(name="Value")
public int getValue() {
return Value;
}
...
}
If you also marshal I recommend to add #XmlAccessorType(XmlAccessType.NONE) to the classes to prevent adding both 'value' and 'Value' elements.
See full working code at package 'wicketstuff/enteam/wicket/examples14/mixed' on
https://repo.twinstone.org/projects/WISTF/repos/wicket-examples-1.4/browse/
Also a test that log into console your XML and parse it back is provided in 'YearOutputTest'

any way to convert xml to object in java?

I am trying to use a XML and access to all fields and data on an easy way, so, I decided to use JaxB , but I have no idea how to create all the classes for the objects, I tried manually like this.
#XmlRootElement(name = "Response")
public class Response {
#XmlElement(ns = "SignatureValue")
String signatureValue;
}
But I get an error on #XmlElement saying the annotation is disallowed for this location...
I checked other posts and they work great if I have something like Hellw but doesnt work with more complex formats, an example of first part of mine is like this
<?xml version="1.0" encoding="UTF-8"?><DTE xsi:noNamespaceSchemaLocation="http://www.myurl/.xsd" xmlns:gs1="urn:ean.ucc:pay:2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
any idea how to do all this??
Thanks in advance
EDIT:
I forgot to say, the XML is actually a String with the entire XML.
The #XmlElement annotation is valid on a field. If you have a corresponding property then you should annotate the class with #XmlAccessorType(XmlAccessType.FIELD) to avoid a duplicate mapping exception.
Java Model
Annotating the Field
#XmlRootElement(name = "Response")
#XmlAccessorType(XmlAccessType.FIELD)
public class Response {
#XmlElement(name = "SignatureValue")
String signatureValue;
public String getSignatureValue() {
return signatureValue;
}
public void setSignatureValue(String signatureValue) {
this.signatureValue = signatureValue;
}
}
Annotating the Property
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "Response")
public class Response {
String signatureValue;
#XmlElement(name = "SignatureValue")
public String getSignatureValue() {
return signatureValue;
}
public void setSignatureValue(String signatureValue) {
this.signatureValue = signatureValue;
}
}
For More Information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
Demo Code
Below is some demo code that reads/writes the XML corresponding to your Response class.
Demo
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Response.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum19713886/input.xml");
Response response = (Response) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(response, System.out);
}
}
input.xml/Output
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<SignatureValue>Hello World</SignatureValue>
</Response>

Can't see namespace prefixes in XML file

I marshall some object but the problem is JAXB writes default namespace prefixes instead of predefined ones. Is there any idea what can cause this problem?
What I expect to see;
<xbrli:entity>
....
What I got;
<ns3:entity>
....
I generated all classes(including package-infos)
example package-info;
#javax.xml.bind.annotation.XmlSchema(namespace = "http://www.xbrl.org/2003/instance",
xmlns = {
#XmlNs(namespaceURI = "http://www.xbrl.org/2003/instance", prefix = "xbrli2")
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.xbrl._2003.instance;
import javax.xml.bind.annotation.XmlNs;
JAXB (JSR-222) does not offer a standard way to specify the namespace prefix used.
Extension - NamespacePrefixMapper
For the JAXB reference implementations and recent versions of EclipseLink JAXB (MOXy) you can use the NamespacePrefixMapper extension to control the namespace prefixes used.
MyNamespaceMapper
import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
//import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
public class MyNamespaceMapper extends NamespacePrefixMapper {
private static final String FOO_PREFIX = ""; // DEFAULT NAMESPACE
private static final String FOO_URI = "http://www.example.com/FOO";
private static final String BAR_PREFIX = "bar";
private static final String BAR_URI = "http://www.example.com/BAR";
#Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
if(FOO_URI.equals(namespaceUri)) {
return FOO_PREFIX;
} else if(BAR_URI.equals(namespaceUri)) {
return BAR_PREFIX;
}
return suggestion;
}
#Override
public String[] getPreDeclaredNamespaceUris() {
return new String[] { FOO_URI, BAR_URI };
}
}
Specifying the NamespacePrefixMapper
Below is an example of how the NamespacePrefixMapper is set on the Marshaller.
Marshaller m = ctx.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
try {
m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", new MyNamespaceMapper());
//m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespaceMapper());
} catch(PropertyException e) {
// In case another JAXB implementation is used
}
Extension - Leveraging #XmlSchema
EclipseLink JAXB (MOXy) and recent versions of the JAXB reference implementation will use the namespace prefixes defined on the package level #XmlSchema annotation.
#XmlSchema(
elementFormDefault=XmlNsForm.QUALIFIED,
namespace="http://www.example.com/FOO",
xmlns={
#XmlNs(prefix="", namespaceURI="http://www.example.com/FOO")
#XmlNs(prefix="bar", namespaceURI="http://www.example.com/BAR")
}
)
package blog.prefix;
import javax.xml.bind.annotation.*;
For More Information
http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html

Jaxb: Unmarshalling xml with multiple namespaces in same package

I'm new to using namespaces in xml so I am kind of confused and would like some clarification. I have a java service where I am receiving xml documents with many different namespaces and while i got it working, I feel like I must have done something wrong so I want to check. In my package-info.java I have my schema annotation such as:
#javax.xml.bind.annotation.XmlSchema(
xmlns={
#javax.xml.bind.annotation.XmHS(prefix="train", namespaceURI="http://mycompany/train"),
#javax.xml.bind.annotation.XmHS(prefix="passenger", namespaceURI="http://mycompany/passenger")
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm=QUALIFIED
)
I have a Train.java annotated on the class level with:
#XmlRootElement(name="Train", namespace="http://mycompany/train")
and each field in the class annotated with:
#XmlElement(name="Color") for example
Train contains a List of Passenger(s) so there's a property
private Set<Passenger> passengers;
and this collection is annotated with:
#XmlElementWrapper(name="Passengers")
#XmlElements(#XmlElement(name="Passenger", namespace="http://mycompany/passenger"))
Then within Passenger.java the class itself is annotated with:
#XmlElement(name="Passenger", namespace="http://mycompany/passenger")
Finally for individual fields within Passenger.java, they are annotated like this:
#XmlElement(name="TicketNumber", namespace="http://mycompany/passenger")
So when I have an xml that looks like:
<train:Train>
<train:Color>Red</train:Color>
<train:Passengers>
<train:Passenger>
<passenger:TicketNumber>T101</passenger:TicketNumber>
</train:Passenger>
</train:Passengers>
</train:Train>
Now I unmarshal this xml I received and Train's Color property is set and Passenger's TicketNumber property is set. But I don't know why I need to add the namespace url on the XmlElement annotation on TicketNumber for that to work but I didn't need to do so for the Color property on Train. If I remove the namespace attribute from the XmlElement annotation on TicketNumber, the value from the xml wont get mapped to the object unless I also remove the namespace prefix from the xml request. I feel like since I've got the namespace attribute defined on the XmlRootElement for Passenger, I shouldn't need to do that for every single field in the class as well just like I didn't have to for Train so I am assuming I must have setup something wrong. Can someone point me in the right direction? Thanks!
Below is an explanation of how namespaces work in JAXB (JSR-222) based on your model.
JAVA MODEL
package-info
Below is a modified version of your #XmlSchema annotation. It contains some key information:
namespace - The default namespace that will be used to qualify global elements (those corresponding to #XmlRootElement and #XmlElementDecl annotations (and local elements based on the elementFormDefault value) that don't have another namespace specified.
elementFormDefault by default only global elements are namespace qualified but by setting the value to be XmlNsForm.QUALIFIED all elements without an explicit namespace specified will be qualified with the namespace value.
xmlns is the preferred set of prefixes that a JAXB impl should use for those namespaces (although they may use other prefixes).
#XmlSchema(
namespace="http://mycompany/train",
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns={
#XmlNs(prefix="train", namespaceURI="http://mycompany/train"),
#XmlNs(prefix="passenger", namespaceURI="http://mycompany/passenger")
}
)
package forum15772478;
import javax.xml.bind.annotation.*;
Train
Since all the elements corresponding to the Train class correspond to the namespace specified on the #XmlSchema annotation, we don't need to specify any namespace info.
Global Elements - The #XmlRootElement annotation corresponds to a global element.
Local Elements - The #XmlElementWrapper and #XmlElement annotations correspond to local elements.
package forum15772478;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement(name="Train")
public class Train {
private List<Passenger> passengers;
#XmlElementWrapper(name="Passengers")
#XmlElement(name="Passenger")
public List<Passenger> getPassengers() {
return passengers;
}
public void setPassengers(List<Passenger> passengers) {
this.passengers = passengers;
}
}
Passenger
If all the elements corresponding to properties on the Passenger class will be in the http://mycompany/passenger namespace, then you can use the #XmlType annotation to override the namespace from the #XmlSchema annotation.
package forum15772478;
import javax.xml.bind.annotation.*;
#XmlType(namespace="http://mycompany/passenger")
public class Passenger {
private String ticketNumber;
#XmlElement(name="TicketNumber")
public String getTicketNumber() {
return ticketNumber;
}
public void setTicketNumber(String ticketNumber) {
this.ticketNumber = ticketNumber;
}
}
Alternatively you can override the namespace at the property level.
package forum15772478;
import javax.xml.bind.annotation.*;
public class Passenger {
private String ticketNumber;
#XmlElement(
namespace="http://mycompany/passenger",
name="TicketNumber")
public String getTicketNumber() {
return ticketNumber;
}
public void setTicketNumber(String ticketNumber) {
this.ticketNumber = ticketNumber;
}
}
DEMO CODE
The following demo code can be run to prove that everything works:
Demo
package forum15772478;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Train.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum15772478/input.xml");
Train train = (Train) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(train, System.out);
}
}
input.xml/Output
In the XML below I have added the necessary namespace declarations that were missing from the XML document in your question.
<train:Train
xmlns:train="http://mycompany/train"
xmlns:passenger="http://mycompany/passenger">
<train:Color>Red</train:Color>
<train:Passengers>
<train:Passenger>
<passenger:TicketNumber>T101</passenger:TicketNumber>
</train:Passenger>
</train:Passengers>
</train:Train>
FOR MORE INFORMATION
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html

Categories