Статьи

AS3 101: XML — Basix

Ну, привет, добрый путешественник ActionScript! За последние 6 месяцев вы уже прошли через много странных пейзажей, но если все пошло по плану, вы стали сильнее и готовы к следующему испытанию. Здесь, в 7-й части, мы завершим тему XML.


По мере прохождения серии AS3 101 мы позволяли себе становиться все более гибкими, создавая программы, которые реагировали на обновления более плавно, чем предыдущие. Вот где это становится действительно интересным: если мы можем сохранить данные, которые делают приложение внешним по отношению к SWF, то создание обновлений становится вопросом редактирования текстового файла (или работы с базой данных), а не редактирования ActionScript и перекомпиляции SWF.

В этом нет ничего нового, но я предполагаю, что это ново для вас, и именно поэтому вы здесь. Я предполагаю, что вы довольны всем остальным, что мы уже рассмотрели в серии AS3 101 — особенно темам «Список отображения», «Массивы» и «Петли». Но я предполагаю, что вам нужно формальное введение в сам XML, а также как с ним работать в ActionScript.

Для этого мы рассмотрим это в трех широких частях. Сначала посмотрим, как пишется XML. Далее мы рассмотрим методы, доступные нам в ActionScript 3 для работы с XML. Наконец, мы соберем все вместе для создания функции продукта на основе XML, предварительный просмотр которой можно увидеть ниже.


Мы должны начать здесь. В XML аббревиатура расшифровывается как «Расширяемый язык разметки», и, предположительно, «XML» звучит круче, чем «EML». Язык разметки — это язык, где разметка какого-либо рода перемежается с обычным текстом, давая текстовую структуру и / или атрибуты. Это приводит к созданию комментариев к тексту, которые отличаются от самого текста. Как обычно, в Википедии есть более полное и элегантное описание языков разметки.

Скорее всего, вы знакомы с одним языком разметки: HTML (расшифровывается как Hyper Text Markup Language). В этом случае теги (те биты, которые начинаются с < и заканчиваются > ) являются разметкой. Если вы знаете HTML, у вас не возникнет проблем с получением XML, поскольку синтаксис идентичен. На самом деле, XML и HTML имеют общего предка в SGML. А XHTML — это просто HTML, переписанный так, чтобы он соответствовал стандартам XML (HTML был гораздо более легкомысленным в некоторых вещах, а XML — нет).

Разметка в XML будет знакома, но к этой «расширяемой» идее может потребоваться некоторое привыкание. Суть в том, что даже несмотря на то, что существуют определенные правила в том, как должен быть написан XML, нет никаких правил относительно того, какова фактическая разметка. Это отличается от HTML, где определено, что <p> является тегом абзаца, а <a> является тегом привязки (или ссылки). XML не определяет предустановленные теги. Вы можете написать свои собственные теги и структурировать их так, как считаете нужным. Это позволяет вам создать XML-документ, который точно соответствует вашей структуре данных. Это то, что расширяется в XML.

Сказав это, есть несколько языков на основе XML, которые имеют предопределенные теги. Одно уже упоминалось: XHTML. XHTML — это просто XML с такими вещами, как теги <p> и <a> . Другим языком на основе XML, который может заинтересовать разработчиков Flash, является MXML, синтаксис разметки, используемый для создания приложений Flex. MXML, опять же, просто XML, хотя он поставляется с несколькими предопределенными тегами, и попытка использовать тег, который не имеет определения, приводит к ошибкам. Но самое замечательное в том, что, как только вы освоите XML, для изучения языков на основе XML не потребуется много времени.

Для более технического ознакомления с языком XML см. Официальную спецификацию w3 .


Мы напишем документ XML в первой половине этого урока, который мы будем использовать во второй половине для загрузки во Flash.

Откройте новый текстовый файл и сохраните его в выбранном вами месте как products.xml .

Самое первое, что мы добавим, — это объявление XML:

1
<?xml version=»1.0″ encoding=»UTF-8″?>

Flash на самом деле будет отлично работать без этой строки. Тем не менее, это хорошая форма, чтобы убедиться, что это там. Это котельная плита; у любого редактора, достойного внимания, будет шаблон XML, который предоставляет эту строку для вас.

Насколько мне известно, нет другого значения для версии, и кодировка обычно будет UTF-8. Тем не менее, стоит отметить, что если ваш текстовый файл не имеет кодировки UTF-8 — например, ISO-8859-1 — вам может потребоваться изменить эту строку (или перекодировать ваш файл в формат UTF-8). Кодировка текста — это тема, выходящая за рамки данного руководства. Это тема, которую следует пересмотреть, однако. Программист зарабатывает на жизнь текстовыми файлами, поэтому полезно знать кодировку текста. Больше информации о кодировке текста можно найти здесь .


Что за элемент? Если вы знаете язык HTML, элемент — это что-либо, определенное набором тегов, например, <div>. Элемент включает в себя все, от открывающего тега до соответствующего закрывающего тега, поэтому элемент содержит как разметку (тег), так и содержимое этого тега. Существует два ключевых типа элементов: открытые элементы и закрытые элементы.

Открытый элемент поставляется с соответствующим набором тегов, таких как <p> … </ p>, где <p> — открывающий тег, а </ p> — закрывающий тег. Таким образом, знак «меньше» (в дальнейшем именуемый скобкой угла раскрытия) является первым символом тега. Далее следует имя элемента (в нашем примере это было «p», но помните, что поскольку XML является расширяемым , имя может быть практически любым, состоящим из букв, цифр, дефисов и подчеркиваний). Тег закрывается знаком «больше» (скобка угла закрытия). Тег в целом открывает элемент. После открывающего тега может быть контент, но в какой-то момент элемент должен закрыться.

Это важно: в HTML вы можете быть ленивыми по поводу закрытия тегов. XML не так простителен. Каждый элемент, который вы открываете, должен быть закрыт.

Чтобы закрыть узел, вы создаете еще один тег с тем же именем, только между открывающей угловой скобкой и именем узла есть косая черта: </ p>

