JAXB: unmarshal from XML subtree? - java

My JAVA program uses an internal class hierarchy which resembles GPX 1.1, but is not identical. since rewriting it to conform 1:1 to GPX is a huge effort, I'd like to change it bit by bit, i.e. reading the <metadata> subtree into the Class MetadataType as generated with xjc from the XSD file
the remaining GPX file is parsed with DOM, until <metadata> shows up:
private void parseMetadata(MetadataType metadata, Element element) throws JAXBException {
try {
System.out.println(element.getNodeName()); // output: metadata
JAXBContext context = JAXBContext.newInstance(MetadataType.class);
javax.xml.bind.Unmarshaller u = context.createUnmarshaller();
JAXBElement<MetadataType> meta = u.unmarshal(element, MetadataType.class);
metadata = meta.getValue();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(metadata.getName()); // NULL
System.out.println(metadata.getAuthor().getName()); // NULL
}
throws
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"metadata"). Expected elements are <{http://www.topografix.com/GPX/1/1}gpx>
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:647)
the class looks like this:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "metadataType", propOrder = {
"name",
"desc",
"author",
"copyright",
"link",
"time",
"keywords",
"bounds",
"extensions"
})
#XmlRootElement(name = "metadata")
public class MetadataType {
protected String name = "";
protected String desc = "";
protected PersonType author;
protected CopyrightType copyright = new CopyrightType();
protected List<LinkType> link = new ArrayList<LinkType>();
#XmlSchemaType(name = "Date")
protected Date time;
protected String keywords = "";
protected BoundsType bounds = new BoundsType();
protected ExtensionsType extensions = new ExtensionsType();
[...]
}
is it possible to unmarshal from an XML subtree; and if yes, what am I doing wrong?
UPDATE/1:
thanks to lexicore, I'm a step further: element definitely contains the metadata node, #XmlRootElement is set, unmarshaling now with unmarshal(element, MetadataType.class).
unmarshaling works, but the content of the objects is empty. I wonder if I run into some namespace troubles here?
the package com.topografix.gpx._1._1 contains a package-info.java, generated by xjc:
#javax.xml.bind.annotation.XmlSchema(namespace = "http://www.topografix.com/GPX/1/1", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.topografix.gpx._1._1;
here's one of the test files:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1"
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
xmlns:wptx1="http://www.garmin.com/xmlschemas/WaypointExtension/v1"
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
creator="GPSMAP 62s" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1
http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas /GpxExtensions/v3
http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/WaypointExtension/v1
http://www8.garmin.com/xmlschemas/WaypointExtensionv1.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1
http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
<metadata>
<link href="http://www.garmin.com">
<text>Garmin International</text>
</link>
<time>2014-01-01T22:26:49Z</time>
</metadata>
[...]
UPDATE/2: the namespace/package name is right. If the namespace is set to (i.e.) "foobar", the following exception is thrown:
javax.xml.bind.JAXBException: Provider com.sun.xml.internal.bind.v2.ContextFactory could not be instantiated:
javax.xml.bind.JAXBException: "foobar" doesnt contain ObjectFactory.class or jaxb.index
when initialized as before, the exception is not thrown, meaning that the namespace is correct AND the ObjectFactory.class is found.
String contextPath = MetadataType.class.getPackage().getName();
JAXBContext context = JAXBContext.newInstance(contextPath);
So, the namespace is correct, but somehow the "link" to the MetadataType class is missing?

