How to add informations to my xml - AS3 - AIR - actionscript-3

I'm loading an xml file name animals.xml
var urlLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE,onXMLLoaded);
var file:File = File.documentsDirectory.resolvePath("animals.xml");
var stream:FileStream = new FileStream();
urlLoader.load(new URLRequest(file.url));
function onXMLLoaded(e:Event):void{
xml = new XML(e.target.data);
trace(xml..animal.#name[2]);
}
when I click on a button, it modifies the name of the cat by Garfield
click_btn.addEventListener(MouseEvent.CLICK, btn_clicked, false, 0, true);
function btn_clicked(event:MouseEvent):void {
modifyName();
}
function modifyName():void{
xml..animal.#name[2] = "GARFIELD";
stream.open(file, FileMode.WRITE);
stream.writeUTFBytes(xml);
stream.close();
}
How can I, now, add new information to my xml ?
My XML is build like that :
<?xml version="1.0" encoding="UTF-8"?>
<animals>
<animal type="dog" name="Fido" age="2">Fido is a good dog.</animal>
<animal type="dog" name="Ralph" age="1">Ralph is brown.</animal>
<animal type="dog" name="Brian" age="1">Brian is Ralph's brother.</animal>
<animal type="cat" name="Charlie" age="3">Charlie likes fish.</animal>
<animal type="rabit" name="Gulper" age="3">Gulper does not want to be eaten.</animal>
</animals>
How do I do to add a new line ?
For example :
animal type ="turtle"
name "Caroline"
age = "5"
Caroline is a turtle
So, in the results, I'll have :
<animal type="dog" name="Fido" age="2">Fido is a good dog.</animal>
<animal type="dog" name="Ralph" age="1">Ralph is brown.</animal>
<animal type="dog" name="Brian" age="1">Brian is Ralph's brother.</animal>
<animal type="cat" name="Charlie" age="3">Charlie likes fish.</animal>
<animal type="rabit" name="Gulper" age="3">Gulper does not want to be eaten.</animal>
<animal type="turtle" name="Caroline" age="5"> Caroline is a turtle </animal>
</animals>

You need to add a new child node to your XML. Something like that:
function addAnimal(target:XML, type:String, name:String, age:int, comment:String):void
{
target.appendChild(<animal type={type} name={name} age={age}>{comment}</animal>);
}
The idea behind curly brackets is to simplify XML node notation. Should be quite transparent by itself, but if you are curious, you may start looking it up from here.
Then, you free to add as many animals as you need:
addAnimal(xml, "turtle", "Caroline", 5, "Caroline is a turtle");
addAnimal(xml, "peacock", "Lord Chen", 25, "Must build a cannon");

Related

DrawIo mxGraph: Using XmlToSvg loses shapes information

I am trying to convert XML to SVG using Java, but it looks like the shapes information is getting lost in the process.
Given a simple draw.io graph:
After running XmlToSvg.java I get:
I saved it as an uncompressed XML. I'm using the mxgraph-all.jar from the mxGraph Repo
Do you know if there are hidden settings to enable to preserve shapes and colors?
Short version
It looks like despite the claims on the GitHub page, no implementation except for JavaScript one is really fully featured and production ready. Particularly Java implementation (as well .Net and PHP server-side ones) doesn't support "Cube" shape out of the box.
More details
Colors
You didn't provide your example XML but when I generate similar graph I get something like
<?xml version="1.0" encoding="UTF-8"?>
<mxGraphModel dx="1426" dy="816" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850"
pageHeight="1100" background="#ffffff" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="2" value="" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="445" y="60" width="230" height="150" as="geometry"/>
</mxCell>
<mxCell id="3" value="" style="ellipse;shape=doubleEllipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
<mxGeometry x="500" y="320" width="120" height="120" as="geometry"/>
</mxCell>
<mxCell id="4" value="" style="endArrow=classic;html=1;" parent="1" source="3" target="2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="430" y="510" as="sourcePoint"/>
<mxPoint x="480" y="460" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="5" value="" style="shape=cube;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="320" width="170" height="110" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
Important thing here is that this XML does not contain any information about colors. Thus whole idea about "preserving colors" is wrong. In Java implementation you can configure "default colors" using an instance of mxStylesheet class and use it to init mxGraph object. For example to change colors to black and white you may do something like this:
mxStylesheet stylesheet = new mxStylesheet();
// configure "figures" aka "vertex"
{
Map<String, Object> style = stylesheet.getDefaultVertexStyle();
style.put(mxConstants.STYLE_FILLCOLOR, "#FFFFFF");
style.put(mxConstants.STYLE_STROKECOLOR, "#000000");
style.put(mxConstants.STYLE_FONTCOLOR, "#000000");
}
// configure "lines" aka "edges"
{
Map<String, Object> style = stylesheet.getDefaultEdgeStyle();
style.put(mxConstants.STYLE_STROKECOLOR, "#000000");
style.put(mxConstants.STYLE_FONTCOLOR, "#000000");
}
mxGraph graph = new mxGraph(stylesheet);
You may look at mxStylesheet.createDefaultVertexStyle and mxStylesheet.createDefaultEdgeStyle for some details.
Shapes
The "ellipse" shape is not handled correctly because there is no code to parse "ellipse;whiteSpace=wrap;html=1;" and understand that the shape should be "ellipse" (comapre this to the "double ellipse" style "ellipse;shape=doubleEllipse;whiteSpace=wrap;html=1;aspect=fixed;" that contains explicit shape value). In JS implementation the first part of the style seems to select a handler function that will handle the rest of the string and do actual work. There seems to be no such feature in Java implmenetation at all. You can work this around by using "named styles" feature and define default shape for corresponding "handler" in the same mxStylesheet object like this:
// I just copied the whole list of mxConstants.SHAPE_ here
// you probably should filter it by removing non-primitive shapes
// such as mxConstants.SHAPE_DOUBLE_ELLIPSE
String[] shapes = new String[] {
mxConstants.SHAPE_RECTANGLE,
mxConstants.SHAPE_ELLIPSE,
mxConstants.SHAPE_DOUBLE_RECTANGLE,
mxConstants.SHAPE_DOUBLE_ELLIPSE,
mxConstants.SHAPE_RHOMBUS,
mxConstants.SHAPE_LINE,
mxConstants.SHAPE_IMAGE,
mxConstants.SHAPE_ARROW,
mxConstants.SHAPE_CURVE,
mxConstants.SHAPE_LABEL,
mxConstants.SHAPE_CYLINDER,
mxConstants.SHAPE_SWIMLANE,
mxConstants.SHAPE_CONNECTOR,
mxConstants.SHAPE_ACTOR,
mxConstants.SHAPE_CLOUD,
mxConstants.SHAPE_TRIANGLE,
mxConstants.SHAPE_HEXAGON,
};
Map<String, Map<String, Object>> styles = stylesheet.getStyles();
for (String sh : shapes)
{
Map<String, Object> style = new HashMap<>();
style.put(mxConstants.STYLE_SHAPE, sh);
styles.put(sh, style);
}
Still you may notice that the list of the mxConstants.SHAPE_ doesn't contain "cube". In JS implementation "cube" is a compound shape that is handled by a specialized handler in examples/grapheditor/www/js/Shape.js which is not a part of the core library! It means that if you want to support such advanced shapes in your Java code, you'll have to roll out the code to handle it yourself.
P.S. With all those changes (hacks) the image I get using Java code from the XML in the first snippet is:
There is an XML-file, containing parameters of the most generic shapes. You should load it into stylesheet to make images look exactly as they were drawn in editor. Default stylesheet is default.xml.
So first of all make your code to get 2 things: stylesheet and diagram content.
String diagramText = getAsString(diagramPath);
String stylesheetText = getAsString(stylesheetPath);
Next, the simplest way to create SVG image is to utilize classes from mxgraph-core.jar. It looks like this
mxStylesheet stylesheet = new mxStylesheet(); // mxgraph-core.jar
InputSource is = new InputSource(new StringReader(stylesheetText));
Document document = documentBuilder.parse(is);
mxCodec codec = new mxCodec(document);
codec.decode(document.getDocumentElement(), stylesheet);
mxIGraphModel model = new mxGraphModel();
mxGraph graph = new mxGraph(model, context.stylesheet);
is = new InputSource(new StringReader(diagramText));
document = documentBuilder.parse(new InputSource(is));
codec = new mxCodec(document);
codec.decode(document.getDocumentElement(), model);
final Document svgDocument = documentBuilder.newDocument();
mxCellRenderer.drawCells(
graph,
null,
1d,
null,
new mxCellRenderer.CanvasFactory() {
#Override
public mxICanvas createCanvas(int width, int height) {
Element root = output.createElement("svg");
String w = Integer.toString(width);
String h = Integer.toString(height);
root.setAttribute("width", w);
root.setAttribute("height", h);
root.setAttribute("viewBox", "0 0 " + w + " " + h);
root.setAttribute("version", "1.1");
root.setAttribute("xmlns", "http://www.w3.org/2000/svg");
root.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
output.appendChild(root);
mxSvgCanvas canvas = new mxSvgCanvas(svgDocument);
canvas.setEmbedded(true);
return canvas;
}
});
return svgDocument; // this is the result
However, as SergGr pointed, Java implementation of mxgraph library doesn't contain some useful shapes. Their drawing rules are described by JavaScript functions in Shape.js.
I tried to execute that JavaScript in ScriptEngine shipped in Java standard library. Unfortunately this idea didn't work, because the JavaScript code somewhere deep inside interacts with browser.
But if we run the code in a browser, it works well. I did it successfully with HtmlUnit.
Write a JavaScript function to call from Java:
function convertToSVG(diagramText, stylesheetText) {
var stylesheet = new mxStylesheet();
var doc = mxUtils.parseXml(stylesheetText);
var stylesheetRoot = doc.documentElement;
var stylesheetCodec = new mxCodec(doc);
var dom = document.implementation;
stylesheetCodec.decode(stylesheetRoot, stylesheet);
doc = dom.createDocument(null, "div", null);
var model = new mxGraphModel();
var graph = new mxGraph(doc.documentElement, model, "exact", stylesheet);
doc = new DOMParser().parseFromString(diagram, "text/xml");
var codec = new mxCodec(doc);
codec.decode(doc.documentElement, model);
doc = dom.createDocument("http://www.w3.org/2000/svg", "svg", null);
var svgRoot = doc.documentElement;
var bounds = graph.getGraphBounds();
svgRoot.setAttribute("xmlns", "http://www.w3.org/2000/svg");
svgRoot.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
svgRoot.setAttribute("width", bounds.width);
svgRoot.setAttribute("height", bounds.height);
svgRoot.setAttribute("viewBox", "0 0 " + bounds.width + " " + bounds.height);
svgRoot.setAttribute("version", "1.1");
var svgCanvas = new mxSvgCanvas2D(svgRoot);
svgCanvas.translate(-bounds.x, -bounds.y);
var exporter = new mxImageExport();
var state = graph.getView().getState(model.root);
exporter.drawState(state, svgCanvas);
var result = new XMLSerializer().serializeToString(doc);
return result;
}
Load this text into String and run the following code
String jsFunction = getAsString("convertToSVG.js");
Path file = Files.createTempFile("44179673-", ".html"); // do not forget to delete it
String hmltText = "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
+ "<head><title>Empty file</title></head><body/></html>";
Files.write(file, Arrays.asList(htmlText));
WebClient webClient = new WebClient(); // net.sourceforge.htmlunit:htmlunit
HtmlPage page = webClient.getPage(file.toUri().toString());
String initScript = ""
+ "var mxLoadResources = false;"
+ "var mxLoadStylesheets = false;"
+ "var urlParams = new Object();";
page.executeJavaScript(initScript);
page.executeJavaScript(getAsString("mxClient.min.js"));
page.executeJavaScript(getAsString("Graph.js")); // Shape.js depends on it
page.executeJavaScript(getAsString("Shapes.js"));
ScriptResult scriptResult = page.executeJavaScript(jsFunction);
Object convertFunc = scriptResult.getJavaScriptResult();
Object args[] = new Object[]{ diagramText, stylesheetText };
scriptResult = page.executeJavaScriptFunction(convertFunc, null, args, null);
String svg = scriptResult.getJavaScriptResult().toString();
The code above seems to work well for me.

Dynamic XML Template in TVML/TVJS

Does anyone know how to Dynamically generate a template in an apple tv app using TVJS/TVML? Basically I want to hit my API, get back an array of objects and then insert that data into my XML template.
I've been searching for info on how to accomplish it but have come up short. I've found many tutorials that use hard coded images, videos, etc but nothing dynamically generated.
Any help would be appreciated.
Finally, I've figured this out. It wouldn't be difficult to generate a template on-the-fly, but instead I wanted to reuse the Presenter and the ResourceLoader, and to have the template as a *.xml.js file. Here is the solution I managed to arrive at.
For the initial view, I used a catalogTemplate, as demonstrated in Ray Wenderlich's tutorial. Instead of conference talks, however, I was displaying categories of men's and women's merchandise. Once a category was selected, I wanted to display a stackTemplate with a number of options for that category. The problem was how to pass any information, the title of the category in the simplest case, to the second template.
In the first template, I had the lockups configured like so:
<lockup categoryTitle="Women: Dresses" categoryDir="w-dresses">
<img src="${this.BASEURL}images/dresses.jpg" width="230" height="288" />
<title>Dresses</title>
</lockup>
In application.js, I had a listener attached, in the same way how tutorials show:
doc.addEventListener("select", Presenter.load.bind(Presenter));
Here is the second template (Category.xml.js):
var Template = function(categoryTitle) {
return `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<stackTemplate>
<banner>
<title>${categoryTitle}</title>
</banner>
</stackTemplate>
</document>`
}
This is a JavaScript, so in your case you can pass into the function, say, an array of values and then construct the template accordingly. The tricky part was to pass a value.
First, I made a couple of changes to the ResourceLoader (this can be done better, of course, it's just a proof of concept). I simply added categoryTitle as an additional parameter to the top-level function and when calling the Template:
ResourceLoader.prototype.loadResource = function(resource, callback, categoryTitle) {
var self = this;
evaluateScripts([resource], function(success) {
if(success) {
var resource = Template.call(self, categoryTitle);
callback.call(self, resource);
} else {
var title = "Resource Loader Error",
description = `Error loading resource '${resource}'. \n\n Try again later.`,
alert = createAlert(title, description);
navigationDocument.presentModal(alert);
}
});
}
Finally, in the Presenter, in the load, I am passing categoryTitle to the resourceLoader:
load: function(event) {
var self = this,
ele = event.target,
categoryTitle = ele.getAttribute("categoryTitle");
if (categoryTitle) {
resourceLoader.loadResource(`${baseURL}templates/Category.xml.js`, function(resource) {
var doc = self.makeDocument(resource);
self.pushDocument(doc);
}, categoryTitle);
}
},
This works for me.
One final note: for some categories, I had titles with an ampersand, like 'Tops & T-shirts'. Naturally, I replaced the ampersand with an XML entity: 'Tops & T-shirts'. This, however, didn't work, probably because this string was decoded twice: the first time the entity was turned into an ampersand, and on the second pass the single ampersand was flagged as an error. What worked for me was this: 'Tops &amp; T-shirts'!
It is simple if you are using atvjs.
// create your dynamic page
ATV.Page.create({
name: 'homepage',
url: 'path/to/your/json/data',
template: function(data) {
// your dynamic template
return `<document>
<alertTemplate>
<title>${data.title}</title>
<description>${data.description}</description>
</alertTemplate>
</document>`;
}
});
// later in your app you can navigate to your page by calling
ATV.Navigation.navigate('homepage');
Disclaimer: I am the creator and maintainer of atvjs and as of writing this answer, it is the only JavaScript framework available for Apple TV development using TVML and TVJS. Hence I could provide references only from this framework. The answer should not be mistaken as a biased opinion.
I'm using PHP to generate the TVML files dynamically, configuring the output as text/javascript format:
<?php
header("Content-type: application/x-javascript");
[run your PHP API calls here]
$template = '<?xml version="1.0" encoding="UTF-8" ?>
<document>
... [use PHP variables here] ...
</document>';
echo "var Template = function() { return `". $template . "`}";
?>
You can dynamically generate a template by creating a dynamic string that represents the xml in a TVML template.
Review the code in here: https://developer.apple.com/library/prerelease/tvos/samplecode/TVMLCatalog/Listings/client_js_Presenter_js.html#//apple_ref/doc/uid/TP40016505-client_js_Presenter_js-DontLinkElementID_6
This file has functions that can be used to create an XML document that can represent a view.
You can make an XMLHttpRequest (ex: consuming API JSon calls through TVJS-tvOS) bring back some JSON data and then dynamically generate an XML document that conforms to one of the TVML templates. Parse it into an XML document and then navigate to the document.

When using THREE.ObjectLoader, if the model has more than one texture, how do I get them to load properly?

I have exported a model as a Three.js scene. I load it using ObjectLoader. It seems to load fine, but the textures are not applied. When I look at the json file, there are materials listed. Here is the code I have tried.
loader.load( "MyModel.json", function(obj){
var materialsFromFile = new THREE.MeshFaceMaterial(obj.materials);
// create our mesh with the loaded geometry and materials
mesh = new THREE.Mesh(obj.geometry, materialsFromFile);
scene.add(mesh);
});
UPDATE:
I have a fix for this, perhaps someone knows a better way? What I do is: first I traverse the model after loading it
obj.traverse(function(child){ initChild(child); });
In initChild(child) I do this:
if(child.material != null)
{
var childName = child.material.name;
child.material = new THREE.MeshPhongMaterial();
child.material.name = childName;
AssignMap(child.material);
}
In AssignMap(material) I first load the textures, then assign them based on the material name:
var texture_metal = new THREE.ImageUtils.loadTexture("media/texture_metal.jpg");
var texture_glass = new THREE.ImageUtils.loadTexture("media/texture_glass.jpg");
if(material.name == "metal texture")
material.map = texture_metal;
if(material.name == "glass texture")
material.map = texture_glass;
Have I gone mad? Is this is reasonable solution? I had looked all over and couldn't find much regarding using THREE.ObjectLoader() and getting mutiple textures to load correctly.

Accessing properties via a String in AS3

I have an engine I created a while back that loads objects into a container based on XML data. A really quick example of the XML would be like this:
<level>
<object cname="enemies.Robot">
<pos x="200" y="400" layer="mobiles" />
</object>
<object cname="Player">
<pos x="12" y="89" layer="mobiles" />
</object>
</level>
I have a class Environment that has a method loadLevel(data:XML) which I parse the XML through, then the function runs through the XML finding all object nodes and uses getDefinitionByName to determine which Object I want to create based on object.#cname.
From here, I have to manually define each property based on the XML like so;
obj.x = xml.pos.#x;
obj.y = xml.pos.#y;
etc.
I was wondering if there's an inbuilt method for setting a property based on a String. By this I mean something like so:
var mc:MovieClip = new MovieClip();
mc.someInbuiltFunctionThatSetsAProperty("alpha", 0.5);
This way I could change my XML to be more like so:
<object cname="Player">
<props>
<x>200</x>
<y>221</y>
<alpha>7834</alpha>
<health>Something</health>
<power>3</power>
</props>
</object>
And iterate through all the children of props to set all of my properties on the fly.
I know if I create an Object and set properties within it like so:
var obj:Object =
{
var1: "hello",
var2: "there",
name: "marty"
};
That you can then iterate through names/values using the for(String in Object) loop like this:
var i:String;
for(i in obj)
{
trace(i + ": " + obj[i]);
}
/**
* Output:
* var1: hello
* var2: there
* name: marty
*/
Is there maybe something even similar to that?
Surely there's a way, as here's an example of identifying a property using a String:
var ar:Array = [new MovieClip(), new MovieClip()];
ar.sortOn("alpha", Array.ASCENDING);
So just to make my question more to-the-point: I want to be able to get and set properties that I can identify using a String.
Why not using ["string property"] notation :
var mc:MovieClip=new MovieClip()
mc["alpha"] = 0.5 // setter
var alpha:Number=mc["alpha"] // getter
I'm not quite clear on what it is you're looking for exactly, but I have a general sense of what you're getting at and have a few suggestions for you. First, have a look at the documentation for the Object class in the AS3 Language Reference. Look specifically at the propertyIsEnumerable() and setPropertyIsEnumerable() methods. I think that's what you're asking about.
If not, you might want to look into the behavior of dynamic classes, which let you add variables to an object on the fly.

E4X Add CDATA content

Basically I need to define a node name and its CDATA content using variables.
var nodeName:String = "tag";
var nodeValue:String = "<non-escaped-content>";
Naively I thought this would work :
var xml:XML = <doc><{nodeName}><![CDATA[{nodeValue}]]></{nodeName}>
Outputs :
<doc><tag><![CDATA[{nodeValue}]]></tag></doc>
In a previous version of the script designed for FP9 I bypassed the problem by using :
new XMLNode( XMLNodeType.XMLNodeType.CDATA_NODE, nodeValue ); // ...
but this doesn't seem to work in FP10, and I have the feeling the method is somehow depreciated anyway.
Anyone an elegant solution for this ?
how about this:
var xml:XML = <doc><{nodeName}>{nodeValue}</{nodeName}></doc>
trace(xml.toXMLString());
outputs:
<doc>
<tag><non-escaped-content></tag>
</doc>
i admit, this is not CDATA, but i don't see a problem ... parsing requires a little more time, but OTOH, correct escaping much more robust than CDATA ...
the version with XMLNode uses the flash.xml package, which is for backwards compatibility with AS2 ... didn't even notice, it was gone under FP10 ... however, you could use this
var x:XML = new XML("<![CDATA[" + nodeValue + "]]>");
as a replacement and then use appendChild as you would with flash.xml ...
alternatively you could use it e4x style, if you wrap it in a function
function cdata(data:String):XML {
return = new XML("<![CDATA[" + data + "]]>");
}
and then
var xml:XML = <doc><{nodeName}>{cdata(nodeValue)}</{nodeName}></doc>
but personally, i think that strings, that are both text based and relatively short, should be escaped, rather then wrapped in CDATA ...
update:
i don't get your point here
"<" is very different than a "<"
that's what the whole thing is about ... :D ... "<" would be interpreted during parsing, whereas "<" is just reconverted to "<", so after parsing the XML, you will have exactly the same string as before ...
this is my code:
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main():void {
var nodeName:String = "tag";
var nodeValue:String = "<non-escaped-content>";
var xml:XML = <doc><{nodeName}>{cdata(nodeValue)}</{nodeName}></doc>;
trace(cdata("test").toXMLString());
trace(xml.toXMLString());
}
private function cdata(data:String):XML {
return new XML("<![CDATA[" + data + "]]>");
}
}
}
works perfectly for me on flash player 10, compiled with flex sdk 4 ... don't have a flash IDE at hand, but when it comes to pure ActionScript results are almost definitely the same, so it should work (you can use that as your document class, if you want to, or simply instantiate it) ...
btw. the first trace shows, that the second example works, which is also quite obvious, since new XML(<String>) uses the native XML parser to create an XML from the given string ...
here is what the above generates:
<![CDATA[test]]>
<doc>
<tag><![CDATA[<non-escaped-content>]]></tag>
</doc>
works quite good for me ... :)
greetz
back2dos
The above cdata function needs to look like the following, notice the last ">" is escaped in code. Otherwise there's compile errors.
private function cdata(data:String):XML
{
return new XML("<![CDATA[" + data + "]]\>");
}
Thanks, cdata function is very useful. I wrote just new one.
function newNode(nodeName:String,nodeValue:String):XML{
return new XML(<{nodeName}>{cdata(nodeValue)}</{nodeName}>);
}
private function cdata(data:String, nodeName:String):XML{
return new XML( "<"+nodeName+"><![CDATA[" + data + "]]\></"+nodeName+">");
}
work fine :)
Here is another solution
public static function getCDATANode(data:String, tagName:String):void
{
var node:XML = new XML( "<" + tagName + "/>" );
var cdata:XML = new XML("<![CDATA[" + data + " ]]>");
node.appendChild(cdata);
trace("getCDATANode: ", node.toXMLString() );
}
Here's my solution without using functions:
var nodeName:String = "tag";
var nodeValue:String = "<non-escaped-content>";
var xml:XML = <doc><{nodeName}>{new XML("<![CDATA[" + nodeValue + "]]>")}</{nodeName}></doc>;
If you need to replace existing nodes content and keep node attributes you can use:
var newNodeValue:String = "<non-escaped-content>";
var xml:XML = <doc><tag attribute="true">This is node content</tag></doc>;
xml.tag[0].setChildren(new XMLList());
xml.tag[0].appendChild(new XML("<![CDATA[" + newNodeValue + "]]>"));