Элементы должны быть закрыты в том порядке, в котором они открыты. Элементы могут быть вложенными, и для этого нужно открыть один элемент, а затем другой. При их закрытии сначала закрывается второй элемент, затем первый элемент. Например:

1
2
3
4
5
6
<a>
    <b>
        <c>
        </c>
    </b>
</a>

Обратите внимание, что мы открыли элемент a , затем элемент b , а затем элемент c . Когда приходит время обернуть все это, нам нужно закрыть их в обратном порядке: c, затем b и, наконец, a .

Обратите внимание, что обычно делается отступ для вложенного элемента, используя символ табуляции или определенное количество пробелов. Это делается для удобства чтения, так же, как обычно делается отступ для содержимого функции или тела цикла. Но, как и в ActionScript, этот пробел в значительной степени игнорируется, и вышеприведенное можно написать так же правомерно, как:

1
<a><b><c></c></b></a>

Как упоминалось в начале этого шага, существует такая вещь, как пустой тег или самозакрывающийся тег. Это тег, который не содержит контента. В HTML-земле у нас есть теги image и break в качестве примеров:

1
<img src=»http://activetuts.s3.amazonaws.com/tuts/044_AS3101XML/Tutorial/some.jpg» />

Синтаксис здесь — это просто один тег с косой чертой в качестве последней вещи перед закрывающей угловой скобкой. Тег открывается и закрывается все за один шаг. Поэтому никакой контент не может быть вложен внутрь. Бит «src =» http://activetuts.s3.amazonaws.com/tuts/044_AS3101XML/Tutorial/ на самом деле не является контентом, это атрибут. Мы доберемся до них через минуту.


Каждый XML-документ должен иметь один и только один корневой элемент. Этот элемент будет инкапсулировать все данные в вашем документе. Подумайте о HTML: есть один элемент, который оборачивает все это. Это корневой элемент.

В этом руководстве мы составим список продуктов XML. Итак, чтобы несколько обобщенно сослаться на весь набор данных, мы напишем это:

1
2
3
<products>
  
</products>

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

Важно знать, что весь наш набор данных поместится между начальным и конечным тегами этого элемента, вкладок и всего. Таким образом, неплохо подумать над названием элемента. У нас просто будет список продуктов, поэтому «продукты» имеют смысл. Но если бы он имел список продуктов и список категорий, то, возможно, называть корневой элемент «продукты» не имеет смысла, так как мы бы, вероятно, использовали «продукты» для вложенного элемента в списке продуктов.

При этом не существует правила, согласно которому нельзя повторно использовать имена элементов. Тем не менее, обычно легче читать, если у вас есть продуманные названия элементов.


Теперь давайте начнем добавлять некоторые данные. Мы добавим один элемент продукта в документ. Этот элемент будет вложен внутрь элемента products. Элемент, который мы добавляем, будет таким:

1
2
3
<product>
  
</product>

Опять же, мы оставляем место для вложенных элементов, так что вторая строка имеет символ табуляции. При добавлении ко всему документу это будет выглядеть примерно так:

1
2
3
4
5
<products>
    <product>
  
    </product>
</products>

Теперь мы можем добавить несколько деталей о данном продукте. Мы добавим имя, ссылку на информацию о продукте и URL-адрес изображения. Мы добавим описание в несколько шагов.

Мы просто добавим элементы к элементу product и присвоим каждому значение:

1
2
3
4
5
6
7
<products>
    <product>
        <name>Falling Snow Effect</name>
        <link>http://activeden.net/item/as3-as2-falling-snow-effect/69077?id=69077&ref=activetuts</link>
        <image>falling-snow-effect.jpg</image>
    </product>
</products>

Итак, мы даем продукту некоторые детали. Поскольку элементы <name>, <link> и <image> вложены в элемент <product>, они «принадлежат» к <product>. Через несколько шагов мы добавим больше элементов продукта. У каждого будет свое имя, ссылка и элементы изображения. Структура данных, в которую вложены эти элементы, сохранит каждое имя, связанное с нужным продуктом.


Как оказалось, узел <link> будет проблематичным. Если у вас есть удобный валидатор XML, продолжайте и запустите его. Вы получите ошибку с эффектом «ожидаемая точка с запятой». Я использую TextMate для редактирования кода, и при запуске команды Tidy из пакета XML будет отображаться следующая ошибка:

XML-пакет TextMate также имеет команду «Validate Syntax», которая будет выполнять аналогичную функцию, но в конечном итоге приведет к ошибке из-за отсутствия DTD (декларации типа документа). Тем не менее, Tidy будет «очищать» ваш файл после успешной проверки, вставляя отступы и удаляя пустые строки. Вы можете или не можете оценить это.

Фактически, вы также можете видеть на скриншоте выше, что TextMate также выделяет амперсанд как недействительный (с сплошным красным фоном).

Это на самом деле причина ошибки из-за того, что называется сущностями .

Вы, вероятно, уже знакомы с сущностями из HTML, даже если вы не знакомы с именем. Они почти одинаковы в XML. Сущность — это специальный код, который представляет специальный символ. Например, в HTML вы можете ввести обычный старый ключ двойной кавычки, и все будет в порядке. Но если вы хотите использовать «фигурные» кавычки, даже если вы знали, как их печатать (Option-left-square-brace и Option-Shift-left-square-brace на Mac), вы не можете быть уверены, что Процессор XML, открывающий файл, будет корректно обрабатывать символ (из-за кодировки текста и другой черной магии… не беспокойтесь о том, почему сейчас). Вместо этого вы можете ввести сущность, которая представляет фигурные скобки:

1
&ldquo;

и

1
&rdquo;

Например…

1
&ldquo;That’s what she said…&rdquo;

Фактически, мы могли бы сделать это утверждение еще красивее с большим количеством сущностей, чтобы представить апостроф и эллипсы (три периода … правильный способ печатать, с помощью одного символа, называемого эллипсами. Это вариант точка с запятой на Mac, Кстати).

1
&ldquo;That&apos;s what she said&hellip;&rdquo;

Это выглядит некрасиво прямо сейчас, но запустите это через анализатор HTML, и вы получите:

«Это то, что она сказала…»

Который чуть более читабелен, чем:

