Why check for root element is required in Jaxb2Marshaller? - java

I am using Jaxb2Marshaller to marshal Java beans through spring #ResponseBody annotation. For JSON marshaling was working fine. But for xml I was continuously getting HTTP 406 response. Little bit digging in Jaxb2Marshaller class reveals it checks for #XmlRootElement for bounded classes (see below snippet).
While generating java code from xsd my pojo does not contain #XmlRootElement and proper message converter was not identified by AnnotationMethodHandlerAdapter and finally result in 406.
Instead of auto generating java code from xsd I have created my own pojo class and used #XmlRootElement. Then marshaling works fine.
I want to understand why it is important of having #XmlRootElement check for bounded classes. Or any way to specify element as #XmlRootElement in xsd.
Code snippet from Jaxb2Marshaller:
public boolean supports(Class clazz) {
return supportsInternal(clazz, true);
}
private boolean supportsInternal(Class<?> clazz, boolean checkForXmlRootElement) {
if (checkForXmlRootElement && clazz.getAnnotation(XmlRootElement.class) == null) {
return false;
}
if (clazz.getAnnotation(XmlType.class) == null) {
return false;
}
if (StringUtils.hasLength(getContextPath())) {
String className = ClassUtils.getQualifiedName(clazz);
int lastDotIndex = className.lastIndexOf('.');
if (lastDotIndex == -1) {
return false;
}
String packageName = className.substring(0, lastDotIndex);
String[] contextPaths = StringUtils.tokenizeToStringArray(getContextPath(), ":");
for (String contextPath : contextPaths) {
if (contextPath.equals(packageName)) {
return true;
}
}
return false;
}
else if (!ObjectUtils.isEmpty(classesToBeBound)) {
return Arrays.asList(classesToBeBound).contains(clazz);
}
return false;
}
Edit:
Blaise answer helped me solve #XmlRootElement problem. But still if someone has any information about why check for XmlRootElement is required, will be a good info.

Why the #XmlRootElement Annotation is Checked For
Spring requires a root element when marshalling the object to XML. JAXB provides two mechanisms to do this:
The #XmlRootElement annotation
Wrapping the root object in an instance of JAXBElement.
Since the object is not wrapped in a JAXBElement Spring is ensuring that the other condition is met.
How Generate an #XmlRootElement
JAXB will generate an #XmlRootElement annotation for all global elements in an XML schema. The following will cause an #XmlElement:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="foo">
<xsd:complexType>
...
</xsd:complextType>
</xsd:element>
</xsd:schema>
When #XmlRootElement is not Generated
An #XmlRootElement annotation will not be generated for global types.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="foo" type="foo"/>
<xsd:complexType name="foo">
...
</xsd:complexType>
</xsd:schema>
Instead the global element(s) associated with the global types are captured in the ObjectFactory class (annotated with #XmlRegistry) in the form of #XmlElementDecl annotations. These annotations
package generated;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
#XmlRegistry
public class ObjectFactory {
private final static QName _Foo_QNAME = new QName("", "foo");
public Foo createFoo() {
return new Foo();
}
#XmlElementDecl(namespace = "", name = "foo")
public JAXBElement<Foo> createFoo(Foo value) {
return new JAXBElement<Foo>(_Foo_QNAME, Foo.class, null, value);
}
}
The #XmlElementDecl annotation provides similar information as #XmlRootElement and could be used for unmarshal operations. JAX-RS implementations probably do not leverage #XmlElementDecl however since marshal operations would require the object to be wrapped in a JAXBElement object to provide the root element name/namespace.

it's an known issue:
https://jira.springsource.org/browse/SPR-7931
"Checking for #XmlRootElement annotation should be made optional in Jaxb2Marshaller"

You can use JaxbElement for classes that does not have #XmlRootElement annotation. #XmlRootElement annotation is placed only to non referenced top level objects if you are generating your code from xsd
Edit
See #Blaise Doughan answer.
#XmlRootElement will be placed only if there is no reference to that type in another type.

Related

How to get only the required tags from XML using JAXB

If I have a XML with huge header tags but I need to get only the list of objects dppc and child object ppc. Please advise how to get the values only from the node dppc.
<SOAPENV:Envelope xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAPENV:Body>
<rpc:distributeObject xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rpc="http://company.xxx.com/Distributed/Object">
<standardHeader xmlns="http://wsi.nat.bat.com/2005/06/StandardHeader/">
<dppc>
<ppc>
<productName>Export1</productName>
</ppc>
<ppc>
<productName>Export2</productName>
</ppc>
</dppc>
</standardHeader>
</rpc:distributeObject>
</SOAPENV:Body>
Please find the below code to unmarshal it
String example =
"<SOAPENV:Envelope xmlns:SOAPENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SOAPENV:Body><rpc:distributeObject xmlns:SOAPENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:rpc=\"http://company.xxx.com/Distributed/Object\"><standardHeader xmlns=\"http://wsi.nat.bat.com/2005/06/StandardHeader/\"><dppc><ppc><productName>Export1</productName></ppc><ppc><productName>Export2</productName></ppc></dppc></standardHeader></rpc:distributeObject></SOAPENV:Body>";
message = MessageFactory.newInstance().createMessage(null,
new ByteArrayInputStream(example.getBytes()));
Unmarshaller unmarshaller = JAXBContext.newInstance(Dppc.class).createUnmarshaller();
Dppc dppc = (Dppc)unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument());
dppc.getPPC();
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
class Dppc{
#XmlPath("rpc:distributeObject/standardHeader/dppc")
private List<PPC> ppC;
public List<PPC> getPPC() {
return ppC;
}
public void setPPC(List<PPC> ppC) {
this.ppC= ppC;
}
}
class PPC {
String productName;
//getter & setters;
}
I have created a package-info file also, but it is not working.
With the pure Implementation of JAXB this is not possible because JAXB don't support XPath by default.
One possible solution is to use EclipseLink(MOXy) which supports the #XmlPath Annotation.
With that annotation it is possible to define the Path of an Element inside the XML. For your XML to read only the dppc Elements and childs your class would look something like this (not tested):
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement(name="SOAPENV:Body")
public class MainElement{
#XmlPath("rpc:distributeObject/standardHeader/dppc")
DPPC dppc;
//getter and setters
}
Same for the dppc and ppc class.
The Link to MOXy give you some nice examples.