I guess you have a few problems here:
Your MetadataType does not have the #XmlRootElement. So JAXB does not know which element is supposed to match it.
You want to unmarshal partially, but you're unmarshalling (I guess) the whole document.
What you could try:
Try unmarshalling a specific class from the specific node using the unmarshal(node, class) method
From your stack trace, you try to unmarshal gpx:gpx element, not the metadata element. You have to go deeper
You have to overtake package-info.java as well (or provide namespaces in your MetadataType, otheriwse you're missing namespaces
See this answer about partial unmarshalling.

Related

Jaxb Unmarshalling java files from XML file with namespace

This is my XML
<?xml version="1.0"?>
<gpx version="1.1" creator="Example" xmlns="http://www.Example.com/1" xmlns:football="https://www.Example-football.com/xsd/football-ext">
<metadata>
<name>hello world</name>
<time>2018-04-26T12:32:52</time>
<extensions>
<sportsMeta>
<football:length>5080.3714454417996</football:length>
</sportsMeta>
</extensions>
</metadata>
</gpx>
Added this to package-info.java
#javax.xml.bind.annotation.XmlSchema(namespace = "http://www.Example.com/1", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, attributeFormDefault = XmlNsForm.UNQUALIFIED, xmlns = {
#javax.xml.bind.annotation.XmlNs(prefix = "football", namespaceURI = "https://www.Example-football.com/xsd/football-ext"),
#javax.xml.bind.annotation.XmlNs(prefix = "", namespaceURI = "https://www.Example-football.com/xsd/football-ext/1/1") })
package com.example.football.share.gpx;
import javax.xml.bind.annotation.XmlNsForm;
I am able to read name, time. But not able to read guid, length.
Here is SportsMeta.java
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "sportsMeta", propOrder = {
"length"
})
public class SportsMeta {
protected BigDecimal length;
public BigDecimal getLength() {
return length;
}
public void setLength(BigDecimal length) {
this.length = length;
}
}
How can I read length info from the XML file.
In your XML input you have this part:
<sportsMeta>
<football:length>5080.3714454417996</football:length>
</sportsMeta>
where the namespace prefix football refers to the namespace URI
"https://www.Example-football.com/xsd/football-ext"
as defined by xmlns:football="https://www.Example-football.com/xsd/football-ext"
in your XML.
To map this XML to Java correctly you need to specify
that namespace URI for the length property of yourSportsMeta class.
You do this by annotating the length property
with #XmlElement and specifying the namespace within there.
(See also the API documentation of XmlElement.namespace.)
#XmlElement(namespace = "https://www.Example-football.com/xsd/football-ext")
protected BigDecimal length;

JAXB ~ Dynamically parse multiple namespaces