«Это то, что она сказала…»

XML имеет несколько встроенных сущностей, которые в основном состоят из символов, которые имеют особое значение в спецификации XML:, «, ‘и &. Обратите внимание, что символы кавычки являются» прямыми «, а не» вьющимися «.

Это, наконец, доходит до нашей проблемы. Амперсанд является зарезервированным символом в XML. Он зарезервирован для указания начала объекта. К счастью, сущность амперсанда предопределена, и нам просто нужно убедиться, что мы заменим фактический амперсанд его сущностью:

1
<link>http://activeden.net/item/as3-as2-falling-snow-effect/69077?id=69077&ref=activetuts</link>

Пять сущностей, определенных в XML, такие же, как в HTML, но вот краткий справочник:

1
2
3
4
5
< &lt;
> &gt;
» &quo;
‘ &apos;
& &amp;

В качестве последнего замечания по этому вопросу, классная вещь с XML-сущностями заключается в том, что вы можете определять свои собственные. Мы не будем вдаваться в эту тему, но XML допускает не только односимвольную замену, но даже целые куски текста. В этом отношении сущности могут действовать как переменные (или, точнее, константы); вместо того, чтобы вводить имя автора каждый раз, когда это происходит, поместите имя в объект и используйте объект. Это круто, но выходит за рамки нашего руководства (некоторые могут утверждать, что весь этот шаг выходит за рамки нашего руководства).

Для получения дополнительной информации о лицах, посетите Википедию .


Как и было обещано, мы добавим элемент description к элементу product. Но в нашем идеальном мире мы отформатируем это описание с помощью HTML для красивого отображения во Flash. Но подумайте немного об этом … как мы отделим структуру данных XML от разметки HTML, которая на самом деле является частью самих данных, а не структуры? То есть если бы мы написали это:

1
2
3
4
5
6
7
<product>
    <name>Falling Snow Effect</name>
    <link>http://activeden.net/item/as3-as2-falling-snow-effect/69077?id=69077&ref=activetuts</link>
    <image>falling-snow-effect.jpg</image>
<strong> <description><font size=»24″>AS3 / AS2 Falling snow effect</font>
<p> This is an editable flash snow effect.
</product>

Как синтаксический анализатор XML узнает, что <description> и <product> являются XML, и что <font>, <br />, <p> и <a> фактически являются частью содержимого?

(Обратите внимание, что я понимаю, что тег <font> является устаревшим HTML, но это тот тип HTML, который может обрабатывать Flash, и это наш конечный пункт назначения, поэтому мы используем тег <font>)

Проницательные из вас говорят: «Мы могли бы использовать сущности». Да, мы могли бы. Это будет выглядеть примерно так:

1
2
&lt;description&gt;&lt;font size=&quot;24&quot;&gt;AS3 / AS2 Falling snow effect&lt;/font&gt;
&lt;p&gt;

И это будет технически работать. Но помните тот бит о XML, который читается? Я бы сказал, что выше не читается. Одна или две сущности … хорошо. Все эти сущности … не так много.

К счастью, есть и другой способ. И вы, наверное, уже знаете его название, потому что прочитали название шага. Это называется CDATA . CDATA — это сокращение от Character DATA , и это просто означает, что что-то, указанное как CDATA, будет игнорироваться как данные XML. Другими словами, не обрабатывайте символы, даже если они имеют значение в XML. CDATA — это специальный тег, который начинается так:

1
<![CDATA[

и заканчивается так:

1
]]>

И по всей середине вы можете положить все, что захотите, и процессор XML будет игнорировать это. Таким образом, мы можем поместить наш текст в формате HTML в XML следующим образом:

