E4X Добавить содержимое CDATA

В основном мне нужно определить имя node и его содержимое CDATA с помощью переменных.

var nodeName:String = "tag";
var nodeValue:String = "<non-escaped-content>";

Наивно я думал, что это сработает:

var xml:XML = <doc><{nodeName}><![CDATA[{nodeValue}]]></{nodeName}>

Выходы:

<doc><tag><![CDATA[{nodeValue}]]></tag></doc>

В предыдущей версии script, предназначенной для FP9, я обошел проблему, используя:

new XMLNode( XMLNodeType.XMLNodeType.CDATA_NODE, nodeValue ); // ...

но это, похоже, не работает в FP10, и я чувствую, что метод каким-то образом обесценился.

Любое элегантное решение для этого?

Ответ 1

как насчет этого:

var xml:XML = <doc><{nodeName}>{nodeValue}</{nodeName}></doc>
trace(xml.toXMLString());

выходы:

<doc>
  <tag>&lt;non-escaped-content&gt;</tag>
</doc>

Я признаю, что это не CDATA, но я не вижу проблемы... для синтаксического анализа требуется немного больше времени, но OTOH, правильное ускорение намного более надежное, чем CDATA...

версия с XMLNode использует пакет flash.xml, который для обратной совместимости с AS2... даже не заметил, он исчез под FP10... однако вы могли бы использовать этот

var x:XML = new XML("<![CDATA[" + nodeValue + "]]>");

в качестве замены, а затем используйте appendChild, как в случае с flash.xml...

В качестве альтернативы вы можете использовать его в стиле e4x, если вы завернете его в функцию

function cdata(data:String):XML {
    return = new XML("<![CDATA[" + data + "]]>");
}

а затем

var xml:XML = <doc><{nodeName}>{cdata(nodeValue)}</{nodeName}></doc>

но лично я считаю, что строки, которые являются текстовыми и относительно короткими, должны быть экранированы, а затем завернуты в CDATA...


обновление: я не понимаю вашу точку зрения.

"&lt;" сильно отличается от a "<"

, что все дело в...: D... "<" будет интерпретироваться во время разбора, тогда как "&lt;" просто преобразуется в "<", поэтому после разбора XML, у вас будет точно ту же строку, что и раньше...

это мой код:

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 + "]]>");
        }
    }
}

отлично работает для меня на flash-проигрывателе 10, скомпилированном с flex sdk 4... у меня нет флеш-IDE под рукой, но когда дело доходит до чистого результата ActionScript, почти наверняка то же самое, поэтому он должен работать (вы может использовать это как ваш класс документа, если вы хотите, или просто создать его экземпляр)...

кстати. первая трассировка показывает, что второй пример работает, что также совершенно очевидно, так как new XML(<String>) использует собственный синтаксический анализатор XML для создания XML из данной строки...

вот что вышло выше:

<![CDATA[test]]>
<doc>
  <tag><![CDATA[<non-escaped-content>]]></tag>
</doc>

работает неплохо для меня...:)


Greetz

back2dos

Ответ 2

Вышеупомянутая функция cdata должна выглядеть следующим образом: обратите внимание, что последний " > " экранирован в коде. В противном случае возникают ошибки компиляции.

private function cdata(data:String):XML
{
    return new XML("<![CDATA[" + data + "]]\>");                
}

Ответ 3

Спасибо, функция cdata очень полезна. Я написал только новый.

function newNode(nodeName:String,nodeValue:String):XML{
    return new XML(<{nodeName}>{cdata(nodeValue)}</{nodeName}>);
}

Ответ 4

private function cdata(data:String, nodeName:String):XML{
    return new XML( "<"+nodeName+"><![CDATA[" + data + "]]\></"+nodeName+">");
}

отлично работает:)

Ответ 5

Вот еще одно решение

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() );
}

Ответ 6

Здесь мое решение без использования функций:

var nodeName:String = "tag";
var nodeValue:String = "<non-escaped-content>";
var xml:XML = <doc><{nodeName}>{new XML("<![CDATA[" + nodeValue + "]]>")}</{nodeName}></doc>;

Если вам нужно заменить существующее содержимое узлов и сохранить атрибуты node, вы можете использовать:

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 + "]]>"));