E4X Добавить CDATA контент

В основном мне нужно определить имя узла и его содержимое 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>

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

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

но это не работает в FP10, и я чувствую, что метод все равно обесценивается.

Кто-нибудь изящное решение для этого?

6 ответов

Решение

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

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;" сильно отличается от "<"

в этом вся суть...: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 Player 10, скомпилированном с Flex SDK 4 ... нет IDE Flash под рукой, но когда дело доходит до чистого ActionScript результаты почти наверняка одинаковы, поэтому он должен работать (вы можете использовать это как ваш класс документа, если вы хотите, или просто создать его экземпляр) ...

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

вот что генерирует вышесказанное:

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

работает довольно хорошо для меня...:)


Greetz

back2dos

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

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

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

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

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

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

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

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

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

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

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() );
}
Другие вопросы по тегам