JAXB empty element unmarshalling

The problem is in the following :
I get the soap response with empty element inside (e.g. ... <someDate /> ... )
and as a result exception is being throwed when JAXB wants to parse this element
instead to set the appropriate field with null value.
How to configure JAXB to treat empty elements as null ?
Can we do this with JAXB only (not using some third-party workarounds)
Base Problem
Empty String is not a valid value for the xsd:date type. To be valid with the XML schema an optional element should be represented as an absent node.,
Why the Base Problem is Impacting You
All JAXB implementations will recognize that empty String is not a valid value for xsd:date. They do this by reporting it to an instance of ValidationEventHandler. You can see this yourself by doing the following:
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setEventHandler(new ValidationEventHandler() {
#Override
public boolean handleEvent(ValidationEvent event) {
System.out.println(event);
return true;
}
});
The implementation of JAX-WS you are using, leverages EclipseLink MOXy as the JAXB provider. And in the version you are using MOXy will by default throw an exception when a ValidationEvent of severity ERROR is encountered instead of FATAL_ERROR like the reference implementation. This has since been fixed in the following bug:
http://bugs.eclipse.org/369994
Work Around
If you are using the JAXB APIs directly you could simply override the default ValidationEventHandler. In a JAX-WS environment a XmlAdapter can be used to provide custom conversion logic. We will leverage an XmlAdapter to override how the conversion to/from Date is handled.
XmlAdapter (DateAdapter)
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class DateAdapter extends XmlAdapter<String, Date>{
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
#Override
public Date unmarshal(String v) throws Exception {
if(v.length() == 0) {
return null;
}
return dateFormat.parse(v);
}
#Override
public String marshal(Date v) throws Exception {
if(null == v) {
return null;
}
return dateFormat.format(v);
}
}
Java Model (Root)
The XmlAdapter is referenced using the #XmlJavaTypeAdapter annotation. If you wish this XmlAdapter to apply to all instances of Date you can register it at the package level (see: http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html).
import java.util.Date;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
#XmlSchemaType(name = "date")
#XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class)
private Date abc;
#XmlSchemaType(name="date")
#XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class)
private Date qwe;
}
Demo Code
Below is a standalone example you can run to see that everything works.
jaxb.properties
In a standalone example to use MOXy as your JAXB provider you need to include a file called jaxb.propeties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
input.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<abc></abc>
<qwe>2013-09-05</qwe>
</root>
Demo
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum18617998/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Output
Note that in the marshalled XML the Date field that was null was marshalled as an absent element (see: http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html).
<?xml version="1.0" encoding="UTF-8"?>
<root>
<qwe>2013-09-05</qwe>
</root>

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

Is it possible to programmatically configure JAXB?

