XMLStreamWriter writeCharacters without escaping
Asked Answered
R

5

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.

Rastus answered 6/5, 2010 at 19:12 Comment(2)
Possible duplicate of How to write unescaped XML to XMLStreamWriter?Joses
I think you need to do writer.flush(), and sw.flush(), right before you do out.append(sw). My sysout was blank until I did flush() methods.Antilogy
W
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//");
Wordage answered 6/5, 2010 at 19:34 Comment(2)
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?Rastus
@Felix: Then it seems to be implementation-dependent. I added the CDATA example.Wordage
M
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.

Mastitis answered 22/11, 2012 at 8:47 Comment(2)
This does not seem to be documented, but it works for writeCharacters. It does, however, not work for writeAttribute :-(Weihs
Not documented, so you can't trust this to work in the future. Check my answer: https://mcmap.net/q/456166/-xmlstreamwriter-writecharacters-without-escapingJoses
W
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//");
Wordage answered 6/5, 2010 at 19:34 Comment(2)
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?Rastus
@Felix: Then it seems to be implementation-dependent. I added the CDATA example.Wordage
S
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).

Subirrigate answered 9/11, 2017 at 11:30 Comment(0)
W
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.

Willianwillie answered 27/3, 2014 at 15:23 Comment(0)
J
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();
Joses answered 14/7, 2016 at 12:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.