I am trying to create an unmarshaller that will work for the following XML files:
<?xml version="1.0" encoding="UTF-8"?>
<REQ-IF xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd
xml:lang="en">
[...]
</REQ-IF>
<?xml version="1.0" encoding="UTF-8"?>
<REQ-IF xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd"
xmlns:configuration="http://eclipse.org/rmf/pror/toolextensions/1.0"
xmlns:id="http://pror.org/presentation/id"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
[...]
</REQ-IF>
<?xml version="1.0" encoding="UTF-8"?>
<REQ-IF xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd"
xmlns:doors="http://www.ibm.com/rdm/doors/REQIF/xmlns/1.0"
xmlns:reqif="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd"
xmlns:reqif-common="http://www.prostep.org/reqif"
xmlns:reqif-xhtml="http://www.w3.org/1999/xhtml"
xmlns:rm="http://www.ibm.com/rm"
xmlns:rm-reqif="http://www.ibm.com/rm/reqif"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
[...]
</REQ-IF>
All those files are structurally the same and are based of the same top-level namespace, but also contain a variety of variable sub-level namespaces and other "things" (which by my understanding should be attributes, but are not), which need to be saved in the system.
Thus far, I have managed to get to the point where this much is saved:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<REQ-IF xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">
[...]
</REQ-IF>
however, my intended result would look like this:
<?xml version="1.0" encoding="UTF-8"?>
<REQ-IF xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd
xml:lang="en">
[...]
</REQ-IF>
So the top-level namespace is saved, but the sub-level namespaces and other "things" are lost in the import/export process. This is bad.
How can I save those other sub-namespaces and other "things", considering that they are dynamically generated?
Basically, what I want to say is "save all these extra attributes in any way you like while parsing the XML, and once you export the XML again, re-write them exactly as they were".
If your main use case is to read ReqIF files, consider that there is an open source implementation of a ReqIF (de)serializer at https://www.eclipse.org/rmf/
Unfortunately it seems that JAXB alone is not capable of manage all the namespace prefixes dynamically and you need to combine it with another parsing mechanism.
I would try to implement something like this (only rough implementation, details below):
public class MyXmlHandler {
XMLInputFactory xif = XMLInputFactory.newInstance();
XMLOutputFactory xof = XMLOutputFactory.newInstance();
XMLEventFactory xef = XMLEventFactory.newInstance();
/**
* Retrieve XMLEvent for root element
*/
public StartElement getStartElement(String source) throws XMLStreamException {
XMLEvent event;
XMLEventReader reader = xif.createXMLEventReader(new StringReader(source));
while (reader.hasNext()) {
event = reader.nextEvent();
if (event.isStartElement()) {
return event.asStartElement();
}
// alternativery you can retrieve here also QNames for first level child elements
// and return all this data in some synthetic wrapper class
}
return null; // alternatively throw an exception
}
/**
* Write root element, than some content from JAXB elements, than end element
*/
public void write(
Marshaller marshaller,
Writer writer,
StartElement root,
List<JAXBElement> elements
) throws JAXBException, XMLStreamException {
XMLEventWriter xew = xof.createXMLEventWriter(writer);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
xew.add(root);
for(JAXBElement element : elements) {
marshaller.marshal(element, xew);
}
xew.add(xef.createEndElement(root.getName(), root.getNamespaces()));
xew.close();
}
}
And use it like this:
// create JAXB context and unmarshaller
JAXBContext ctx = JAXBContext.newInstance(RootClass.class);
Unmarshaller unmarshaller = ctx.createUnmarshaller();
// unmarshall XML
JAXBElement<RootClass> element = unmarshaller.unmarshal(source, RootClass.class);
RootClass rootValue = element.getValue();
// extract root element data from XML
StartElement root = handler.getStartElement(data);
// perform some business logic
// create marshaller
Marshaller marshaller = ctx.createMarshaller();
// create list of JAXBElements for root children
List<JAXBElement> elements = new ArrayList<>();
QName qname = ... // construct qualified name or retrieve it from saved structure
// very schematic, names of the child elements depend on your implementation
elements.add(new JAXBElement(qname , rootValue.getChild().getClass(), rootValue.getChild()));
handler.write(marshaller, writer, root, elements);
When preserving root element data, you can save also QNames for its children in some wrapper class. So far I see the REQ-IF structure contains header, core content and tool extensions. You could save QNames for all of them and then use them for constructing JAXB elements during marshalling process.

How can I determine the location of the XML namespace on Java (JAXB or another method)?

