8

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?

Tomalak
  • 332,285
  • 67
  • 532
  • 628
magic
  • 101
  • 1
  • 2

4 Answers4

11

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' ?>");
Mahendran Sakkarai
  • 8,381
  • 6
  • 44
  • 66
mat_boy
  • 12,998
  • 22
  • 72
  • 116
  • 1
    This is the elegant way to do it, but it won't work if you are doing `marshal()` to a `File` (for example). It requires the output to be a Writer or Stream. Once you are aware of this it should be simple matter to wrap your `File` in a `FileWriter`. – Kevin Sadler Nov 04 '13 at 15:11
  • @KevinSadler Your edit has been rejected by the community. I added the edit, but it has been uglyfied. Please, prettify it such that the edit will be linked to you! Thanks! – mat_boy May 13 '14 at 07:46
  • OK I have reformatted it and altered the comment slightly, I hope it will be accepted as I think it adds a couple of useful things. – Kevin Sadler May 13 '14 at 14:33
  • Just a slight note: the supported properties depend on the used implemenation of JAXB – VeikkoW Sep 08 '14 at 14:44
  • For the record: using the default Jaxb implementation in Java 8, which uses the marshaller javax.xml.bind.helpers.AbstractMarshallerImpl under the hood, this very elegant method unfortunately does not work anymore. – mtj Sep 21 '16 at 06:21
  • 1
    only working using `com.sun.xml.internal.bind.xmlHeaders` – MushyPeas Oct 12 '19 at 16:00
4

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.

Jasper
  • 1,971
  • 19
  • 34
2

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);
yegor256
  • 102,010
  • 123
  • 446
  • 597
1
JAXBContext jaxbContext;
try {
       jaxbContext = JAXBContext.newInstance(new Class[] {SomeObject.class});

       StringWriter writer = new StringWriter();
       writer.write("<?xml version='1.0'?>");
       writer.write("\n");
       writer.write("<?xml-stylesheet type=\"text/xsl\" href=\"\">");
       writer.write("\n");

       Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
       jaxbMarshaller.marshal(someobject, writer);
}
Artemix
  • 2,113
  • 2
  • 23
  • 34
Ashok
  • 11
  • 1
  • 4
    Please try to answer in words and not only in code. And since you answer so late, how does your answer differ from the other ones? – Olle Sjögren Nov 05 '12 at 13:38