1
2
3
4
5
6
7
8
<product>
<name>Falling Snow Effect</name>
    <link>http://activeden.net/item/as3-as2-falling-snow-effect/69077?id=69077&ref=activetuts</link>
    <image>falling-snow-effect.jpg</image>
    <description><![CDATA[<font size=»24″>AS3 / AS2 Falling snow effect</font>
<p> This is an editable flash snow effect.
    </description>
</product>

И это гораздо более читабельно.

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

В Википедии, как всегда, есть еще несколько деталей о CDATA .


Нам нужен способ внутренней идентификации продукта. Мы присвоим идентификационный номер элементу продукта. Однако вместо добавления другого элемента мы добавим его в качестве атрибута.

Атрибут — это просто еще один способ связать данные с элементом, но вместо того, чтобы вкладывать элемент в другой элемент, мы можем напрямую прикрепить атрибуты к элементу. Когда вы используете элемент <img> в HTML, вы в конечном итоге также используете атрибуты для указания src. Атрибуты XML работают так же:

1
2
<product id=»42″>
   …

Правила:

  • Во-первых, атрибут должен полностью содержаться в открывающем теге элемента (или в единственном теге пустого элемента)
  • Должны быть пробелы перед началом объявления атрибута (один пробел является нормальным, но любое количество пробелов, табуляций или возвратов в порядке. Я часто использую пробелы, чтобы сделать XML более читабельным)
  • Имя атрибута (в данном случае «id») должно соответствовать тем же правилам именования, что и элементы.
  • Сразу после имени атрибута должен стоять знак равенства («=»). Пробелы не допускаются.
  • Сразу после знака равенства должна быть пара кавычек, которые содержат текстовые данные, содержащиеся в атрибуте.
  • Внутри кавычек вы можете использовать практически любой текст, но помните специальные символы, определенные в XML. Используйте сущности, если это необходимо. Пробелы здесь разрешены.
  • Если один элемент имеет более одного атрибута, разделите каждый набор пробелами, например:
1
<product id=»42″ order=»2″>

Выше только для демонстрационных целей. Мы будем в порядке только с атрибутом id.

Когда вы используете атрибуты и когда вы используете элементы? Это зависит от вас. Мое основное правило заключается в том, что короткие данные могут входить в атрибуты, а более длинные данные — в элементы. Тем не менее, я считаю, что пустые элементы удобны, поэтому я мог бы ошибиться при использовании атрибутов, если это возможно. С другой стороны, синтаксис для чтения атрибутов в ActionScript 3, возможно, (хотя бы немного) более многословен, чем чтение элементов, поэтому, если мне придется использовать один элемент по соображениям длины, я буду стремиться использовать элементы для остальных данные, а также.


Теперь, когда у нас есть один продукт, мы можем создать его список, напечатав (или скопировав и вставив) одну и ту же структуру, только с разными данными. Вид с высоты птичьего полета будет выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<products>
    <product>
        …
    </product>
    <product>
        …
    </product>
    <product>
        …
    </product>
    <product>
        …
    </product>
</products>

Каждый отдельный элемент продукта представляет отдельный продукт, поэтому у нас есть четыре продукта. Каждый из них будет содержать различные данные, но каждый также будет следовать структуре, разработанной нами для первого продукта. Вот весь документ:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?xml version=»1.0″ encoding=»UTF-8″?>
 
<products>
    <product id=»42″>
        <name>Falling Snow Effect</name>
        <link>http://activeden.net/item/as3-as2-falling-snow-effect/69077?id=69077&ref=activetuts</link>
        <image>images/snow.jpg</image>
        <description><![CDATA[<p><font size=»18″>AS3 / AS2 Falling snow effect</font></p>
        <p>This is an editable flash snow effect.
        <p><a href=»event:link»>View product details</a></p>]]></description>
    </product>
  
    <product id=»13″>
 
        <name>Flash Banner Creator</name>
        <link>http://activeden.net/item/flash-banner-creator-and-rotator/49745?id=49745&ref=activetuts</link>
        <image>images/banners.jpg</image>
        <description><![CDATA[
            <p><font size=»18″>Flash Banner Creator and Rotator</font></p>
            <p>This is a very advanced tool to create professional looking dynamic flash banners, slideshows, ads and intros.
            <p><a href=»event:link»>View product details</a></p>]]>
        </description>
    </product>
  
    <product id=»75″>
        <name>XML Countdown</name>
        <link>http://activeden.net/item/as3-as2-falling-snow-effect/69077?id=69077&ref=activetuts</link>
        <image>images/countdown.jpg</image>
        <description><![CDATA[
            <p><font size=»18″>XML Countdown</font></p>
            <p>A dynamic, customisable countdown, with universal time support: Everybody on the internet will countdown to the same moment.
            <p><a href=»event:link»>View product details</a></p>]]>
        </description>
    </product>
  
    <product id=»8423″>
        <name>XML Slideshow with Ken Burns Effect</name>
        <link>http://activeden.net/item/xml-slideshow-with-ken-burns-effect/32354?id=32354&ref=activetuts</link>
        <image>images/kenburns.jpg</image>
        <description><![CDATA[
            <p><font size=»18″>XML Slideshow with Ken Burns Effect</font></p>
            <p>MAIN FEATURES:</p>
            <ul>
                <li>Unlimited pictures</li>
                <li>Highly customizable design via XML only</li>
                <li>You can customize this slideshow in it’s smallest aspects: transitions, speeds, colors, sizes, etc, all via a well structured xml file.</li>
                <li>Awesome Ken Burns effect</li>
            </ul>
            <p>This can become the ultimate header, banner, gallery for your website.</p>
            <p><a href=»event:link»>View product details</a></p>]]>
        </description>
    </product>
</products>

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

Как обычно, мы пропустим процесс создания обложки, и я советую вам использовать начальный файл, найденный в загружаемых файлах.

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

Во-первых, есть фоновый слой с прямоугольником на нем. Нет, важная персона.

Далее, существует динамическое TextField с именем caption_tf . Это стиль с большим размером шрифта, поэтому он действует как заголовок. Он расположен так, что над ним будет ряд кнопок, а под ним будет загружено изображение. Обе кнопки и изображение будут размещены программно.

Затем у нас есть другой динамический TextField, называемый description_tf . Для этого установлен меньший размер шрифта, более подходящий для основного текста. Поле также установлено на многострочное и имеет большую площадь, чтобы вместить немного больше текста. Он расположен так, что он будет сидеть под изображением.

Оба TextFields имеют встроенные шрифты, так как мы будем динамически обновлять текст с помощью ActionScript.

Наконец, в библиотеке есть символ FeatureButton, и он настроен на экспорт для ActionScript. Его имя класса ActionScript также FeatureButton (это имя является важным), и он настроен на экспорт в первом кадре. Экземпляр этой кнопки размещен на сцене в направляющем слое, который называется «связанные символы» для удобного редактирования. Однако этот слой не будет включен в SWF, поскольку он является направляющим.


Прежде чем мы перейдем к практическому коду, я хотел бы рассказать о том, как ActionScript обрабатывает XML. Чтобы быть конкретным, способ ActionScript 3 обрабатывает XML. В ActionScript 2 (и 1) XML, безусловно, был возможен и даже довольно распространен, но синтаксис, используемый для извлечения данных из XML, был громоздким. Короче говоря, в нем много использовалось свойство «children», и было довольно легко заблудиться, пробираясь сквозь сложный документ.

ActionScript 3 продвигает XML для «первоклассного гражданина», то есть объекта верхнего уровня. Иными словами, XML так важен для AS3, что официально является нативным типом данных. Для его работы не требуется никаких строк импорта, и сумасшедшая вещь заключается в том, что вы можете вводить XML прямо в файлы ActionScript. Попробуйте это: откройте новый файл Flash ActionScript 3 и добавьте следующее на панель «Сценарий»:

1
2
3
var products:XML = <products>
    <product id=»42″ />
<products>

Вы можете, если хотите, сделать это целым XML-файлом продуктов, который мы создали ранее, но я хочу подчеркнуть, что он работает . Обычно я не слишком часто использую этот трюк, но он особенно полезен при работе с фиктивными данными. То есть, когда вы только начинаете проект и у вас нет готовых файлов XML, вы все равно можете быстро настроить работу в ActionScript, вставив временные данные XML, подобные этой. В связанных новостях, когда вам нужно создать небольшой тестовый файл, копирование вашего XML прямо в ActionScript может избавить вас от необходимости проходить процесс загрузки XML-файла, когда это не то, что вы тестируете.

И последнее, но, что немаловажно, поскольку XML является первоклассным гражданином ActionScript 3, у нас есть синтаксис для извлечения данных из объектов XML через нечто, называемое E4X (ECMAScript для XML; ActionScript 3 — это язык, совместимый с ECMAScript, и, следовательно, реализующий E4X). E4X предоставляет простой точечный синтаксис для обхода структуры дерева XML. Если вы использовали XPath для копания в XML, он похож на эту систему. Мы разберемся с деталями, когда создадим функциональную часть нашего продукта, но вот вкус E4X с использованием in-ActionScript XML из двух абзацев назад:

1
trace(products.product.@id);

Вкратце, он ссылается на основной объект XML ( products ), выбирает вложенный элемент product ( .product ) и, наконец, значение атрибута id этого элемента ( . @ Id ). Детали немного сложнее, но, надеюсь, это иллюстрирует, насколько плавно ActionScript 3 может работать с XML.

Вы можете прочитать больше о E4X в Википедии , а также о ECMAScript .

Если вам интересно, вы можете либо запустить файл AS2 Flash и проверить обработку XML, либо вы можете использовать порт AS3 класса AS2 XML. Посмотрите справочные документы под flash.xml.XMLDocument. Я бы посоветовал вам делать это только ради ученых и для удовлетворения вашего любопытного аппетита, поскольку я лично никогда бы не пожелал синтаксиса AS2 XML даже моему злейшему врагу.


Давайте начнем. Во-первых, нам понадобятся некоторые переменные, которые будут использованы позже. Мы просто создадим их сейчас, и их цель будет объяснена более полно по мере их использования.

В вашем файле Flash (мы закончили с временным файлом, который мы создали на последнем шаге), нам нужно поместить скрипт в первый кадр слоя действий. В этом скрипте, который будет содержать всю нашу логику для части, начните с объявления и размещения значений в нескольких переменных:

1
2
3
4
5
6
7
var xml:XML;
var featureIds:Dictionary = new Dictionary();
var link:String;
var loader:Loader = new Loader();
addChild(loader);
loader.x = 10;
loader.y = 86;

Переменные xml и link получат значения позже в программе. FeaturesIds пока должен быть пустым словарем, который также будет заполнен позже. Загрузчик должен быть создан и размещен на сцене, но, опять же, мы не будем ничего загружать до позже.


Мы можем писать XML непосредственно в ActionScript, но более гибко загружать его во время выполнения из внешнего XML-файла. Таким образом, мы можем создать фрагмент Flash, который достаточно гибок, чтобы реагировать на изменения в XML, и затем выполнение обновлений становится вопросом обновления XML-файла, а не Flash-файла. Вот как это должно работать; Обновление XML легко, обновление Flash-файлов менее.

Итак, нам нужно загрузить файл XML. Мы используем объект URLLoader для этого. Добавьте следующее после объявления существующих переменных:

1
2
3
4
var xmlLoader:URLLoader = new URLLoader();
var url:URLRequest = new URLRequest(«products.xml»);
xmlLoader.load(url);
xmlLoader.addEventListener(Event.COMPLETE, onXmlLoad);

Сначала мы создаем URLLoader. URLLoader просто загружает содержимое любого заданного URL. Это отличается от загрузчика (который мы встречали в учебнике AS3 101 по экранным объектам ), который разработан специально для загрузки SWF-файлов и файлов растровых изображений и их отображения. URLLoader загрузит все что угодно. В нашем случае мы хотим загрузить текстовый файл.

Во второй строке мы создаем объект URLRequest, который указывает на URL-адрес XML-файла, который мы хотим загрузить. В этом случае это относительный путь (и файл XML находится в том же каталоге, что и SWF). Если хотите, вы можете разместить XML в другом месте и настроить строку в URLRequest. Это может быть даже абсолютный путь, если хотите. Однако обратите внимание, что ограничения безопасности возникают при загрузке файла XML из другого домена, в котором находится SWF. Работа с этим выходит за рамки данного учебного пособия, но полезно знать о ситуации и знать, что вы можете искать в «crossdomain.xml», как с этим справиться.

Третья строка указывает URLLoader начать загрузку из URLRequest.

Мы добавляем прослушиватель событий в четвертую строку, чтобы быть уверенным, что сможем воздействовать на загруженные данные после их полной загрузки. Мы ничего не можем сделать с файлом XML до этого. Кроме того, мы должны настроить обработчики событий ProgressEvent.PROGRESS и IOErrorEvent.IO_ERROR (более подробно обсуждается в учебнике AS3 101 по экранным объектам ), но для целей этого учебника мы будем упоминать их, но не будем на них действовать.

В качестве заключительной части этого шага мы должны убедиться, что мы пишем (или, по крайней мере, начинаем писать) функцию onXmlLoad, которая будет выполняться после загрузки XML:

1
2
3
function onXmlLoad(e:Event):void {
    trace(«xml loaded»);
}

На этом этапе вы сможете запустить файл и увидеть след на панели «Вывод» при загрузке файла XML (это не займет много времени). Или, если что-то пошло не так, вы можете увидеть ошибку на панели «Вывод», возможно, из-за неуместного XML-файла.


Теперь, когда мы загрузили XML-файл, нам нужно превратить текстовые данные в XML-объект. Это легко сделать, добавив следующую строку в функцию onXmlLoad:

1
2
3
4
function onXmlLoad(e:Event):void {
    trace(«xml loaded»);
 <strong>xml = new XML(xmlLoader.data);</strong>
}

Мы используем переменную, которую создали несколько шагов назад. Он существует вне функции, поэтому он сохраняется в течение всего времени использования приложения Flash. Теперь мы можем использовать это.

Свойство data URLLoader — это просто содержимое загруженного нами файла. В этом случае это текстовые данные, которые являются данными XML, и передача строки в формате XML в конструктор XML ( new XML () ) проанализирует эту строку в объект XML. Итак, теперь у нас есть правильный объект XML в переменной xml. Вы можете проверить это с помощью следующей строки в конце функции onXmlLoad:

1
trace(xml.toXMLString())

Если вы тестируете сейчас, вы должны увидеть XML-документ, более или менее распечатанный на панели «Вывод».


Теперь немного волшебства E4X. Мы получим большой опыт в этом, но сейчас нам нужно извлечь все четыре (или сколько угодно) элементов продукта из XML, чтобы мы могли построить четыре (или сколько угодно) кнопок. Использование выражений E4X будет настолько «жадным», насколько это возможно, что означает, что они получат столько совпадений, сколько допустимо. Это работает в нашу пользу, так как мы можем написать очень простое выражение и заставить его захватить все элементы продукта.

На данный момент, переменная xml содержит весь объект XML. Таким образом, ссылка на переменную xml означает, что мы ссылаемся на корневой элемент XML, то есть элемент. Оттуда мы можем использовать точечные синтаксические выражения для детализации структуры данных. Если мы сделаем следующую строку в конце функции onXmlLoad:

1
var productElements:XMLList = xml.product;

Мы получим все элементы, которые являются прямыми потомками корневого элемента. Позже мы увидим, как мы можем быть более избирательными. В данный момент важно отметить, что выражение E4X фактически возвращает объект XMLList , а не объект XML. Объект XMLList является несколько странным объектом и может вести себя как объект XML в нескольких ситуациях. Вы можете думать об этом как о массиве элементов XML. В нашем случае он будет иметь отдельные записи для каждого из четырех элементы.

На самом деле, мы можем немного изучить XMLList, прежде чем идти дальше. Попробуйте следующее:

1
trace(productElements[2]);

И вы должны увидеть третий элемент на панели «Вывод» (индексы, такие как индексы массива и глубины для объектов DisplayObject, основаны на 0).

Вы также можете узнать, сколько элементов в списке, используя метод length ():

1
trace(productElements.length());

Важно понимать, что списки XMLL похожи на массивы, но не на самом деле. Что меня часто сбивает с толку, так это то, что я забываю, что у массивов есть myArray.length ), а у XMLLists есть myList.length () ). Это необходимое различие, потому что XMLLists способны обрабатывать выражения E4X, поэтому написание myList.length на самом деле ищет элементы, содержащиеся в списке.

