5

How do I use XMLStreamWriter to write exactly what I put in? For instance, if I create script tag and fill it with javascript I don't want all my single quotes coming out as '

Here's a small test I wrote that doesn't use any of the abstractions I've got in place, just calls to writeCharacters.

  public void testWriteCharacters() {
    StringWriter sw = new StringWriter();
    XMLOutputFactory factory = XMLOutputFactory.newInstance();

    StringBuffer out = new StringBuffer();
    try {
      XMLStreamWriter writer = factory.createXMLStreamWriter(sw);
      writer.writeStartElement("script");
      writer.writeAttribute("type","text/javascript");
      writer.writeCharacters("function hw(){ \n"+
      "\t alert('hello world');\n" +
      "}\n");
      writer.writeEndElement();
      out.append(sw);
    } catch (XMLStreamException e) {
    } finally {
      try {
        sw.close();
      } catch(IOException e) {
        e.printStackTrace();
      }
    }
    System.out.println(out.toString());
  }

This produces an apos entity for both the single quotes surrounding hello world.

Felix
  • 699
  • 2
  • 9
  • 24
  • Possible duplicate of [How to write unescaped XML to XMLStreamWriter?](http://stackoverflow.com/questions/19998460/how-to-write-unescaped-xml-to-xmlstreamwriter) – Roland Jul 18 '16 at 08:41

5 Answers5

9

You could use a property on the factory:

final XMLOutputFactory streamWriterFactory = XMLOutputFactory.newFactory();
streamWriterFactory.setProperty("escapeCharacters", false);

Then the writer created by this factory will write characters without escaping the text in the element given that the factory supports this property. XMLOutputFactoryImpl does.

René Höhle
  • 26,716
  • 22
  • 73
  • 82
Bodum R Mugg
  • 99
  • 1
  • 2
  • This does not seem to be documented, but it works for `writeCharacters`. It does, however, not work for `writeAttribute` :-( – binwiederhier Jul 17 '14 at 18:53
  • Not documented, so you can't trust this to work in the future. Check my answer: http://stackoverflow.com/a/38374931/480894 – Roland Jul 14 '16 at 13:00
7

XmlStreamWriter.writeCharacters() doesn't escape '. It only escapes <, > and &, and writeAttribute also escapes " (see javadoc).

However, if you want to write text without escaping at all, you have to write it as a CDATA section using writeCData().

The typical approach for writing scripts in CDATA sections is:

<script>//<![CDATA[
    ...
//]]></script>

That is:

out.writeCharacters("//");
out.writeCData("\n ... \n//");
axtavt
  • 239,438
  • 41
  • 511
  • 482
  • I added an example above. Its been escaping single quotes for me. The CData doesn't escape anything, but the contents don't render and javascript doesn't execute. Thoughts? – Felix May 06 '10 at 21:07
  • @Felix: Then it seems to be implementation-dependent. I added the CDATA example. – axtavt May 06 '10 at 21:54
1

Alternative method, with custom escape handler:

XMLOutputFactory xmlFactory = XMLOutputFactory.newInstance();
xmlFactory.setProperty(XMLOutputFactory2.P_TEXT_ESCAPER, new MyEscapingWriterFactory());

'MyEscapingWriterFactory' is your implementation of 'EscapingWriterFactory' interface. It allows fine grained text escaping control. This is useful when you use text element to deal with random input (say, invalid XML with multiple processing instructions or incorrectly written CDATA sections).

Dimitar II
  • 2,299
  • 32
  • 33
0

You can also use woodstox's stax implementation. Their XMLStreamWriter2 class has a writeRaw() method. We're using it for this specific reason and it works great.

David Thielen
  • 28,723
  • 34
  • 119
  • 193
0

Write directly to the underlying Writer or OutputStream:

Writer out = new StringWriter();
XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(out);
... //write your XML
writer.flush();
//write extra characters directly to the underlying writer
out.write("<yourstuff>Test characters</yourstuff>");
out.flush();
... //continue with normal XML
writer.writeEndElement();
writer.flush();
Roland
  • 7,525
  • 13
  • 61
  • 124