nashwaan / xml-js

Converter utility between XML text and Javascript object / JSON text.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CDATA is written with indentation and newlines

Hagedihag opened this issue · comments

I read the following XML with xml2json:

<?xml version="1.0"?>
<group>
	<name><![CDATA[An example name]]></name>
</group>

but writing it back with json2xml gives me:

<?xml version="1.0"?>
<group>
    <name>
        <![CDATA[My modified name]]>
    </name>
</group>

This is is not the expected XML output.
The CDATA section is not a TAG and should not be handled as one and therefore not be indented.
Sure, its easier to read, but its not 100% correct.
It would be great to fix that or make a config parameter for that behaviour.

example code:

var xmljs = require('xml-js');
var xmlIn = '<?xml version="1.0"?>\n<group>\n\t<name><![CDATA[An example name]]></name>\n</group>';
console.log('xmlIn:\n',xmlIn);

var jsonIn = xmljs.xml2json(xmlIn, {
	compact: true
});
var obj = JSON.parse(jsonIn);

// code to modify obj
obj.group.name._cdata = 'My modified name';

var jsonOut = JSON.stringify(obj);

var xmlOut = xmljs.json2xml(jsonOut, {
	compact	: true, 
	spaces	: 4,
	fullTagEmptyElement: true
});

console.log('xmlOut:\n',xmlOut);

Solution
file: js2xml.js

  1. Function: writeElementsCompact, Line 143
                case options.cdataKey: xml += writeCdata(element, options); break;
  1. Function: hasContent, Line 102
                case options.cdataKey:
                	return false;

@brathering Are you sure CData should not be proceeded by spaces or indentation at all?

I am thinking that there could be multiple CData inside an element:

<?xml version="1.0"?>
<group>
    <name>
        <![CDATA[My modified name 1]]>
        <![CDATA[My modified name 2]]>
        <![CDATA[My modified name 3]]>
    </name>
</group>

Following your proposal, they will be like this:

<?xml version="1.0"?>
<group>
    <name><![CDATA[My modified name 1]]><![CDATA[My modified name 2]]><![CDATA[My modified name 3]]></name>
</group>

Yes, I'm quite sure, because CDATA is not a tag and can be used inline in text:

<?xml version="1.0"?>
<group>
  <name>The url <![CDATA[http://www.test.com]]> and name <![CDATA[examplename]]> are wrapped</name>
</group>

If you use xmllint to format the above xml, it also doesn't add spaces and indentation:

$ xmllint --format test.xml

Thanks for confirming this.

I have published v1.1.0 which supports the suggested behavior.
Also, to support old behavior, indentCdata: true flag can be set in options object.

@brathering Please let me know whether the new result is as per your expectations or not.

v1.1.0 is published now.

Thank you very much for the quick update, looks good now and works as expected.