I am using XJC to create from XML Schema a Jaxb annotated class.
With
JAXBContext context = JAXBContext.newInstance(SomeClass.class);
Marshaller marshaller = context.createMarshaller();
StringWriter writer = new StringWriter();
marshaller.marshal(cardJob, writer);
String resultString = writer.getBuffer().toString();
I create an xml output string - This works perfect. What I want to achieve is, adding an enum to this class like
Jan (1, "January"),
Feb (2, "February"),
...
by creating an entry in the xml schema and getting in the end
an output like
<.January><./January>.
Maybe wrong but something like an xml element from an enum entry name.
Help would be pretty great, cause I dont get any solution :(
maybe you can build your own ContentHandler
org.xml.sax.ContentHandler
handle the enums and put them into buffer before endDocument
marshaller.marshal(obj, new yourContentHandler());
Related
We have a logging system where we log payload on-demand to troubleshoot and in non-prod. However, due to column size constraint, we truncate the XML if it is more than 5000 characters.
The XML is not pretty-print formatted and is a continuous string.
When the XML is truncated, it is hard to format it to make it easy to check the data in the XML. Usually, I use Java DocumentBuilderFactory to format a complete XML, but that fails if we use against a incomplete XML.
I would like to have a solution that can format an incomplete XML instead of throwing an error.
Following the approach Michael Kay had outlined in his answer I linked to in a comment to use an identity Transformer with indentation over a StreamSource to catcn any parse exception the code looks like
String xml = "<root><section><p>Paragraph 1.</p><p>Paragraph 2."; //"<root><section><p>Paragraph 1.</p><p>Paragraph 2.</p></section></root>";
Transformer identityTransformer = TransformerFactory.newInstance().newTransformer();
identityTransformer.setOutputProperty("indent", "yes");
StringWriter resultWriter = new StringWriter();
StreamResult resultStream = new StreamResult(resultWriter);
try {
identityTransformer.transform(new StreamSource(new StringReader(xml)), resultStream);
}
catch (TransformerException e) {
System.out.println(e.getMessageAndLocation());
System.out.println(resultWriter.toString());
}
and then at least, for that example, gets to the last p element:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<section>
<p>Paragraph 1.</p>
<p
So some information at the end is lost but before that incomplete element the code at least breaks up the long one liner of the input into several lines.
Note: I used Saxon 10 HE as the default Transformer, if you use the JRE's one or Xalan you will need to set identityTransformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2"); as otherwise you get line breaks but no indentation.
I have decided to create dynamic xml as a response of my rest service.
Xml structure is defined in properties file it may change in future.
What will best approach to achieve this task.
Help me out with suggestions friends.
Thanks in advance
It is not recommended to use the properties file for generating dynamic XML. If the client requirement is that you have to used that properties file. Else the recommended way is to use the XSD schema generation method.
You can use the javax.xml.stream.XMLOutputFactory to generate the XML output. You can read the XML structure from the property file as your requirement and can generate the output using the javax.xml.stream.XMLOutputFactory.
Hope following code will helpful to you.
StringWriter stringWriter = new StringWriter();
XMLOutputFactory xmlFactory = XMLOutputFactory.newFactory();
XMLStreamWriter writer = xmlFactory.createXMLStreamWriter(stringWriter);
writer.writeStartDocument();
writer.writeStartElement(<<First element>>);
Using the Properties propertyNames() we will be getting the list of all the keys.
Using keys we can find the values.
Using this we can create a xml file using StringBuilder
For Example
StringBuilder sb = new StringBuilder();
sb.append("<"+key+">");
sb.append("+value+");
sb.append("</"+key+">");
After this write it to a file . Using FileOutputStream.java
I've a JMS messaging app thats reading and writing to MQ queues. The message data is string form and in xml format (minus the normal header markers like the xml version etc). I'm looking at the best ways to read in, write out and validate against an xsd schema however the examples I'm coming across all talk about working with files.
Is there any way (tutorials out there) to take an xml string; read it in and validate it and also do the same for an xml string I create validate and write out without writing to disk?
Would appreciate any pointers.
Check out the javax.xml.validation APIs in Java SE, in particular the Validator class which is used to validate XML content against an XML schema:
http://download-llnw.oracle.com/javase/6/docs/api/javax/xml/validation/package-summary.html
Use a StringReader on the strings, pass the reader to the JAXB methods to read the contents.
thanks folks I managed to sort this one out with the following.
Marshall:
JAXBContext jaxbContext = JAXUtility.getContext(packageLocation);
StringWriter sw = new StringWriter();
Marshaller m = jaxbContext.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
if (o instanceof UnadvisedDeal) { m.marshal((UnadvisedDeal) o,sw);
UnMarshall:
JAXBContext jaxbContext = JAXUtility.getContext(packageLocation);
Unmarshaller um = jaxbContext.createUnmarshaller();
ud = (UnadvisedDeal) um.unmarshal(new StringReader(sw.toString()));
thanks for the help though
I have an XML file which I'd like to parse into a non-XML (text) file based on a XLST file. The code in both seem correct, and it works when testing manually, but I'm having a problem doing this programatically.
I'm using JDOM's XSLTransformer class to apply the XSLT to the XML and it returns it in the format of a JDOM Document. The problem here is that I can't seem to access anything in the Document as it is not a proper XML file and I get a "java.lang.IllegalStateException: Root element not set" error.
Is there a better way within Java to obtain a non-XML file as a result of XSLT?
JDOM XSLTTransformer is a convenience wrapper around javax.xml.transform.Transformer for JDOM input and output.
A JDOM input is easily transformed to text output.
Transformer transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(stylesheet));
JDOMSource in = new JDOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult out = new StreamResult(writer);
transformer.transform(in, out);
return writer.toString();
I'm marshaling objects into an XML file. How can I add comments into that XML file?
You can add comments right after the preamble with the proprietary Marshaller property com.sun.xml.bind.xmlHeaders (see XML Preamble Control)
In the included JAXB-implementation jdk1.6.0_29 the property is called "com.sun.xml.internal.bind.xmlHeaders"
See also question: How to add DOCTYPE and xml processing instructions when marshalling with JAXB?
So to get this XML with the test-comment after the preamble:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Test Comment -->
<player>
<name>Daniel</name>
<birthday>1982-06-09T00:00:00+02:00</birthday>
</player>
You can use this Java-Code:
JAXBContext context = JAXBContext.newInstance(Player.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty("com.sun.xml.internal.bind.xmlHeaders", "\n<!-- Test Comment -->");
m.marshal(player, System.out);
I do not see a way to do it with JAXB alone. However, I think you can leverage DOM to get the desired effect:
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document doc = builder.getDOMImplementation().createDocument(null, null, null);
final Binder<Node> binder = jaxbContext.createBinder();
binder.marshal(jaxbObject, doc);
final Comment comment = doc.createComment("This is a comment");
doc.appendChild(comment);
final DOMSource domSource = new DOMSource(doc);
// use System.out for testing
final StreamResult streamResult = new StreamResult(System.out);
final TransformerFactory tf = TransformerFactory.newInstance();
final Transformer serializer = tf.newTransformer();
serializer.transform(domSource, streamResult);
Where jaxbContext is the JAXBContext object you are working with and jaxbObject is the object to be marshalled. This sample just appends the comment to the end of the document. For a different location, you would have to traverse the DOM through the doc object or use XPath to find the exact element you want the comment added to and use appendChild on it.
If anyone comes to this now, like I just did, it is worth pointing out that the property to do this is now com.sun.xml.bind.xmlHeaders (no longer internal it seems), so you can solve the problem like this (I have only tried it with EclipseLink MOXY):
JAXBContext context = JAXBContext.newInstance(Player.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty("com.sun.xml.bind.xmlHeaders", "\n<!-- Test Comment -->");
m.marshal(player, System.out);
The following information originally comes from Marshaller Properties in the JAXB RI Extensions documentation on jaxb.java.net:
XML Preamble Control
This property allows you to specify an XML preamble (
declaration) and any additional PIs, comments, DOCTYPE declaration
that follows it. This property takes effect only when you are
marshalling to OutputStream, Writer, or StreamResult. Note that this
property interacts with the Marshaller.JAXB_FRAGMENT property. If that
property is untouched or set to false, then JAXB would always write
its XML preamble, so this property can be only used to write PIs,
comments, DOCTYPE, etc. On the other hand, if it is set to true, then
JAXB will not write its own XML preamble, so this property may contain
custom XML preamble.