Преобразование XML-данных в строгий гибкий тип

#xml #apache-flex #data-structures

Вопрос:

Проект, над которым я работаю, будет извлекать XML с веб-сервера и создавать на его основе хранилище данных. Данные будут иметь определенные основные поля, но должны быть расширяемыми… например, у меня есть и позже, возможно, захочется иметь, который добавляет дополнительные поля.

В приложении Flex я не хочу, чтобы центральное хранилище данных работало с объектами XML или просто помещало свойства в объекты. Я хочу иметь сильные типы, например класс Person, которые создаются/заполняются из XML.

Как это можно сделать гибким способом? Может ли Flex автоматически создавать человека из XML, если имена атрибутов совпадают, или мне нужно написать функцию преобразования для, и т. Д.?

Ответ №1:

Я не думаю, что это можно сделать автоматически. Обычно я создаю класс a, чтобы отразить структуру XML, которая у меня есть, а затем создаю метод статического класса для создания экземпляра объекта с заданным XML-узлом. Например:

 package {

  public class Foo{

     public function Foo(barparam1:String, barparam2:uint, barparam3:String, barparam4:Number){
       this._bar1 = barparam1;
       this._bar2 = barparam2;
       this._bar3 = barparam3;
       this._bar4 = barparam4;
       }

     protected var _bar1:String;
     protected var _bar2:uint;
     protected var _bar3:String;
     protected var _bar4:Number;

     public function get bar1():String{ return this._bar1; }
     public function get bar2():uint    { return this._bar2; }
     public function get bar3():String  { return this._bar3; }
     public function get bar4():Number  { return this._bar4; }

     public function toString():String{
        return "[Foo bar1:""   this.bar1   "", bar3:""   this.bar3   "", bar2:"   this.bar2   ", bar4:"   this.bar4   "]";
        }

     public static function createFromXml(xmlParam:XML):Foo{

        /* XML Format:
          <foo bar1="bar1value" bar2="5">
            <bar3>bar3 data</bar3>
            <bar4>10</bar4>
          </foo>
        */

       return new Foo(xmlParam.@bar1, xmlParam.@bar2, xmlParam.bar3[0], xmlParam.bar4[0]);
       }
    }
  }
 

Ответ №2:

Если вы не привязаны к XML (например, у вас есть сервер приложений вместо файлового сервера), вы можете рассмотреть возможность использования AMF (Формат сообщений о действиях) для передачи данных. Есть несколько проектов, которые предоставляют AMF серверам, включая собственные версии Adobe Blaze DS и варианты с открытым исходным кодом сообщества, такие как OpenAMF, AMFPHP, PyAMF и так далее. Это даст вам возможность передавать пользовательские объекты с сервера на Flex, автоматический анализ типов данных и безопасность типов. Взгляните на это сравнение вариантов передачи данных, чтобы получить представление об относительных достоинствах.

Тем не менее, XML может быть очень полезен для таких вещей, как данные конфигурации приложений, и в тех случаях, когда вы не используете сервер приложений. Я согласен с другим плакатом, где я немедленно разберу xml на соответствующие структуры вручную. Обычно я храню их с помощью VO после исправления (для объекта Value) и оставляю их открытыми. Я часто делаю это иерархически.

 package model.vo
{
public class ConfigVO
{
    public var foo:String;
    public var bar:int;
    public var baz:Boolean;
    public var sections:Array;

    public function ConfigVO(xml:XML)
    {
        parseXML(xml);
    }

    private function parseXML(xml:XML):void
    {
        foo = xml.foo;
        bar = xml.bar;
        baz = (xml.baz == "true");

        sections = [];
        for each(var sectionXML:XML in xml.section)
        {
            sections.push(new SectionVO(sectionXML));
        }
    }
}
}

package model.vo
{
public class SectionVO
{
    public var title:String;

    public function SectionVO(xml:XML)
    {
        parseXML(xml);
    }

    private function parseXML(xml:XML):void
    {
        title = xml.@title;
    }
}
}
 

В прошлом я видел системы, которые привязывали имена XML-элементов к определениям классов. Они обычно используют своего рода самоанализ класса, чтобы определить, какие свойства считывать с xml, или у них будут некоторые статические свойства класса, которые сопоставляют свойства экземпляра с тегами или атрибутами xml. По моему опыту, от них гораздо больше хлопот, чем пользы. Для добавления нового общедоступного свойства требуется всего 2 секунды, а для чтения данных из атрибута или дочернего тега-одна строка. Я предлагаю избегать таких сложных схем, но для полноты картины приведу простой пример.

 package model
{
    public class XMLReader
    {
        // maps <tagname> to a class 
        private static var elementClassMap:Object =
        {
            "section": SectionVO,
            "person": PersonVO
        };

        public var parsedElements:Array;

        public function XMLReader(xml:XML)
        {
            parsedElements = [];
            parseXML(xml);
        }

        private function parseXML(xml:XML):void
        {
            var voClass:Class;
            for each(var element:XML in xml.children())
            {
                voClass = elementClassMap[element.name().localname];
                if(voClass)
                {
                    parsedElements.push(new voClass(element));
                }
            }
        }
    }
}
 

Ответ №3:

Ответ №4:

Создание надежных типов данных имеет ряд преимуществ, наиболее важными из которых являются завершение кода и проверка синтаксиса во время компиляции. Ручные сопоставления могут быть выполнены, но должны быть сгенерированы (и, следовательно, на самом деле больше не являются ручными), чтобы рано или поздно не выйти из синхронизации.

Библиотеки общих преобразований, основанные на самоанализе, универсальны, просты в использовании и должны быть достаточными для большинства случаев использования.

JAXB является стандартом для Java. ASXB обеспечивает легкую реализацию этой идеи для мира Actionscript. Он использует явные объекты в качестве объектов с аннотациями для (un)маршалирования объектов из XML и в XML.

Если вы вынуждены использовать XML на проводе, я бы предложил рассмотреть ASXB поближе. Если вы свободны в выборе формата и имеете поддержку на стороне сервера, вам следует выбрать собственный формат AMF, так как он напрямую поддерживается на языке и имеет гораздо меньшие накладные расходы во время транспортировки.

В нашем текущем проекте мы написали небольшие генераторы кода, которые используют внешний API на стороне Java (самоанализ исходного кода, чтобы также скопировать Javadoc) и генерировать классы AS из него во время процесса сборки. Таким образом, было легко переключиться с AMF на XML, когда внешние требования вынудили нас сделать это.

PS: не забудьте добавить параметры компилятора в файл конфигурации flex, чтобы сохранить аннотации

Ответ №5:

АсБеанГен может это сделать. Он генерирует объекты значений для XML-файлов, управляемых DTD.

Ответ №6:

Некоторое время назад я начал работать над библиотекой Flex, которая поможет сериализовать и десериализовать объекты сценариев действий в XML и из XML. Все, что вам нужно сделать, это создать объекты модели, поместить некоторые аннотации в поля, чтобы сериализатор знал, как вы хотите сериализовать поле (элемент, атрибут, какое имя и т. Д.), И вызвать процесс сериализации (de).

Я думаю, что это соответствует вашим потребностям.

Если вы хотите, вы можете проверить это по адресу http://code.google.com/p/flexxb/.

Надеюсь, это окажется полезным.