Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making JAXB generate an XML processing instruction

Tags:

xml

jaxb

xslt

I am generating XML dynamically using JAXB.

Now, I want to convert it to HTML using XSL. How can i include

<?xml-stylesheet type="text/xsl" href=""> 

in the dynamically generated XML?

like image 209
magic Avatar asked Jan 28 '10 08:01

magic


People also ask

Is JAXB XML parser?

JAXB — Java Architecture for XML Binding — is used to convert objects from/to XML. JAXB offers a fast and suitable way to marshal (write) Java objects into XML and unmarshal (read) XML into Java objects. It supports Java annotations to map XML elements to Java attributes.

How does Jaxb read XML?

To read XML, first get the JAXBContext . It is entry point to the JAXB API and provides methods to unmarshal, marshal and validate operations. Now get the Unmarshaller instance from JAXBContext . It's unmarshal() method unmarshal XML data from the specified XML and return the resulting content tree.


3 Answers

All the solutions here are pretty ugly and verbose. Simply set the line inside the Mashaller object specifying the additional header.

Marshaller jaxbMarshaller = ...
jaxbMarshaller.setProperty("com.sun.xml.bind.xmlHeaders", 
    "<?xml-stylesheet type='text/xsl' href='nameoffile.xsl' ?>");

This example will output an XML object to a file using a stylesheet and format the elements nicely for humans to read. The object myXmlObject is of class MyXmlClass, and will be written to file, formatted by a stylesheet given by xslUrl:

JAXBContext context = JAXBContext.newInstance(MyXmlClass.class);
Marshaller marshaller = context.createMarshaller();
//Need to use a Writer to marshal with the XSL
FileWriter fw = new FileWriter(file);
//Do this or else the XML is all one line and not human friendly...
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty("com.sun.xml.bind.xmlHeaders",
        "<?xml-stylesheet type='text/xsl' href=\"" +
        xslUrl +
        "\" ?>");
marshaller.marshal(myXmlObject, fw);

Update

In recent version of JAXB we need to use property key as com.sun.xml.internal.bind.xmlHeaders like below.

Marshaller jaxbMarshaller = ...
jaxbMarshaller.setProperty("com.sun.xml.internal.bind.xmlHeaders", 
    "<?xml-stylesheet type='text/xsl' href='nameoffile.xsl' ?>");
like image 183
mat_boy Avatar answered Oct 16 '22 09:10

mat_boy


You could use a StringWriter to first write the stylesheet information into it, and then marshal the object into it:

StringWriter writer = new StringWriter();
//add processing instructions "by hand" with escaped quotation marks
//or single marks
writer.println("<?xml version='1.0'?>");
writer.println("<?xml-stylesheet type=\"text/xsl\" href=\"\">");

//create and configure marshaller to leave out processing instructions
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);

//marshal to the StringWriter
marshaller.marshal(someObject,writer);
//get the string representation 
String str = writer.toString();

Of course you can also directly print to every other output stream you want, e.g. files or Sytstem.out.

like image 44
Jasper Avatar answered Oct 16 '22 09:10

Jasper


See how it's done in rexsl-core, part of ReXSL XSL/JAXB/JAX-RS framework: XslResolver:

final String header = String.format(
  "\n<?xml-stylesheet type='text/xsl' href='%s'?>",
  StringEscapeUtils.escapeXml("my-stylesheet.xsl")
);
marshaller.setProperty("com.sun.xml.bind.xmlHeaders", header);
like image 2
yegor256 Avatar answered Oct 16 '22 09:10

yegor256