0

I need to put String content to xml in Java. I use this kind of code to insert information in xml:

Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File ("file.xml"));
DOMSource source = new DOMSource (doc);

Node cards = doc.getElementsByTagName ("cards").item (0);

Element card = doc.createElement ("card");
cards.appendChild(card);

Element question = doc.createElement("question");
question.appendChild(doc.createTextNode("This <b>is</b> a test.");
card.appendChild (question);

StreamResult result = new StreamResult (new File (file));
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.transform(source, result);

But string is converted in xml like this:

<cards>
  <card>
    <question>This &lt;b&gt;is&lt;/b&gt; a test.</question>
  </card>
</cards>

It should be like this:

<cards>
  <card>
    <question>This <b>is</b> a test.</question>
  </card>
</cards>

I tried to use CDDATA method but it puts code like this:

// I changed this code
question.appendChild(doc.createTextNode("This <b>is</b> a test.");
// to this
question.appendChild(doc.createCDATASection("This <b>is</b> a test.");

This code gets a xml file look like:

<cards>
  <card>
    <question><![CDATA[This <b>is</b> a test.]]></question>
  </card>
</cards>

I hope that somebody can help me to put String content in the xml file exactly with same content.

Thanks in advance!

Mikko Kirkanen
  • 179
  • 4
  • 17
  • 1
    Are you **sure** you want to actually have a `b` element in your `question` element? Anything that actually reads the content of the `question` element will see the text as you intend it, the entity encoding is for storing it in the XML data. E.g., what it's doing is actually correct, and anything reading your XML later will get the text "This is a test". – T.J. Crowder Mar 31 '11 at 13:50
  • @Crowder Yes, I'm sure. I used Java program to create deck which includes cards with question and answer parts. Text should be styled with -tags so that can use in flash with styled text. In java program I use JTextPane with html content so I can see it right. – Mikko Kirkanen Apr 03 '11 at 09:10

5 Answers5

2

This would be expected behaviour.

Consider if the brackets were kept as you put them, the end result would essentially be:

<cards>  
  <card>    
    <question>
      This 
      <b>
        is
      </b>
       a test.
    </question>  
  </card>
</cards>

Basically, it would result in the <b> being an additional node in the xml tree. Encoding the brackets to &lt; and &gt; ensures that when displayed by any xml parser, the brackets will be displayed, and not confused as being an additional node.

If you really wanted them to display as you say you do, you will need to create elements named b. This will not only be awkward, it will also not display quite as you've written above - it would display as additional nested nodes as I've shown above. So you would need to amend the xml writer to output inline for those tags.

Nasty.

Jaymz
  • 6,140
  • 2
  • 26
  • 30
1

Maybe you could solve it in this way (code only for <question> tag part):

Element question = doc.createElement("question");
question.appendChild(doc.createTextNode("This ");
Element b = doc.createElement("b");
b.appendChild(doc.createTextNode("is");
question.appendChild(b);
question.appendChild(doc.createTextNode(" a test.");
card.appendChild(question);
bluish
  • 26,356
  • 27
  • 122
  • 180
1

Check this solution: how to unescape XML in java

Community
  • 1
  • 1
0

What you are effectively trying to do is to insert XML into the middle of a DOM without parsing it. You can't do this since the DOM APIs don't support it.

You have three choices:

  • You could serialize the DOM and then insert the String at the appropriate point. The end result may or may not be well-formed XML ... depending on what is in the String that you inserted.

  • You could create and insert DOM nodes representing the text and the <b>...</b> element. This requires you to know the XML structure of the stuff that you are inserting. @bluish's answer gives an example.

  • You could wrap the String in some container element, parse it using an XML parser to give a second DOM, find the nodes of interest, and add them to the original DOM. This requires that the String is well-formed XML when wrapped in the container element.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

Or, since you're already using a Transformation, why not go all the way?

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output omit-xml-declaration="yes"/>

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

<xsl:template match="cards">
    <card>
        <question>This <b>is</b> a test</question>
    </card>
</xsl:template>
</xsl:stylesheet>
forty-two
  • 12,204
  • 2
  • 26
  • 36