Flex cookbook entry: How to know QName instance origins.
В ActionScript 3 у простого типа QName есть возможность хранить информацию о происхождении экземпляра, т.е. можно узнать, это имя атрибута или узла/свойства. Но я не смог найти простого и прямого способа «выдернуть» эту информацию из экземпляра QName. Поэтому дальше горожу свой огород.
В классе flash.utils.Proxy есть метод flash_proxy::isAttribute, который возвращает булево значение – имя атрибута передано или нет. Я воспользовался этим методом немного не по назначению и появился метод QNameUtils.isAttribute:
package aw.utils{ import flash.utils.Proxy; import flash.utils.flash_proxy; public class QNameUtils extends Object{ static private const proxyIsAttributeMethod:Function = (new Proxy()).flash_proxy::isAttribute; static public function isAttribute(name:QName):Boolean{ return proxyIsAttributeMethod(name); } ... } }
Далее, стало интересно, как можно влиять на это значение – простого способа, опять таки, нет. Единственный способ , это создать в XML атрибут с таким же именем и потом получить xml.@attribute.name() – вот это будет имя атрибута. Но появилась проблема в том, что XML атрибут не может находиться в пространстве имён NULL(это обозначает «любое пространство имён»), а экземпляр QName может ссылаться на него и при создании такого атрибута он перемещается в базовое пространство имён(с uri = “”). И опять на помощь спешит flash.utils.Proxy – при попытке запросить атрибут он сам создаёт имя атрибута без изменений пространства имён или локального имени. В общем, я опять воспользовался обходным путём.
package aw.utils{ import flash.utils.Proxy; import flash.utils.flash_proxy; public class QNameUtils extends Object{ ... static private var _converter:ConverterProxy; static public function setAttribute(name:QName, isAttribute:Boolean=true):QName{ if(isAttribute){ if(!_converter) _converter = new ConverterProxy(); _converter.@[name]; name = _converter.getLastUsedName(); }else name = new QName(name.uri, name.localName); return name; } ... } } import flash.utils.Proxy; import flash.utils.flash_proxy; class ConverterProxy extends Proxy{ private var _lastName:QName; public function ConverterProxy():void{ super(); } public function getLastUsedName():QName{ return this._lastName; } override flash_proxy function getProperty(name:*):*{ this._lastName = name; return null; } }
Создал скрытого наследника flash.utils.Proxy исключительно для целей конвертации и использую его в методе QNameUtils.setAttribute.
В общем, встречайте aw.utils.QNameUtils, класс для работы со скрытым ключом атрибута в экземплярах QName.
Вот небольшой пример его работы:
import aw.utils.QNameUtils; var name:QName; var xml:XML = <node attr="value"/>; name = xml.@attr.name(); // получаем имя атрибута trace(QNameUtils.isAttribute(name)); // true name = new QName('', 'attr'); // создаём обычный экземпляр QName trace(xml.@[name]); // value name = QNameUtils.create('', 'attr', true); // создаём экземпляр QName для атрибута trace(xml[name]); // value
Как видите, нет необходимости хранить информацию о происхождении отдельно или указывать при запросе – можно в один способ запросить узел и атрибут по динамическому имени без дополнительных хранилищ данных, ведь всё хранится прямо в экземпляре QName. А вопрос сериализации QName с ключом пусть ляжет на конкретного разработчика в конкретном случае , если кто решит воспользоваться.
Метки: attribute, aw.utils.QNameUtils, flash.utils.Proxy, namespace, Proxy, QName, QNameUtils, uri
[...] атрибуты. Следует заметить, что QNameCollection игнорирует указатель атрибута в QName и если попробовать добавить атрибут, он просто [...]