Мы можем соединить эти два бита информации и перебрать XMLList (удалив предыдущие следы):

1
2
3
4
5
var len:int = productElements.length();
for (var i:int = 0; i < len; i++) {
    trace(«Element » + i);
    trace(productElements[i].toXMLString());
}

Мы все еще только отслеживаем, но теперь мы можем перебирать данные, как мы делали это в уроке по циклированию . Только теперь наши данные являются внешними по отношению к нашему Flash-приложению. Как это круто?


ОК, мы зациклились. Давайте сделаем что-нибудь с данными.

По мере выполнения цикла мы создадим новую кнопку из символа библиотеки, разместим ее и добавим в список отображения. Мы также дадим ему имя (для удобства) и назначим прослушиватель событий CLICK.

01
02
03
04
05
06
07
08
09
10
11
var len:int = productElements.length();
var btn:FeatureButton;
for (var i:int = 0; i < len; i++) {
    btn = new FeatureButton();
    btn.x = 10 + i * 50;
    btn.y = 10;
    addChild(btn);
    btn.name = "btn" + i;
    btn.buttonMode = true;
    btn.addEventListener(MouseEvent.CLICK, onButtonClick);
}

В этом нет ничего нового из того, что мы рассмотрели в предыдущих уроках AS3 101. Свойство buttonMode может потребоваться объяснить: по умолчанию Sprite или MovieClip с поведением, подобным кнопке, не отображают никакого специального курсора. В Интернете, однако, мы привыкли к курсору пальца при наведении на что-то нажимаемое , поэтому неплохо включить buttonMode , что делает именно это: курсор превращается в курсор пальца, когда спрайт переворачивается.