I'm using JAXB to marshall an Java object to XML.
Example;
com.abc.Defter.java object package-info.java:
#javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.com",
xmlns = {#javax.xml.bind.annotation.XmlNs(namespaceURI = "http://www.example.com", prefix = "abc")})
package com.abc;
com.xyz.Xbrl.java object package-info.java:
#javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example2.com",
xmlns = {#javax.xml.bind.annotation.XmlNs(namespaceURI = "http://www.example2.com", prefix = "xyz")})
package com.xyz;
Marshalling result xml string;
<abc:defter xmlns:abc="http://www.example.com" xmlns:xyz="http://www.example2.com">
<xyz:xbrl>
<xyz:unit id="try">
<measure>iso4217:TRY</measure>
</xyz:unit>
</xyz:xbrl>
</abc:defter>
All namespaces are in the root directory, but I do not want it. I would like the following example;
<abc:defter xmlns:abc="http://www.example.com">
<xyz:xbrl xmlns:xyz="http://www.example2.com">
<xyz:unit id="try">
<measure>iso4217:TRY</measure>
</xyz:unit>
</xyz:xbrl>
</abc:defter>
How can I do it JAXB or another method using?

Java Unmarshalling issue (jaxb) [duplicate]

I am using JAXB to parse xml elements from the SOAP response. I have defined POJO classes for the xml elements. I have tested pojo classes without namespace and prefix its working fine .Though when i am trying to parse with namespaces and prefix facing the following exception.Requirement is to parse the input from SOAPMessage Object
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Envelope"). Expected elements are <{}Envelope>
Tried to fix by creating #XMLSchema for the package in package-info.java and located this file in package folder.Can any one guide me to move forward?
Referred this posts but didn help me .
EDITED :XMLSchema
#javax.xml.bind.annotation.XmlSchema (
xmlns = { #javax.xml.bind.annotation.XmlNs(prefix = "env",
namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
#javax.xml.bind.annotation.XmlNs(prefix="ns3", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
}
)
package com.one.two;
Thanks in advance
This can be done without modifying the generated JAXB code using standard SOAPMessage class. I wrote about this here and here
It's a little fiddly but works correctly.
Marshalling
Farm farm = new Farm();
farm.getHorse().add(new Horse());
farm.getHorse().get(0).setName("glue factory");
farm.getHorse().get(0).setHeight(BigInteger.valueOf(123));
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Marshaller marshaller = JAXBContext.newInstance(Farm.class).createMarshaller();
marshaller.marshal(farm, document);
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
soapMessage.getSOAPBody().addDocument(document);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
soapMessage.writeTo(outputStream);
String output = new String(outputStream.toByteArray());
Unmarshalling
String example =
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Header /><soapenv:Body><ns2:farm xmlns:ns2=\"http://adamish.com/example/farm\"><horse height=\"123\" name=\"glue factory\"/></ns2:farm></soapenv:Body></soapenv:Envelope>";
SOAPMessage message = MessageFactory.newInstance().createMessage(null,
new ByteArrayInputStream(example.getBytes()));
Unmarshaller unmarshaller = JAXBContext.newInstance(Farm.class).createUnmarshaller();
Farm farm = (Farm)unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument());
Here is how you can handle your use cae:
If You Need to Map the Envelope Element
package-info
Typically you would use the #XmlSchema as follows. Using the namespace and elementFormDefault properties like I've done means that all data mapped to XML elements unless otherwise mapped will belong to the http://www.xxxx.com/ncp/oomr/dto/ namespace. The information specified in xmlns is for XML schema generation altough some JAXB implementations use this to determine the preferred prefix for a namespace when marshalling (see: http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html).
#XmlSchema (
namespace="http://www.xxxx.com/ncp/oomr/dto/",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(prefix = "env", namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
#XmlNs(prefix="whatever", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
}
)
package com.one.two;
import javax.xml.bind.annotation.*;
Envelope
If within the com.one.two you need to map to elements from a namespace other than http://www.xxxx.com/ncp/oomr/dto/ then you need to specify it in the #XmlRootElement and #XmlElement annotations.
package com.one.two;
import javax.xml.bind.annotation.*;
#XmlRootElement(name="Envelope", namespace="http://schemas.xmlsoap.org/soap/envelope/")
#XmlAccessorType(XmlAccessType.FIELD)
public class Envelope {
#XmlElement(name="Body", namespace="http://schemas.xmlsoap.org/soap/envelope/")
private Body body;
}
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
If You Just Want to Map the Body
You can use a StAX parser to parse the message and advance to the payload portion and unmarshal from there:
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class UnmarshalDemo {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("src/blog/stax/middle/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while(!xsr.getLocalName().equals("return")) {
xsr.nextTag();
}
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Customer> jb = unmarshaller.unmarshal(xsr, Customer.class);
xsr.close();
}
}
For More Information
http://blog.bdoughan.com/2012/08/handle-middle-of-xml-document-with-jaxb.html
Just wanted to add onto the existing answers -- while unmarshalling if the XML document is not namespace aware you might receive an error: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://some.url";, local:"someOperation")
If this is the case you can simply use a different method on the unmarshaller:
Unmarshaller unmarshaller = JAXBContext.newInstance(YourObject.class).createUnmarshaller();
JAXBElement<YourObject> element = unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument(), YourObject.class);
YourObject yo = element.getValue();

Marshalling and Unmarshalling changes xml using moxy