Say I have two JavaBeans Person and Address.
If I create a list of Person objects, I'd like to marshal to something like this:
<persons>
<person>...</person>
</persons>
It's possible to use the technique described here:
Using JAXB to unmarshal/marshal a List<String>
By annotating JaxbList with #XmlRootElement(name = "persons") and #XmlElement(name = "person"), then it's possible to marshal to the XML above.
But, it'd be nice to be able to reuse the same JaxbList<T> class to also marshal a list of Address objects. And in reality, I will have many other types of beans. I can go with something like:
<list>
<item xsi:type="person" xmlns:xsi="http://www.w2.org/2001/XmlSchema-instance"></item>
</list>
But, ideally, it'd be nice to have it replace "list" with the plural version of class name and "item" with the class name.
So, is it possible to programmatically configure the JaxbContext or something during runtime and essentially set the value of the name inside #XmlRootElement and #XmlElement?
Or any other way to get this working without having to write a separate implementation of JaxbList for every bean type? Maybe XmlJavaTypeAdapter can achieve this sort of thing?
Update
#Blaise Doughan's solution accepted below works great. For my use case, I needed to go straight from Java object to XML, here's what worked (note this is not my full implementation, it's sort of just pseudo code for demonstration):
//JAXBContext is thread safe and so create it in constructor or
//setter or wherever:
...
JAXBContext jc = JAXBContext.newInstance(Wrapper.class, clazz);
...
public String marshal(List<T> things, Class clazz) {
//configure JAXB and marshaller
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//Create wrapper based on generic list of objects
Wrapper<T> wrapper = new Wrapper<T>(things);
JAXBElement<Wrapper> wrapperJAXBElement = new JAXBElement<Wrapper>(new QName(clazz.getSimpleName().toLowerCase()+"s"), Wrapper.class, wrapper);
StringWriter result = new StringWriter();
//marshal!
m.marshal(wrapperJAXBElement, result);
return result.toString();
}
You could create a generic Wrapper object like the following:
Wrapper
You could create a generic wrapper class with a List property annotated with #XmlAnyElement(lax=true). The type of the object used to populate this list will be based on its root element (see: http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html).
package forum13272288;
import java.util.*;
import javax.xml.bind.annotation.XmlAnyElement;
public class Wrapper<T> {
private List<T> items = new ArrayList<T>();
#XmlAnyElement(lax=true)
public List<T> getItems() {
return items;
}
}
Address
You will need to annotate the possible contents of the list with #XmlRootElement.
package forum13272288;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Address {
}
Person
package forum13272288;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Person {
}
Demo
The demo code below demonstrates how to use the Wrapper class. Since the root element can be different you will need to specify that you want to unmarshal to the wrapper class. Alternatively you could leverage the #XmlElementDecl annotation to associate multiple root elements with the wrapper class (see: http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html).
package forum13272288;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Wrapper.class, Person.class, Address.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StreamSource personsXML = new StreamSource("src/forum13272288/persons.xml");
JAXBElement<Wrapper> wrapper1 = unmarshaller.unmarshal(personsXML, Wrapper.class);
marshaller.marshal(wrapper1, System.out);
StreamSource addressesXML = new StreamSource("src/forum13272288/addresses.xml");
JAXBElement<Wrapper> wrapper2 = unmarshaller.unmarshal(addressesXML, Wrapper.class);
marshaller.marshal(wrapper2, System.out);
}
}
Output
Below is the output from running the demo code. The files persons.xml and addresses.xml look just like there corresponding output.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persons>
<person/>
<person/>
</persons>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addresses>
<address/>
<address/>
</addresses>
For More Information
http://blog.bdoughan.com/2012/11/creating-generic-list-wrapper-in-jaxb.html

Jaxb generated xml - problem with root element prefix

I am trying to generate xml using jaxb. I created xsd and generated java classes.
But when I generate xml, I am geeting prefix ns2 to the root tag, which I don't want.
ex: I want root tag to be
<report>
<id>rep 1</id>
</report>
, But getting as
<ns2:report>
....
</ns2:report>
In the generated java class, I gave annotation as #XmlRootElement(name="report",namespace="urn:report")
Can some one pls help
If this is your class:
package example;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="report",namespace="urn:report")
public class Root {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Then it makes sense that there is a prefix on the root element, because you have specified that the "root" element is namespace qualified and the "id" element is not.
<ns2:report xmlns:ns2="urn:report">
<id>123</id>
</ns2:report>
If you add a package-info class to your model, you can leverate the #XmlSchema annotation:
#XmlSchema(
namespace = "urn:report",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Then the JAXB implementation may choose to leverage the default namespace, but note now all of the elements are namespace qualified which may or may not match your XML schema:
<report xmlns="urn:report">
<id>123</id>
</report>
For more information on JAXB and namespaces see:
http://bdoughan.blogspot.com/2010/08/jaxb-namespaces.html
Take a look at this answer. It describes how to use a SAX Filter to remove any namespace.
The blog entry Customizing JAXB shows the alternatives provided by implementing a PreferredMapper . Unfortunately it explains, that is not possible to fully suppress namespaces.
Use this attribute in your root element of your schema: elementFormDefault="qualified"
So for instance:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
Somehow the accepted answer did not work for me. I got success when I found solutions in some related stockOverflow questions involving DelegatingXMLStreamWriter from cxf and a filter, NoNamesWriter. The implementation I used with NoNamesWriter:
public class NoNamesWriter extends DelegatingXMLStreamWriter
{
#Override
public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
delegate.writeStartElement("", local, uri);
}
public static XMLStreamWriter filter(FileOutputStream fileOutputStream) throws XMLStreamException {
return new NoNamesWriter(XMLOutputFactory.newInstance().createXMLStreamWriter(fileOutputStream));
}
public NoNamesWriter(XMLStreamWriter writer) {
super(writer);
}
}
Invoke the same as described here, like:
xmlmarshaller.marshal(xc, NoNamesWriter.filter(new FileOutputStream(outfile, false));

Categories