Кроме того, заглушите функцию обработки событий:

1
2
3
function onButtonClick(me:MouseEvent):void {
    trace("button clicked: " + me.target.name);
}

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

Теперь для действительно крутой части. Отредактируйте ваш XML-документ; либо удалитьэлемент (чтобы у вас было 3) или добавить дополнительный (чтобы у вас было 5). Когда вы снова протестируете свой SWF (просто перепубликуете его во Flash), вы должны, чтобы количество кнопок соответствовало количествуэлементы. Признайся, это круто.


Теперь нам нужно обработать клик более элегантно. Что мы собираемся сделать, это связать каждогоатрибут id элемента с экземпляром FeatureButton. Мы будем использовать словарь ( featureIds ), который мы создали ранее.

Теперь в цикле нам нужно получить идентификатор из элемента XML, а затем сохранить его в словаре вместе с FeatureButton.

01
02
03
04
05
06
07
08
09
10
11
12
13
for (var i:int = 0; i < len; i++) {
    btn = new FeatureButton();
    btn.x = 10 + i * 30;
    btn.y = 10;
    addChild(btn);
    btn.name = "btn" + i;
    btn.addEventListener(MouseEvent.CLICK, onButtonClick);
  
    var productElement:XML = productElements[i];
    var idString:String = productElement.@id;
    var id:int = parseInt(idString);
    featureIds[btn] = id;
}

Шаги сломаны. В первой (новой) строке мы просто получаем ссылку на элемент продукта, с которым мы сейчас работаем. Затем мы используем E4X для извлечения атрибута id из этого элемента (помните, символ «@» вводит нас в атрибуты элемента). Теперь, поскольку данные XML всегда являются String, а наши идентификаторы на самом деле являются целыми числами, нам нужно преобразовать String в int, что и делает функция parseInt .

Этот последний момент важно помнить: только то, что вы знаете его число (или логическое значение, или дату, или что-то еще), не означает, что ActionScript распознает его как таковой. XML — это на самом деле просто текстовые данные, поэтому все, что выходит из него через выражение E4X, будет строкой. Если вы хотите, чтобы это было что-то другое, вам нужно явно преобразовать это.

Последняя строка устанавливает связь между кнопкой и ее идентификатором, используя кнопку в качестве ключа в Словаре и назначая идентификатор в качестве значения.


