XStream(new StaxDriver()) without XML declaration - java

My program JAVA:
public static String toXml() {
KtpMessage ktpMessage =new KtpMessage();
ktpMessage.setdetails("test");
XStream xstream = new XStream(new StaxDriver());
String objectXml = xstream.toXML(ktpMessage);
return objectXml;
The result is :
<?xml version='1.0' encoding='utf-8'?><myclasses.Message><details>test</details></myclasses.Message>
my problem:
I want to generate the "objectXml" but without <?xml version='1.0' encoding='utf-8'?>
how can I do that ?
i want have this result:
<myclasses.Message><details>test</details></myclasses.Message>
thanks for your help

If you create your own StaxWriter you can use the constructor that tells it not to write the startDocument StAX event (which is what creates the XML declaration). Something like this (exception handling omitted):
StaxDriver drv = new StaxDriver();
XStream xstream = new XStream(drv);
StringWriter strWriter = new StringWriter();
StaxWriter sw = new StaxWriter(drv.getQnameMap(),
drv.getOutputFactory().createXMLStreamWriter(strWriter),
false, // don't do startDocument
true); // do repair namespaces
xstream.marshal(ktpMessage, sw);
sw.close();
String objectXml = strWriter.toString();

Related

Handle illegal URI characters in xslt inclusion

In a xsl transformation I have a xslt file that includes some other xslt. The problem is that the URI for these xslt contains illegal characters, in particular '##'. The xslt looks like this:
<xsl:include href="/appdm/tomcat/webapps/sentys##1.0.0/WEB-INF/classes/xslt/release_java/xslt/gen.xslt" />
and when I try to instantiate a java Transformer I get the error:
javax.xml.transform.TransformerConfigurationException: javax.xml.transform.TransformerConfigurationException: javax.xml.transform.TransformerException: org.xml.sax.SAXException: org.apache.xml.utils.URI$MalformedURIException: Fragment contains invalid character:#
This is the java code:
public String xslTransform2String(String sXml, String sXslt) throws Exception {
String sResult = null;
try {
Source oStrSource = createStringSource(sXml);
DocumentBuilderFactory oDocFactory = DocumentBuilderFactory.newInstance();
oDocFactory.setNamespaceAware(true);
//sXslt is the xslt content with the inclusions
//<xsl:include href="/appdm/tomcat/webapps/sentys##1.0.0/WEB-INF/classes/xslt/release_java/xslt/gen.xslt" />"
Document oDocXslt = oDocFactory.newDocumentBuilder().parse(new InputSource(new StringReader(sXslt)));
Source oXsltSource = new DOMSource(oDocXslt);
StringWriter oStrOut = new StringWriter();
Result oTransRes = createStringResult(oStrOut);
Transformer oTrans = createXsltTransformer(oXsltSource);
oTrans.transform(oStrSource, oTransRes);
sResult = oStrOut.toString();
} catch (Exception oEx) {
throw new BddException(oEx, XmlProvider.ERR_XSLT, null);
}
return sResult;
}
private Transformer createXsltTransformer(Source oXsltSource) throws Exception {
Transformer transformer = getXsltTransformerFactory().newTransformer(
oXsltSource);
ErrorListener errorListener = new DefaultErrorListener();
transformer.setErrorListener(errorListener);
return transformer;
}
is there a way I can go with relative paths instead of absolute path?
Thank you
To avoid the MalformedURIException, replace the second or both # with %23.
See https://stackoverflow.com/a/5007362/4092205

Apache CXF/JAXB unmarshaller converting Japanese characters to ? marks java

Apache CXF/JAXB is not unmarshaling Japanese characters. If we are printing the xml using System.out.println output is coming properly like below.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee id="1470">
<designation>Eng</designation>
<name>マデュ</name>
<salary>20000.0</salary>
</employee>
If we are passing the same XML to CXF layer it is converting like below.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee id="1470">
<designation>Eng</designation>
<name>???</name>
<salary>20000.0</salary>
</employee>
How to solve this issue. Thanks in advance.
Can you try use PrintWriter on top of StringWriter?
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
Can you try with XMLEventWriter to System.out?
XMLEventFactory events = XMLEventFactory.newInstance();
QName bar = new QName("urn:bar", "bar");
XMLOutputFactory factory = XMLOutputFactory.newInstance();
factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
XMLEventWriter writer = factory.createXMLEventWriter(System.out);
JAXBContext pContext = JAXBContext.newInstance(target);
Marshaller marshaller = pContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(pObject, writer);
writer.add(events.createStartDocument());
writer.setDefaultNamespace("urn:bar");
writer.add(events.createStartElement(bar, null, null));
writer.add(events.createEndDocument());
writer.flush();

merge XML using STAX XMLStreamWriter

I have created an XML using STAX and XMLStreamWriter. It works fine.
I need to merge two xml together. The problem that I am facing is the patient Pojo returns me XML containing all the patient information is below
<Patient>
<SocialSecurity>3333344</SocialSecurity>
<Name>
<LastName>pillai</LastName>
<FirstName>dhanya</FirstName>
<Name>
<Patient>
I need to add this into existing XML after <proID> like merging.
<?xml version="1.0" ?>
<Validate>
<proID>123</prodID>
</Validate>
Please advice
The answer is as below
public static void main(String[] args) throws Throwable {
XMLEventWriter eventWriter;
XMLEventFactory eventFactory;
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
eventWriter = outputFactory.createXMLEventWriter(bos);
eventFactory = XMLEventFactory.newInstance();
XMLEvent newLine = eventFactory.createDTD("\n");
// Create and write Start Tag
StartDocument startDocument = eventFactory.createStartDocument();
eventWriter.add(startDocument);
eventWriter.add(newLine);
StartElement configStartElement = eventFactory.createStartElement("","","Message");
eventWriter.add(configStartElement);
eventWriter.add(newLine);
XMLInputFactory inputFactory = XMLInputFactory.newFactory();
PatientDetails patientDetails= new PatientDetails();// Here I have called an POJO that return String and we add
String xml = patientDetails.getPatientDetails();
Source src = new StreamSource(new java.io.StringReader(xml));
XMLEventReader test = inputFactory.createXMLEventReader(src);
while(test.hasNext()){
XMLEvent event= test.nextEvent();
//avoiding start(<?xml version="1.0"?>) and end of the documents;
if (event.getEventType()!= XMLEvent.START_DOCUMENT && event.getEventType() != XMLEvent.END_DOCUMENT)
eventWriter.add(event);
// eventWriter.add(newLine);
test.close();
} //end of while
eventWriter.add(eventFactory.createEndElement("", "", "Message"));
eventWriter.add(newLine);
eventWriter.add(eventFactory.createEndDocument());
eventWriter.close();
System.out.println(bos.toString());
}//end of main

Remove standalone from xml [duplicate]

I am currently using the following code to marshal an object into an xml string
JAXBContext context;
try {
context = JAXBContext.newInstance(heartbeat.getClass());
StringWriter writer = new StringWriter();
Marshaller marshaller = context.createMarshaller();
heartbeat.setHeader(header);
heartbeat.setHeartbeatEvent(event);
marshaller.marshal(heartbeat, writer);
String stringXML = writer.toString();
return stringXML;
} catch (JAXBException e) {
throw new RuntimeException("Problems generating XML in specified "
+ "encoding, underlying problem is " + e.getMessage(),
e);
}
Which produces the following header
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
My desired output is the following
<?xml version=\"1.0\"?>
By adding this to the marshaller
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.FALSE);
marshaller.setProperty("com.sun.xml.bind.xmlHeaders", "<?xml version=\"1.0\"?>");
I receive
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><?xml version="1.0"?>
and changing the JAXB_FRAGMENT property to TRUE removes the header entirely. I have been following the JAXB - Remove 'standalone="yes"' from generated XML thread attempting to solve the problem but I have had no luck so far. Can someone please give me some insight on how to get my desired header from the JAXB marshaller?
When marshalling to an OutputStream using a combination of the following produces the expected output.
marshaller.setProperty("com.sun.xml.bind.xmlHeaders", "<?xml version=\"1.0\"?>");
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
The problem you are seeing occurs when you marshal to a Writer, which appears to be a bug in the JAXB reference implementation. You can raise an issue at the link below:
https://java.net/jira/browse/JAXB/
You could always do:
JAXBContext context;
try {
context = JAXBContext.newInstance(heartbeat.getClass());
StringWriter writer = new StringWriter();
writer.append("<?xml version=\"1.0\"?>");
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
heartbeat.setHeader(header);
heartbeat.setHeartbeatEvent(event);
marshaller.marshal(heartbeat, writer);
String stringXML = writer.toString();
return stringXML;
} catch (JAXBException e) {
throw new RuntimeException("Problems generating XML in specified "
+ "encoding, underlying problem is " + e.getMessage(),
e);
}
EclipseLink JAXB (MOXy) also supports the com.sun.xml.bind.xmlHeaders and it works correctly when marshalling to a Writer (I'm the MOXy lead)
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
This worked for me
marshaller.setProperty("com.sun.xml.internal.bind.xmlHeaders",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
In JAXB 3.0.1 the above mentioned constants cause a PropertyException:
jakarta.xml.bind.PropertyException: name: com.sun.xml.bind.xmlDeclaration value: false
In this case, the XML preamble can be configured with these marshaller constants:
marshaller.setProperty("org.glassfish.jaxb.xmlHeaders", "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
https://eclipse-ee4j.github.io/jaxb-ri/3.0.0/docs/ch05.html

how can i unmarshall in jaxb and enjoy the schema validation without using an explicit schema file

I am using jaxb for my application configurations
I feel like I am doing something really crooked and I am looking for a way to not need an actual file or this transaction.
As you can see in code I:
1.create a schema into a file from my JaxbContext (from my class annotation actually)
2.set this schema file in order to allow true validation when I unmarshal
JAXBContext context = JAXBContext.newInstance(clazz);
Schema mySchema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaFile);
jaxbContext.generateSchema(new MySchemaOutputResolver()); // ultimately creates schemaFile
Unmarshaller u = m_context.createUnmarshaller();
u.setSchema(mySchema);
u.unmarshal(...);
do any of you know how I can validate jaxb without needing to create a schema file that sits in my computer?
Do I need to create a schema for validation, it looks redundant when I get it by JaxbContect.generateSchema ?
How do you do this?
Regarding ekeren's solution above, it's not a good idea to use PipedOutputStream/PipedInputStream in a single thread, lest you overflow the buffer and cause a deadlock. ByteArrayOutputStream/ByteArrayInputStream works, but if your JAXB classes generate multiple schemas (in different namespaces) you need multiple StreamSources.
I ended up with this:
JAXBContext jc = JAXBContext.newInstance(Something.class);
final List<ByteArrayOutputStream> outs = new ArrayList<ByteArrayOutputStream>();
jc.generateSchema(new SchemaOutputResolver(){
#Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
outs.add(out);
StreamResult streamResult = new StreamResult(out);
streamResult.setSystemId("");
return streamResult;
}});
StreamSource[] sources = new StreamSource[outs.size()];
for (int i=0; i<outs.size(); i++) {
ByteArrayOutputStream out = outs.get(i);
// to examine schema: System.out.append(new String(out.toByteArray()));
sources[i] = new StreamSource(new ByteArrayInputStream(out.toByteArray()),"");
}
SchemaFactory sf = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
m.setSchema(sf.newSchema(sources));
m.marshal(docs, new DefaultHandler()); // performs the schema validation
I had the exact issue and found a solution in the Apache Axis 2 source code:
protected List<DOMResult> generateJaxbSchemas(JAXBContext context) throws IOException {
final List<DOMResult> results = new ArrayList<DOMResult>();
context.generateSchema(new SchemaOutputResolver() {
#Override
public Result createOutput(String ns, String file) throws IOException {
DOMResult result = new DOMResult();
result.setSystemId(file);
results.add(result);
return result;
}
});
return results;
}
and after you've acquired your list of DOMResults that represent the schemas, you will need to transform them into DOMSource objects before you can feed them into a schema generator. This second step might look something like this:
Unmarshaller u = myJAXBContext.createUnmarshaller();
List<DOMSource> dsList = new ArrayList<DOMSource>();
for(DOMResult domresult : myDomList){
dsList.add(new DOMSource(domresult.getNode()));
}
String schemaLang = "http://www.w3.org/2001/XMLSchema";
SchemaFactory sFactory = SchemaFactory.newInstance(schemaLang);
Schema schema = sFactory.newSchema((DOMSource[]) dsList.toArray(new DOMSource[0]));
u.setSchema(schema);
I believe you just need to set a ValidationEventHandler on your unmarshaller. Something like this:
public class JAXBValidator extends ValidationEventCollector {
#Override
public boolean handleEvent(ValidationEvent event) {
if (event.getSeverity() == event.ERROR ||
event.getSeverity() == event.FATAL_ERROR)
{
ValidationEventLocator locator = event.getLocator();
// change RuntimeException to something more appropriate
throw new RuntimeException("XML Validation Exception: " +
event.getMessage() + " at row: " + locator.getLineNumber() +
" column: " + locator.getColumnNumber());
}
return true;
}
}
And in your code:
Unmarshaller u = m_context.createUnmarshaller();
u.setEventHandler(new JAXBValidator());
u.unmarshal(...);
If you use maven using jaxb2-maven-plugin can help you. It generates schemas in generate-resources phase.

Categories