User's collector

Внимание!   Данная опция будет доступна только после того, как вы авторизуетесь.
   запомнить меня 
8 октября 2007

XML и пространства имен: тонкости работы

Начну с обычного примера:

Actionscript:
  1. package
  2. {
  3.     public class XMLExample
  4.     {
  5.         public function XMLExample ()
  6.         {
  7.             var someXml:XML =
  8.                 <root>
  9.                     <item id="id" content-type="image/png">image
  10.                 </root>;
  11.         }
  12.     }
  13. }

Получить значение аттрибута id тэга item можно так:

Actionscript:
  1. trace(someXml.item.@id);

Значения аттрибута content-type содержит символ "-" поэтому мы используем такую конструкцию:

Actionscript:
  1. trace(someXml.item.@["content-type"]);

Все это хорошо до тех пор, пока в xml не появляется xmlns, из-за которого приведенный выше код перестает работать на вполне законных основаниях:

Actionscript:
  1. var someXml:XML =
  2.         <root xmlns="http://uri">
  3.             <item id="id" content-type="image/png">image</item>
  4.         </root>;

Обратившись к первоисточнику я узнал, что класс верхнего уровня Namespace мне поможет:

Actionscript:
  1. package
  2. {
  3.     public class XMLExample
  4.     {
  5.         private var ns:Namespace = new Namespace("http://uri");
  6.        
  7.         public function XMLExample ()
  8.         {
  9.             var someXml:XML =
  10.                 <root xmlns="http://uri">
  11.                     <item id="id" content-type="image/png">image</item>
  12.                 </root>;
  13.            
  14.             default xml namespace = ns;
  15.  
  16.             // Вот это прекрасно работает
  17.             trace(someXml.item.@id);
  18.            
  19.             <strong>// А вот для content-type работать отказывается
  20.             trace(someXml.item.@["content-type"]);
  21.            
  22.             // И так тоже результат нулевой
  23.             trace(someXml.item.attribute("content-type"));</strong>
  24.         }
  25.     }
  26. }

Хорошо, подумал я и решил проверить видны ли атрибуты в принципе:

Actionscript:
  1. var l:int = someXml.item.attributes().length();
  2. for(var i:int = 0; i <l; i++)
  3.     trace("Attribute #" + i + ": " + someXml.item.attributes()[i].name());

Трэйсы исправно вывели:

CODE:
  1. Attribute #0: id
  2. Attribute #1: content-type

Ага! — сказал я и решил попробывать следующую строку:

Actionscript:
  1. trace(someXml.item.@[someXml.item.attributes()[1].name()]);

И как вы наверно догадались этот трейс выводит: image/png.

Снова обращаюсь к первоисточнику в попытках узнать, что же возвращает такое name(), что это открывает мне доступ к значению необходимого аттрибута. Согласно сигнатуре и описанию данный метод возвращает самый обычный Object. Или нет? Вот цитата:

Returns
Object - qualified name is either a QName or null.

Быстренько прокручиваю к разделу See also и нахожу в нем линк на еще один класс верхнего уровня Qname (все таки asdoc классная документация), который и стал решением моей проблемы. И так внимание правильный ответ:

Actionscript:
  1. trace(someXml.item.@[new QName("", "content-type")]);

Вывод: чтение документации требует максимальной внимательности и предельной концентрации.

Удачи! ;)

Теги:


5 комментариев к записи:

Rostislav Siryk [ 11 октября , 2007 в 00:00 ]

И у тебя отлично выводится код в комментах )

Rostislav Siryk [ 10 октября , 2007 в 23:58 ]

Так точно. QName и Namespace - важные части подхода E4X.

Во взрослых XML-ях (например, GIG-данные от MapServer) без нескольких используемых вперемешку неймспейсов не обходится; поэтому я создал для себя утилитную функцию, что возвращает элементы по их нейпмпейсу, предварительно находя их через QName (сейчас проверим, как у тебя код постится ):

Actionscript:
  1. /**
  2. * Helps to get the elements located in namespaces like
  3. * @param    xmlList
  4. * @param    nsName
  5. * @param    nsURI
  6. * @param    elementName
  7. * @return List of found elements
  8. */
  9. protected function getElementsByQName(xmlList:XML, nsName:String, nsURI:String, elementName:String):XMLList
  10. {
  11.     var elNamespace:Namespace = new Namespace(nsName, nsURI);
  12.     var elQName:QName = new QName(elNamespace, elementName);
  13.     return xmlList.elements(elQName) as XMLList;
  14. }

Отличная хрень этот QName :)

Vooparker [ 11 октября , 2007 в 09:32 ]

Рост, спасибо за функцию :)
ЗЫ: Код в каментах можно и подсвечивать - [ as][ /as] (без пробелов).

Rostislav Siryk [ 14 октября , 2007 в 15:53 ]

Крута :)

zz [ 15 октября , 2007 в 20:04 ]

Кста, длиные строки ппц,
лучше скролбары в контейнере

Оставьте свой комментарий:

Имя: *
* — обязательно для заполнения
Электропочта: *
Сайт:
Сообщение *
Коментировать
Коментировать