Затем нам нужно вернуть этот идентификатор, как только щелкнет. В функции onButtonClick:

1
2
3
function onButtonClick(me:MouseEvent):void {
    trace("button clicked: " + featureIds[me.target]);
}

Если вы попробуете это, вы увидите, что вы получаете соответствующую идентификацию для каждого клика.

Итак, теперь мы можем приступить к получению остальных данных о продукте. Вот где E4X превращается из крутого в мощный . Мы собираемся выборочно выбрать элемент продукта из всего нашего XML-документа на основе этого идентификатора. Это мало чем отличается от запроса базы данных для одной строки с определенным идентификатором из сотен строк. Это выглядит так:

1
2
3
4
5
function onButtonClick(me:MouseEvent):void {
    var id:int = featureIds[me.target];
    trace("button clicked: " + id);
    var productElement:XML = xml.product.(@id==id)[0];
}

На самом деле, одновременно происходит несколько трюков. Первая часть выглядит следующим образом: (@ id == id) . Скобки позволяют условно выбирать элементы XML. Если бы мы только что написали xml.product. @ Id , мы получили бы XMLList всех атрибутов id, содержащихся в элементах продукта. Однако с добавленным условным выражением E4X находитЭлементы основаны на критериях, которые мы установили в скобках. В этом случае мы смотрим на атрибут id элемента и сравниваем его с нашим известным идентификатором из словаря.

Второй трюк включает в себя пропуск XMLList (в некотором смысле). Вы помните, что выражение E4X возвращает XMLList, а не объект XML. Что ж, мы можем быть достаточно уверены, что у каждого элемента продукта есть уникальный идентификатор (как? Хорошо, давайте просто предположим, что у нас есть некоторый механизм для обеспечения этого, очень похоже на то, как в базах данных есть способы обеспечения уникальных ключей для записей таблицы). Следовательно, каждый раз, когда выполняется это выражение, оно, вероятно, возвращает XMLList, состоящий из одного объекта XML. Даже если этого не произойдет, мы все равно хотим только один, чтобы мы могли продолжить отображение данных.

Итак, мы добавляем это [0] в конце выражения. Мы могли бы написать это так:

1
2
var productElementMatch:XMLList = xml.product.(@id==id);
var productElement:XML = productElementMatch[0];

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

Зачем тебе это показывать? Есть две причины, почему я показываю вам это. Проще говоря, чтобы показать вам это. Если никто никогда не скажет вам эти тонкие детали языка ActionScript, как вы узнаете? Другая причина в том, что я достаточно уверен, что наши идентификаторы будут уникальными, и я бы предпочел менее подробную версию кода.


Наконец, мы можем что-то сделать с этими данными. Отсюда все довольно просто. Мы делаем еще несколько простых выражений E4X, чтобы получить отдельные данные из элемента продукта, и мы используем их для заполнения содержимого области функций. Вот полная функция onButtonClick:

01
02
03
04
05
06
07
08
09
10
function onButtonClick(me:MouseEvent):void {
    var id:int = featureIds[me.target];
    trace("button clicked: " + featureIds[me.target]);
    var productElement:XML = xml.product.(@id==id);
 
    caption_tf.text = productElement.name.toString();
    description_tf.htmlText = productElement.description.toString();
    link = productElement.link.toString();
    loader.load(new URLRequest(productElement.image.toString()));
}

Первые две строки довольно просты; они просто берут строки из XML и помещают их в два текстовых поля. Один вариант с описанием TextField. С этим мы используем свойство htmlText вместо простого старого текстового свойства. Это позволяет Flash отображать простой набор HTML-тегов для форматирования текста. Это теги, которые мы вставили в элемент <description>, которые требовали использования тега CDATA.

Мы также просто помещаем строку из элемента XML <link> в переменную ссылки, которую мы создали некоторое время назад. Мы будем использовать это на следующем шаге, когда подключим ссылку в текстовом поле описания.

Наконец, мы снова просто используем значение String элемента <image> для загрузки чего-либо в Loader, который мы создали одновременно с переменной link. Строковый URL должен быть заключен в URLRequest, так же как и при загрузке XML-документа. Однако на этот раз мы делаем это и загружаем файл за один шаг. Это немного глупее, но вы часто будете видеть этот стиль.

Если вы проверите это сейчас, это должно выглядеть довольно хорошо!


В <a>наших описаниях есть теги, но они мало что делают. Здесь мы представим другую технику, TextEvent.

Когда в TextField есть текст HTML, а в HTML есть <a>тег, он автоматически становится активным. И если значением атрибута href является URL-адрес, вы перейдете на эту страницу в своем веб-браузере при нажатии на ссылку. Но ActionScript предоставляет немного больше, чем простая гиперссылка; Вы также можете использовать ссылку для запуска ActionScript.

Во-первых, значение атрибута href должно начинаться с «event:», а не «http: //» или относительной ссылки. Используя протокол событий psuedo, мы можем заставить Flash обрабатывать щелчок немного по-другому. Мы уже сделали это в документе XML, но я упомяну здесь как необходимый шаг.

Во-вторых, нам нужно добавить прослушиватель событий в рассматриваемый TextField:

1
description_tf.addEventListener(TextEvent.LINK, onTextLink);

Это событие отправляется, когда href начинается с «event:»

Наконец, нам нужно написать эту функцию. Вы получите объект TextEvent в параметрах функции, который будет иметь значение href в свойстве text. Мы используем значение наполнителя, «ссылка». В более сложном приложении это могут быть данные, на которые нужно воздействовать, или идентификатор, который различает одну ссылку или другую. Мы просто хотим, чтобы текстовое событие, а затем мы будем использовать значение переменной ссылки, чтобы перейти на новую страницу. Чтобы увидеть, что происходит, попробуйте следующее:

1
2
3
function onTextLink(te:TextEvent):void {
    trace(te.text);
}

Теперь, чтобы обернуть это, замените этот след следующим:

1
2
3
4
5
function onTextLink(te:TextEvent):void {
 
    navigateToURL(new URLRequest(link));
     
}

Протестируйте фильм, и вы сможете ориентироваться, используя ссылку «Просмотр сведений о продукте».