I am trying to create this kind(xsd inside) of documents. some examples are here. Because of constant values in root-element and some other constant elements i generated a template with eclipse:
<?xml version="1.0" encoding="UTF-8"?>
<invoice:response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:invoice="http://www.forum-datenaustausch.ch/invoice" xmlns="http://www.forum-datenaustausch.ch/invoice" xsi:schemaLocation="http://www.forum-datenaustausch.ch/invoice generalInvoiceResponse_440.xsd" language="de">
<invoice:processing>
<invoice:transport from="" to="">
<invoice:via sequence_id="0" via=""/>
</invoice:transport>
</invoice:processing>
<invoice:payload response_timestamp="0">
<invoice:invoice request_date="2001-12-31T12:00:00" request_id="" request_timestamp="0"/>
</invoice:payload>
</invoice:response>
But simple unmarshalling and marshalling changes the content:
<?xml version="1.0" encoding="UTF-8"?>
<response xmlns="http://www.forum-datenaustausch.ch/invoice" xmlns:ns1="http://www.w3.org/2000/09/xmldsig#" xmlns:ns0="http://www.w3.org/2001/04/xmlenc#" language="de">
<processing>
<transport from="" to="">
<via via="" sequence_id="0"/>
</transport>
</processing>
<payload response_timestamp="0">
<invoice request_timestamp="0" request_date="2001-12-31T12:00:00.0" request_id=""/>
</payload>
</response>
for some reason the schema location attribute is gone. this could be added manually before marshalling. the 2nd problem is, all prefixes are gone.
i don't know who consumes the produced xml (do they unmarshal with handwritten code? with or without validation?). Because of this i want an output that is most similar to given examples and valid.
So is there either a way to leave existing elements and attributes untouched and to let moxy add namespace prefixes to each element?
The following should help. This question is also being handled on the EclipseLink forum:
http://www.eclipse.org/forums/index.php/t/487391/
for some reason the schema location attribute is gone.
You can specify the following property on the Marshaller to output a schema location:
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.forum-datenaustausch.ch/invoice generalInvoiceResponse_440.xsd");
2nd problem is, all prefixes are gone.
The namespace prefixes are gone, but the namespace qualification is the same (all elements have the same local name and namespace URI). In the first document the invoice prefix is assigned to the http://www.forum-datenaustausch.ch/invoice namespace, and in the second document that namespace is assigned as the default namespace
CONTROLLING NAMESPACE PREFIXES AT DESIGN TIME
You can provide MOXy hints at what namespace prefixes should be used by leveraging the #XmlSchema annotation (see: http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html).
package-info
#XmlSchema(
elementFormDefault=XmlNsForm.QUALIFIED,
namespace="http://www.forum-datenaustausch.ch/invoice",
xmlns={
#XmlNs(prefix="invoice", namespaceURI="http://www.forum-datenaustausch.ch/invoice"),
#XmlNs(prefix="ds", namespaceURI="http://www.w3.org/2000/09/xmldsig#"),
#XmlNs(prefix="xenc", namespaceURI="http://www.w3.org/2001/04/xmlenc#")
}
)
package forum16559889;
import javax.xml.bind.annotation.*;
Response
package forum16559889;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Response {
}
Demo
package forum16559889;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Response.class);
Response response = new Response();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.forum-datenaustausch.ch/invoice generalInvoiceResponse_440.xsd");
marshaller.marshal(response, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<invoice:response xsi:schemaLocation="http://www.forum-datenaustausch.ch/invoice generalInvoiceResponse_440.xsd" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:invoice="http://www.forum-datenaustausch.ch/invoice" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
CONTROLLING THE NAMESPACE PREFIXES AT RUNTIME
You cam leverage MOXy's NamespacePrefixMapper extension to control the namespace prefixes used at runtime.
package forum16559889;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.oxm.NamespacePrefixMapper;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Response.class);
Response response = new Response();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.forum-datenaustausch.ch/invoice generalInvoiceResponse_440.xsd");
marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, new NamespacePrefixMapper() {
#Override
public String getPreferredPrefix(String namespaceUri,
String suggestion, boolean requirePrefix) {
if("http://www.forum-datenaustausch.ch/invoice".equals(namespaceUri)) {
return "invoice";
} else if("http://www.w3.org/2000/09/xmldsig#".equals(namespaceUri)) {
return "ds";
} else if("http://www.w3.org/2001/04/xmlenc#".equals(namespaceUri)) {
return "xenc";
} else {
return null;
}
}
});
marshaller.marshal(response, System.out);
}
}

Categories