Сейчас все работает, за исключением того, что при первой загрузке страница довольно пуста. Все отлично после того, как вы нажмете кнопку, но мы, вероятно, должны сделать так, чтобы первый продукт отображался по умолчанию. Это легко сделать, имитируя нажатие первой кнопки после загрузки XML.

В конце цикла в функции onXmlLoad добавьте следующий код:

1
2
3
if (i == 0) {
    btn.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
}

Теперь вся функция должна выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function onXmlLoad(e:Event):void {
    trace("xml loaded");
    xml = new XML(xmlLoader.data);
    //trace(xml.toXMLString())
    var productElements:XMLList = xml.product;
    //trace(productElements[2])
    //trace(productElements.length());
    var len:int = productElements.length();
    var btn:FeatureButton;
    for (var i:int = 0; i < len; i++) {
        btn = new FeatureButton();
        btn.x = 10 + i * 50;
        btn.y = 10;
        addChild(btn);
        btn.name = "btn" + i;
        btn.buttonMode = true;
        btn.addEventListener(MouseEvent.CLICK, onButtonClick);
  
        var productElement:XML = productElements[i];
        var idString:String = productElement.@id;
        var id:int = parseInt(idString);
  
        featureIds[btn] = id;
  
        if (i == 0) {
            btn.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
        }
    }
}

Это почти то же самое, что нажатие на первую кнопку (этот код запускается, только если i равен 0, другими словами, первый раз в цикле, когда мы создаем первую кнопку). Разница в том, что событие CLICK генерируется не посредством фактического щелчка мышью пользователем, а вместо этого путем ручного вызова dispatchEvent для кнопки MovieClip. Этот вызов dispatchEvent будет происходить изнутри всякий раз, когда происходит реальный щелчок. Это не подходящая техника во всех случаях, но здесь это хорошо; если вы запустите фильм сейчас, вы увидите, что первая функция появится автоматически.


Если вы знаете HTML, вы, вероятно, также знаете CSS. Так же, как Flash поддерживает ограниченный набор HTML в своих TextFields, он также поддерживает ограниченный набор CSS для стилизации текста HTML в своих TextFields. Этот шаг не обязательно связан с использованием XML, но мы умно включим некоторые встроенные XML, чтобы доставить некоторые стили в наше текстовое поле, и в процессе изучим основы того, как стилизовать динамический HTML-текст с помощью CSS.

Во-первых, нам нужно написать нашу таблицу стилей. Весь следующий код может быть легко размещен в конце вашего скрипта. Мы можем создать встроенную переменную XML (то есть встроенную в скрипт, а не загружать внешний документ), а затем поместить наш CSS в тег CDATA:

1
2
3
4
5
6
7
var css:XML = <style>
    <![CDATA[
        a {
            color:#992408;
        }
    ]]>
</style>

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

1
trace(css.toString());

Далее мы можем создать объект StyleSheet:

1
var styles:StyleSheet = new StyleSheet();

А затем нам нужно проанализировать CSS-файл «file» в StyleSheet, вот так:

1
styles.parseCSS(css.toString());

Это берет строку, которая содержит код CSS и делает ее пригодной для использования в качестве объекта ActionScript StyleSheet. Теперь мы можем применить таблицу стилей к описанию TextField:

1
description_tf.styleSheet = stylesheet;

И если вы протестируете это сейчас, вы увидите, что ваши текстовые ссылки отображаются в красноватом цвете:

Обратите внимание, что parseCSS принимает любую строку, и мы могли бы просто сделать это:

1
styles.parseCSS("a {color:#992408;}");

Для простого стиля это, вероятно, выполнимо, но, как вы, вероятно, знаете, документы CSS могут становиться длиннее, а использование пробелов (новые строки и отступы) значительно облегчает работу с файлом. Здесь мы используем способность ActionScript записывать данные XML прямо в сценарий и использовать CDATA XML для создания строки, которая в основном представляет собой код в коде (если вы также учитываете XML как код, то это код внутри кода внутри код).

Этот метод позволяет легко справиться с экранированием кавычек или переводом строки. Легко, как в, вы не должны это делать. Использование встроенного XML с CDATA также полезно для написания функций JavaScript, которые вы выполняете с ExternalInterface (метод, который мы упомянем, но не будем здесь рассматривать). XML — это больше, чем просто хранилище данных!

Обратите внимание, что вы также можете загружать файлы CSS так же, как вы загружаете файлы XML. Было более кратко жестко закодировать CSS в ActionScript, плюс он учитывал касательные в использовании XML. Ищите « загрузить CSS с помощью ActionScript » для получения некоторых основных инструкций по использованию внешних файлов CSS. Вы увидите некоторые сходства между этим и загрузкой внешних XML-файлов.


На этом этапе у вас должен быть чрезвычайно мощный инструмент в вашем арсенале. XML — чрезвычайно популярный формат для хранения данных в приложениях Flash. Есть и другие методы, которые имеют свои преимущества и недостатки, но концепции остаются теми же. Обучение управлению вашими Flash-компонентами с помощью внешних ресурсов и данных официально поднимает вас с начального уровня на средний уровень.

Да, это правда.Если вы до сих пор следовали всем семи частям этой серии, вы, вероятно, больше не можете считаться новичком. Вы узнали о переменных, функциях, условной логике, циклах и массивах, списке отображения Flash и, наконец, XML как внешнем источнике данных. К этому моменту ключевые концепции были представлены и проиллюстрированы, и, хотя, безусловно, есть больше деталей, которые необходимо знать, и более продвинутые методы, которые необходимо изучить, теперь вы должны обладать знаниями, необходимыми для работы с довольно сложными проектами. Я надеюсь, что вы можете оглянуться назад и поразить себя тем, как далеко вы продвинулись.

Вы спрашиваете, что дальше для AS3 101? Я думаю, пришло время поднять его на ступеньку выше. Ищите несколько уроков по основам объектно-ориентированного программирования, которые скоро появятся. Мы все еще будем время от времени возвращаться к «существенным» темам, так что не беспокойтесь, если вы все еще чувствуете, что в фундаменте остались некоторые дыры.