Java дает вам портируемый код, а Exensible Markup Language (XML) дает вам портируемые данные [8].
XML является стандартом, адаптированным Консорциумом World Wide Web (W3C - World Wide Web Consortium) для усовершенствования HTML для обмена данными в среде Web. В этой главе мы опишем XML, инструменты и API для доступа к XML из Java.
Большинство читателей видели HTML, язык для описания Web страниц. В отличие от многих, мы не будем критиковать HTML, он полностью удовлетворяет многим параметрам. HTML не первый язык тэгов, но он, определенно, наиболее часто используемый, наиболее удачный и наиболее широко понимаемый.
Если HTML такой удачный, почему у нас возникла необходимость в XML? Есть несколько причин.
Во-первых, XML облегчает обмен данными. В XML дата и описание того, как они должны быть структурированы (размечены) хранятся в виде текста, так что вы можете легко читать и редактировать. Во-вторых, XML разметка может быть настроена под заказчика и стандартизирована. Это дает нам экстраординарную силу XML. HTML является языком разметки, предназначенным для описания web страниц, но его основная слабость состоит в том, что он смешивает данные и представление. Когда группа пользователей с общей заинтересованностью в тэгах для определенного языка разметки работают с XML, они просто создают настроенный для своих нужд язык разметки. Сотни таких языков были стандартизированы, включая:
- Bank Internet Payment System (BIPS)
- Financial Information eXchange protocol (FIX)
- Telecommunications Interchange Markup (TIM)
- Mathematics Markup Language (MathML)
Фактически, вы можете добавить расширение в язык разметки, созданное кем-либо еще. Extensible Hypertext Markup Language (XHTML) является XML версией HTML, которая позволяет добавлять элементы на страницу, а браузер отобразит их, как обычный HTML.
XML также великолепен, поскольку XML документ является самоописательным. Вот простейший XML документ:
<?xml version="1.0" encoding="UTF-8"?> <phonenumber country="us"> <areacode>215</areacode> <number>6424748</number> </phonenumber>
Каждый элемент XML имеет тэг и вы можете легко понять, какие данные представлены даже спустя годы. Это значит, что XML документ является самодокументируемым.
В-третьих, XML имеет такой синтаксис, который позволяет автору XML документа предать структуру данным. Вложенность элементов данных в другие элементы очень важна, поскольку данные необычайно просты. XML прост в дизайне, но может представлять сложные данных. При использовании HTML вы можете представлять длинный учетный документ, но использовать совместно этот учетный документ с другими программами или организациями будет сложно - они не знают о вашей структуре. HTML был предназначен для представления неопределенной структуры. В XML вы можете построить в соответствии семантическим правилам, которые указывают структуру документа учета. Другой XML документ может быть создан для описания того, как лучше отображать этот учетный документ. XML разделяет структуру и представление.
Что такое XML?
XML дает вам возможность описывать "слабоструктурируемые" данные. Только что высказанная мысль о том, что XML позволяет вам структурировать данные может звучать несколько сбивающей с толку. Слабоструктурированные данные определяются как "бессхемные" или самоописательные. Это означает, что нет разделения описания типа от структуры данных.
Как вы уже видели в этой книге, когда мы храним или программируем часть данных, сначала мы описываем структуру этих данных, а потом создаем экземпляр этого типа. В случае слабоструктурированных данных мы напрямую описываем данные с помощью простого синтаксиса. XML специально разработан для описания данных или содержимого, а не представления. Это фундаментальное отличие от HTML.
Давайте рассмотрим пример. Если я скажу, что я имею данные, которые описывают меню ресторана, то в уме сразу всплывет любимый ресторан и его меню. Но давайте взглянем на проблему немного пристальней, и вы осознаете, что все меню выполняют одну и то же работу - описывают цены ресторана - но каждое меню делает это немного иначе. Многие китайские рестораны используют числа и разделяют свои блюда по содержимому - морепродукты, мясо, птица, свинина или овощи. Другие рестораны структурируют свое меню по сроку приема пищи - завтрак, ланч или обед.
<?xml version='1.0'?> <?xml:stylesheet type="text/xsl" href="tij_menu.xsl" ?> <restaurant xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="tij_menu.xsd"> <name>TIJ's Restaurant</name> <address> <addr1>108 Java Sapien Avenue</addr1> <city>Wayne</city> <state>PA</state> <country>USA</country> </address> <phone>610-687-1234</phone> <menu> <menugroup desc="Starters"> <menuitem> <name>Nachos</name> <price>$7.25</price> <description> cheddar and monterey jack cheese, salsa, sour cream and guacamole. add jalapenos or black olives $.50 each </description> </menuitem> <menuitem> <name>Portabello Mushroom Cap</name> <price>$8.75</price> <description> Stuffed with crabmeat, andouille sausage and smoked tomato sauce </description> </menuitem> <menuitem> <name>Chicken Wings</name> <price>$4.95</price> <description> A dozen chicken Wings with blue cheese sauce. Two dozen for $8.75 </description> </menuitem> <menuitem> <name>Quesadilla</name> <price>$6.25</price> <description> Chicken, black beans, guacamole, salsa, fresca and sour cream </description> </menuitem> </menugroup> <menugroup desc="Salads, Big Salads, and Soups"> <menuitem> <name>House Salad</name> <price>$4.75/$8.00</price> <description> Small or large house salad with balsamic herbed vinaigrette </description> </menuitem> <menuitem> <name>Mesclun Salad</name> <price>$7.25/$13.50</price> <description> with marinated mushrooms, roasted peppers, artichokes, fresh mossarella and balsamic vinaigrette </description> </menuitem> <menuitem> <name>Grilled Chicken Salad</name> <price>$6.75/$11.25</price> <description> soy sesame marinade, mixed greens, red and green peoppers, carrots, red onion, crispy fried wontons and honey ginger dressing </description> </menuitem> <menuitem> <name>Chicken Soup of the Day</name> <price>$2.30/$3.95</price> </menuitem> </menugroup> <menugroup desc="Pizza"> <menuitem> <name>Duck Confit Pizza</name> <price>$9.00</price> <description> with caramelized onion, fresh thyme and goat cheese </description> </menuitem> <menuitem> <name>The Salty Pizza</name> <price>$8.50</price> <description> with proscuitto, black olives cotija cheese, tomatoes and anchovies </description> </menuitem> <menuitem> <name>Traditional Pizza</name> <price>$7.50</price> <description> red sauce and mozzarella cheese </description> </menuitem> <menuitem> <name>Toppings</name> <price>$.50</price> <description> Pepperoni, Sausage, Chicken, Grilled Portabello, Roasted Peppers, Sun Dried Tomatoes, Roasted Garlic, Broccoli Rabe, Spinach, Shrimp, Proscuitto, Black Olives, Goat Cheese, Bacon, Roasted Veggies, Green Peppers, Onions, Mushrooms </description> </menuitem> </menugroup> <menugroup desc="Entrees"> <menuitem> <name>Grilled Rib Eye Steak</name> <price>$18.00</price> <description> with buttermilk biscuits, vegetable of the day and button mushroom gravy </description> </menuitem> <menuitem> <name>Pork Tenderloin</name> <price>$16.00</price> <description> dry rubbed with swiss chard, maple whipped sweet potatoes and apple bourbon sauce </description> </menuitem> <menuitem> <name>Grilled Chicken</name> <price>$16.00</price> <description> with mushroom risotto pesto sauce and tomato salsa </description> </menuitem> <menuitem> <name>Center Cut Sirlion</name> <price>$16.00</price> <description> with cheddar cheese mashed potatoes, horseradish sour cream and vegetable of the day </description> </menuitem> </menugroup> <menugroup desc="Kids"> <menuitem> <name>Hot Dog</name> <price>$3.50</price> <description> on roll; with American Chees $3.75 </description> </menuitem> <menuitem> <name>Grilled Cheese Sandwich</name> <price>$3.25</price> <description>The classic!</description> </menuitem> <menuitem> <name>Chicken Fingers</name> <price>$5.00</price> <description>Finger licking good</description> </menuitem> </menugroup> <menugroup desc="Beverages"> <menuitem> <name>Milkshake</name> <price>$3.50</price> <description> vanilla, chocolate or strawberry; double thick, $5.00 </description> </menuitem> <menuitem> <name>Orange Cream Soda Float</name> <price>$5.00</price> </menuitem> <menuitem> <name>Chocolate Milk</name> <price>$2.50</price> </menuitem> </menugroup> </menu> </restaurant>
Я не знаю, определяет ли эта структура все меню для всех ресторанов, но она описывает меню для любимого близлежащего ресторана и она может быть подогнана под большинство меню.
XML позволяет пользователям определять тэги для указания структуры. В этом меню <restaurant> содержит <menu>, также наш ресторан может содержать <menugroups>, а <menugroups> содержат <menuitems>, которые представляют блюда. Здесь может быть необходимо больше данных для элементов меню - скажем: калорийность блюд.
В отличие от HTML, XML документ не предоставляет никаких инструкций о том, как он будет отображаться. Этот тип информации может быть включен отдельно в страницу стилей (stylesheet). Страница стилей на языке спецификации XSL (XML Stylesheet Language) используется для трансляции XML данных в HTML представление.
Таким образом, я должен также объяснить, что XML - это нечто большее, чем простой набор правил для конструирования данных. XML включает целый пласт спецификаций, которым он удовлетворяет. Эти спецификации позволяют вам описать структуру XML документа. По существу, они удаляют "слабость" из слабоструктурированных данных.
XML Элементы
Основными компонентами XML являются элементы. Они являются частями текста, ограниченного соовпадающими тэгами, такими как <menu> и </menu>. Внутри этих тэгов элемент может содержать "строку" текста, другой элемент или их комбинацию.
В примере с меню, <menuitem> называется открывающим тэгом, а </menuitem> называется закрывающим тэгом. Открывающий и закрывающий тэги также называются разметкой, поскольку они размечают или объясняют данные. Одно из правил XML состоит в том, что эти тэги должны быть сбалансированы. Это означает, что они должны быть закрыты в обратном порядке по сравнению с тем, в котором они были открыты, как скобки. Тэги в XML определяются пользователем; нет предопределенных тэгов, как в случае HTML. Текст между открывающим и соответствующим закрывающим тэгами, включая вложенные тэги, называется элементом, а структуры между тэгами называются содержимым. Вложенные элементы - это отношения между элементом и составляющими его элементами. Поэтому, <price> … </price> является вложенным элементом <menuitem> … </menuitem> в нашем примере.
Один элемент включает в себя все другие - <restaurant> … </restaurant>. Это корневой элемент.
Мы используем повторяющиеся элементы с одинаковым тэгом для представления коллекции. В примере меню <menu> содержит один или несколько элементов <menugroup>, а <menugroup> могут содержать один или несколько элементов <menuitem>.
Элемент также может быть пустым, а пустой элемент может быть укороченным. Это выполняется путем помещения "/" в конце открывающего тэга, как в случае <menuitem/>.
XML Атрибуты
XML позволяет нам ассоциировать атрибуты с элементами. Атрибуты являются парами имя-значение, которые действуют наподобие "property" в модели данных. В нашем примере меню мы имеет атрибут, называемый "desc" внутри элемента menugroup.
Есть различия между атрибутами и тэгами. Данный атрибут может присутствовать только внутри тэга, в то время, как вложенные элементы внутри этого тэга могут повторяться. Значение, ассоциированное с атрибутом, должно быть строковым, в то время, как элемент может также иметь вложенные элементы наряду со значениями. Поэтому атрибуты нельзя использовать, когда часть данных может быть представлена в виде коллекции.
Атрибуты вносят некоторую сумятицу, так как представленная информация может быть как элементом, так и атрибутом. Например, мы может представить нашу menugroup так:
или
<menugroup> <desc>Beverages</desc> </menugroup>
Любой формат представляет данные, но когда ваши данные становятся более сложными, вы должны быть более избирательны.
Набор Символов
Актуальные символы в XML документе хранятся как числовые коды. Наиболее общим набором символов является American Standard Code for Information Interchange (ASCII). ASCII коды простираются от 0 до 255, что умещается в один байт.
XML - это текстовый формат данных, который будет составлять мощь следующего поколения World Wide Web. В этом мы имеем проблему, и она - "Worldwide". Многие скрипты не обрабатывают ASCII, а именно Japanese, Arabic, Hebrew, Bengali и многие другие языки.
По этой причине набором символов по умолчанию для XML по заявлению W3C является Unicode, а не ASCII. Но на практике поддержка Unicode, как и многих других частей технологии XML, не полностью реализована на большинстве платформ. Windows 95/98 не имеет полной поддержки Unicode, хотя в Windows NT, Windows 2000 и XP с этим делом обстоит лучше. Чаще всего это значит, что XML документ написан в простом ASCII или в UTF-8, который представляет собой компрессированную версию Unicode, использующую восьмибитное представление символов.
В нашем примере первая строка заявляет:
здесь указывается использование UTF-8 символов кодировки UTF-8.
В настоящее время XML процессор предполагает, что значением по умолчанию для вашего документа является UTF-8, так что если вы пропустите спецификацию кодировки, будет предполагаться, что это UTF-8. За более детальной информацией о наборах символов просмотрите список опубликованный Internet Assigned Number Authority (IANA) на www.isi.edu/in-notes/iana/assignments/character-sets.
XML Технологии
Бывший в начале таким простым и быстрым, XML становится сложным. XML сложен по одной главной причине - есть много чего, что к нему относится. Термин XML охватывает многочисленный набор технологий, которые подпадают под ширму названия XML. Некоторая часть терминологии, вращающаяся вокруг XML, включена в такие названия как: пространство имен, преобразования или XSLT, XPath, XLinks, XPointers, SAX и DOM. С каждым годом появляются все новые и новые термины, точно так же появляются новые и новые книги, охватывающие эти новые темы и технологии. Я не могу охватить их все, но я попробую дать вам основные.
JAXP - Обработка XML
Java API для обработки XML (Java API for XML Processing - JAXP) предоставляет стандартное API для разбора и трансформации XML документа. Это API разработано так, чтобы не зависеть от определенной реализации XML процессора. Летом 2002 года Sun реализовала пакет Java XML. Он включает ссылки на версию Xerces 2 в качестве XML парсера по умолчанию, и Xalan - в качестве XSLT машины по умолчанию, оба продукты Apache.
Мы будем использовать те же самые инструменты, поскольку они широко используются, наиболее соответствуют спецификации и они распространяются свободно на web сайте apache - www.apache.org. Таким образом, каждый может загрузить их.
Пространство имен XML
В XML все относится к данным. Структурирование данных, определение данных и совместное использование данных. XML дает вам значительную свободу в определении своих собственных тэгов, но что произойдет, когда вы определите тэг, который уже определен грамматикой, которую вы хотите использовать.
Например, возьмем два популярных XML проекта: XHTML и MathML. Что случится, если вы захотите показать уравнение внутри XHTML документа? Некоторые тэги в MathML перекрываются с тэгами XHTML.
Ответом является пространство имен. Создание пространства имен позволит вам разделить один набор тэгов с другим, таким образом предотвратить конфликт. Использование пространства имен позволяет вам добавлять имя, за которым через двоеточие следует тэг и имена атрибутов, меняющее эти имена так, чтобы они не конфликтовали.
Примером пространства имен, который мы видим наиболее часто, является определения пространства имен XML Shema внутри XML документа.
Экземпляр пространства имен XML Shema определяется и ассоциируется с URL. Это пространство имен может быть теперь сокращено до xsi и оно используется для указания информации в XML документе, которая относится к схеме. Вот что в точности мы делаем здесь с помощью xsi:noNamespaceSchemaLocation. К этому атрибуту спереди приставляется xsi.
Схема XML определяет множество новых имен, которые описывают элементы, типы, атрибуты, определение которых вписывается в схему. Этот документ затем должен быть построен в соответствии с правилами схемы.
Хорошо Форматированный и Достоверный XML
Есть несколько ограничений для XML документа, тэги должны совпадать и правильно размещаться, атрибуты должны быть уникальными. О документе говорят, что он хорошо форматирован, когда он удовлетворяет этим простым правилам. Это несколько больше, чем просто убедиться, что XML данные будут представлены в виде дерева категорий.
Более строгие правила могут применяться к документу, если ожидается, что XML соответствует определенной грамматике. XML приложение имеет спецификацию синтаксиса и семантики структуры данных. Определение типа документа DTD (document type definition) или XML Схема предоставляет правила структурирования, которым должен удовлетворять XML документ, чтобы быть "достоверным". Использование DTD несколько неудовлетворительно, поэтому сейчас XML схемы становится стандартом для определения XML грамматики.
Вот схема для примера tij_menu.xml - tij_menu.xsd:
<xsd:schema xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <xsd:annotation> <xsd:documentation> TIJ Restaurant Menu Schema. </xsd:documentation> </xsd:annotation> <xsd:element name="restaurant" type="restaurantType" /> <xsd:complexType name="restaurantType"> <xsd:element name="name" type="xsd:string" /> <xsd:element name="address" type="addressType" /> <xsd:element name="phone" type="xsd:string" /> <xsd:element name="menu" type="menuType" /> </xsd:complexType> <xsd:complexType name="menuType"> <xsd:attribute name="desc" type="xsd:string" /> <xsd:element name="menugroup" type="menugroupType" minOccurs="1" maxOccurs="unbounded" /> </xsd:complexType> <xsd:complexType name="menugroupType"> <xsd:element name="menuitem" minOccurs="1" maxOccurs="unbounded"> <xsd:complexType> <xsd:element name="name" type="xsd:string" minOccurs="1" /> <xsd:element name="price" type="xsd:string" minOccurs="0" /> <xsd:element name="description" type="xsd:string" minOccurs="0" /> </xsd:complexType> </xsd:element> </xsd:complexType> </xsd:schema>
Схема XML предоставляют богатую грамматическую структуру для XML документа, который перекрывает ограничения DTD. Ее цель состоит в том, чтобы убедиться, что XML документ построен в соответствии с требованиями, составляющими схему. Это позволяет использовать совместно аналогичные данные, например, составить заказ или меню. Если мы хотим запустить службу меню, которая позволяет пользователям просматривать меню ресторанов в своем районе, мы можем пожелать, чтобы все отправляемые меню приходили в специфическом формате. Или попросить, чтобы все отправляемые меню приходили со своим собственным дескриптором формата, чтобы мы могли преобразовать его.
В tij_menu.xml <restaurant> является корневым элементом и он содержит различные вложенные элементы. В терминах схемы, элементы, которые содержат вложенные элементы, или имеют атрибуты, являются сложными типами. Элементы, которые содержат только простые данные, такие как числа, строки или даты, но не имеют вложенных элементов, являются простыми типами. Атрибуты всегда являются простыми типами, поскольку значения атрибутов не могут содержать никакие структуры. Если мы взглянем на документ, как на дерево, то увидим, что простые типы не имеют дочерних узлов, в то время как сложные типы могут иметь их.
Отличия между простыми и сложными типами очень важно, поскольку вы декларируете простые и сложные типы отдельно. Вы декларируете сложные типы сами, а спецификации XML схемы сопутствуют многие простые, уже задекларированные типы.
Это пример декларации простого типа. Типами обычно являются стоки, целые числа, десятичные числа, время и т.п. Допустим, что это не лучшая структура для прайса и мы можем сделать лучше. Мы решили добавить в качестве атрибута валюту прайса. Это недопустимо, элемент простого типа не может иметь атрибутов. Так что мы меняем прайс на сложный тип.
<xsd:complexType name="price"> <xsd:base ="decimal" /> <xsd:attribute name="currency" type="string" /> </xsd:complexType>
Элементы, в которые вставлены другие элементы, должны быть сложными типами. Для приведенной выше схемы вы можете увидеть, что <restaurant> содержит <menu>, <menu> содержит <menugroup>, а <menugroup> содержать <menuitem>. Ограничения могут быть наложены на значения элементов посредством использования minOccurs and maxOccurs. По умолчанию эти значения равны 1 для элемента. В tij_menu.xml необходимо иметь много элементов <menuitem> внутри <menugroup>, так что мы устанавливаем значение maxOccurs в величину -- не ограничено.
Создание хорошо форматированного и достоверного XML документа - это двух этапный процесс. Научиться писать XML, как мы это видели, просто, для этого очень мало правил. Далее, вы должны выучить XML приложение (-ния), которое вы будете использовать. Это обычно стандарт или спецификация, определенная сторонней организацией, согласно которой вы должны организовать свои данные. Данные должны быть прочитаны и должен быть создан достоверный XML документ, в который помещаются ваши данные в том формате, который могут понимать другие программы.
Синтаксический анализатор с проверкой достоверности: SAX и DOM
Имея правильный инструмент для усиления качества контроля, мы может сделать жизнь намного легче. Это одна из великих преимуществ XML, а так как цель XML состоит в том, чтобы быть универсальным языком, который работает одинаково все время, стандарт для целостности данных должен быть высоким.
Ключом для целостности такого уровня является синтаксический анализатор с проверкой достоверности. Синтаксический анализатор с проверкой достоверности проверяет ваш XML документ на хорошее форматирование, которое обычно страдает от отсутствующих закрывающих тэгов или орфографических ошибок. Как это предполагает название, этот синтаксический анализатор выполняет проверку на хорошее форматирование документа, проверяя ошибки, которые трудно найти: отсутствующие элементы или неверный порядок элементов, основываясь на модели документа, помещенной в DTD или XML Схему.
Другой великолепный аспект, относящийся к синтаксическим анализаторам проверки достоверности с открытым кодом, является то, что лучшие из них бесплатны. Синтаксический анализатор, который я буду использовать в этой главе, это Apache Xerces. Существует Java и C++ версии, которые поддерживают модель документов, выполненных как в DTD, так и в XML Схеме. (xml.apache.org)
XML прогрессирует так быстро, что трудно за ним уследить. Это относится и к инструментам, которые мы будем использовать. Xerces 2.1.0 значительно отличается по архитектуре от Xerces 1.4. Это произошло потому, что XML среды очень быстро эволюционируют. Xerces 2 работает с SAX 2.0, DOM Level 2, некоторыми добавлениями из DOM Level 3... - это бесконечно, и команда Apache сделала восхитительную работу, включив все пересмотренные и новые технологии.
Но что же в точности делает синтаксический анализатор? Он разделяет на части XML документ и позволяет вам иметь дело с ним программно. Существует два метода для программистской работы с XML документом, вы можете иметь дело с событиями, которые происходят во время синтаксического разбора, или вы можете разбить XML документ на общее представление содержимого и модель, которой все инструменты могут манипулировать.
Простейшее API для XML (SAX - Simple API for XML) является интерфейсом для синтаксического анализа документа и последующей вставки кода приложения при возникновении важных событий во время синтаксического разбора документа. SAX является системой управления XML документом, основанной на событиях. Она позволяет обрабатывать документ последовательно, без необходимости считывать весь документ в память.
Объектная Модель Документа DOM (Document Object Model) является стандартным представлением содержимого и модели XML документа для всех языков программирования и инструментов. Поддержка существует для JavaScript, Java, C++, CORBA, Python, Perl и других языков, что позволяет DOM быть кроссплатформенной и кроссязычной спецификацией.
В своей наиболее фундаментальной форме DOM является древовидной моделью. В то время, как SAX дает вам событийную концепцию синтаксического разбора, DOM дает вам полное представление документа в памяти. Обе модели имеют свои сильные и слабые стороны, как мы это увидим.
SAX
Это основа. Давайте взглянем на детали, мы начнем с простой SAX программы, которая проверяет достоверность нашего tij_menu.xml:
import
java.io.*;
import
org.xml.sax.*;
import
org.xml.sax.helpers.*;
public class
validate2
{
static public
void
main
(
String
[]
argv
) {
if
(
argv.length ==
0
) {
System.out.println
(
"Usage: java validate2 file:<filename> or n"
+
"or java validate2 uri"
)
;
}
XMLReader parser =
null
;
// пробуем запустить поверку
try
{
parser = XMLReaderFactory
.createXMLReader
(
"org.apache.xerces.parsers.SAXParser"
)
;
// эти свойства должны быть установлены для
// проверочной схемы
parser.setFeature
(
"http://xml.org/sax/features/validation"
,
true
)
;
parser.setFeature
(
"http://apache.org/xml/features/validation/schema"
,
true
)
;
}
catch
(
SAXException e
) {
System.err.println
(
"Cannot activate validation."
)
;
}
// синтаксический разбор документа
try
{
System.out.println
(
argv
[
0
])
;
parser.parse
(
argv
[
0
])
;
}
catch
(
SAXParseException e
) {
System.out.println
(
e.getMessage
()
+
" at line "
+ e.getLineNumber
()
+
", column "
+ e.getColumnNumber
())
;
}
catch
(
SAXException e
) {
System.err.println
(
"XML exception reading document."
)
;
}
catch
(
IOException e
) {
System.err.println
(
"I/O exception reading XML document:n"
+ e.getMessage
())
;
}
}
}
Командная строка для запуска этого примера выглядит так:
java validate2 file:tij_menu.xml
Инструкция import подключает Java классы, которые нам необходимы. Здесь подключаются классы из org.xml.sax с поддержкой SAX от W3C. SAX предоставляет общий интерфейс для многих различных синтаксических анализаторов XML. Этот стандартный интерфейс основывается на событиях и предоставляет простейший, низкоуровневый доступ к XML документу.
Первый шаг состоит в синтаксическом анализе документа. Для синтаксического анализа XML документа вам необходим объект XMLReader, который мы просто назовем parser. Мы получим его посредством XMLReaderFactory и укажем главный класс синтаксического анализатора SAX - Xerces: org.apache.xerces.parsers.SAXParser. Этот класс реализует интерфейс org.xml.sax.XMLReader. Каждый синтаксический анализатор должен иметь хотя бы один класс, который реализует этот интерфейс.
Для того, чтобы получить полную схему проверки достоверности, нам необходимо установить две особенности с помощью метода setFeature() синтаксического анализатора. Validation и SchemaValidation должны быть включены. Без SchemaValidation эта программа будет искать DTD.
И наконец, нам необходимо вызвать метод parse нашего синтаксического анализатора XMLReader. Вот и все.
Есть много хороших вещей, который вы можете сделать во время синтаксического разбора документа с помощью SAX. Эта функциональность устанавливается через обработчики. Обработчики - это ничто иное, как callback методы, определяемые SAX, чтобы позволить программисту вставить код приложения на важные события внутри разбираемого документа. Эти события имеют место при разборе документа, а не после того, как он закончится. В SAX 2.0 есть четыре основных интерфейса обработки: org.xml.sax.ContentHandler, org.xml.sax.ErrorHandler, org.xml.sax.DTDHandler и and org.xml.sax.EntityResolver. Классы реализации для этих интерфейсов регистрируются с помощью setContentHandler(), setErrorHandler(), setDTDHandler и setEntityResolver(). XMLReader будет вызывать callback метод для соответствующего обработчика во время синтаксического разбора. Интерфейс ContentHandler имеет callback'и для таких событий, как начало и конец документа, начало и конец элемента, и обработка инструкций.
DOM
Мир, соответствующий DOM, полностью отличается от SAX. Основа сущности DOM'а - это вывод из процесса синтаксического разбора. При использовании SAX наша программа реагировала на специфичные точки в процессе разбора, при использовании DOM данные не могут использоваться до тех пор, пока не будет разобран весь документ. Вывод из синтаксического анализатора DOM предназначен для использования с интерфейсом DOM, определенном в объекте org.w3c.dom.Document. К этому объекту документа применим формат дерева, которое строится на интерфейсе DOM org.w3c.dom.Node. Наследуя от этого интерфейса, DOM предоставляет несколько специфичных для XML интерфейсов - Element, Document, Attr и Text. Ваше приложение, ориентированное на DOM, теперь может перемещать и манипулировать различными аспектами дерева.
Прежде, чем вдаваться в подробности, вы должны немного узнать об эволюции DOM'а. Первая версия DOM'а не имела официальной спецификации, была только объектная модель, которую реализовывали Navigator 3 и Explorer 3 в своих браузерах. Конечно же, эти объектные модели не были полностью законченными, так что я считаю, что в этом случае применим термин DOM Level 0.
DOM Level 1 является попыткой получить совместимость некоторого уровня между браузерами. Необходимо было быстро создать Level 1, прежде чем разные стороны пойдут по противоположным направлениям. Получив такие ограничения, DOM Level 1 был на удивление хорошей спецификацией и охватывал большинство нужд программистов для обработки XML.
DOM Level 2 произвел чистку интерфейсов DOM Level 1. Была добавлена поддержка пространства имен в интерфейсы Element и Attr, и было добавлено некоторое количество поддерживаемых интерфейсов для событий, пересечений, границ, представления и страниц стилей. В настоящее время (2002), все главные синтаксические анализаторы XML поддерживают DOM Level 2 и это должно быть вашим стандартом кодирования.
Скоро выйдет DOM Level 3. Xerces 2 начал поддерживать частично DOM Level 3. DOM 3 будет предоставлять независимые от синтаксического анализатора методы для создания нового объекта Document либо посредством синтаксического разбора файла, либо путем построения черновой формы в памяти. DOM 3 добавит поддержку DTD и Схем. Таким образом, DOM 3 добавит новую функциональность, а ваш код DOM 2 должен продолжать работать.
Вот пример NodeWalker.java, который использует DOM:
import
org.apache.xerces.parsers.DOMParser;
import
org.w3c.dom.*;
public class
NodeWalker
{
static
String outStr
[]
=
new
String
[
250
]
;
static
int
lineNum =
0
;
static public
void
main
(
String
[]
argv
) {
try
{
// Xerces Parser
DOMParser parser =
new
DOMParser
()
;
parser.parse
(
argv
[
0
])
;
Document doc = parser.getDocument
()
;
walker
(
doc.getDocumentElement
())
;
}
catch
(
Exception e
) {
e.printStackTrace
(
System.err
)
;
}
// output
System.out.println
(
"Num of line:"
+ lineNum
)
;
for
(
int
i =
0
; i < lineNum; i++
) {
System.out.println
(
outStr
[
i
])
;
}
}
public static
void
walker
(
Node node
) {
if
(
node ==
null
) {
return
;
}
int
type = node.getNodeType
()
;
switch
(
type
) {
case
Node.ELEMENT_NODE:
{
// Name of this node
outStr
[
lineNum
]
= node.getNodeName
()
;
lineNum++;
// attributes of this node
int
length =
(
node.getAttributes
()
!=
null
)
? node.getAttributes
()
.getLength
()
:
0
;
for
(
int
i =
0
; i < length; i++
) {
Attr attrib =
(
Attr
)
node.getAttributes
()
.item
(
i
)
;
outStr
[
lineNum
]
= attrib.getNodeName
()
;
lineNum++;
}
// children of this node
NodeList children = node.getChildNodes
()
;
if
(
children !=
null
) {
length = children.getLength
()
;
for
(
int
i =
0
; i < length; i++
) {
walker
(
children.item
(
i
))
;
}
}
break
;
}
case
Node.TEXT_NODE:
{
String str = node.getNodeValue
()
.trim
()
;
if
(
str.indexOf
(
"n"
)
<
0
&& str.length
()
>
0
) {
outStr
[
lineNum
]
= str;
lineNum++;
}
break
;
}
}
}
}
Обратите внимание, что метод parse( ) возвращает void. Эти изменения позволяют приложению использовать класс синтаксического анализатора DOM и класс синтаксического анализатора SAX поочередно. Однако для этого требуются дополнительные методы для получения результирующего объекта Document после XML разбора. В случае Apache Xerces такой метод называется getDocument( ).
Метод разбора транслирует поток символов из XML файла в поток признаков. Эти признаки строятся во временную структуру в памяти, программа может переносить ее и манипулировать ей. DOM является API для XML документа. Оно предполагается как объектно-ориентированное представление XML документа, в отличие от абстрактного представления типов данных. Это значит, что каждый компонент документа определен в виде интерфейса, указывающего его поведение. Данные могут быть доступны только через интерфейс. DOM определяет интерфейс Node, а интерфейсы подклассов Element, Attribute и CharacterData наследуются от Node. NodeWalker просто переключает Node.ELEMENT_NODE и Node.TEXT_NODE, мы можем добавить другие узлы, включая CDATA_SECTION и PROCESSING_INSTRUCTION_NODE. Интерфейс Node определяет методы для доступа к компонентам узла. Например, parentNode( ) возвращает родительский узел; childNodes( ) возвращает множество детей. Кроме того, существуют методы для изменения узлов и для создания новых узлов. Поэтому приложение может полностью реструктуризировать документ с помощью DOM.
Интерфейс Document базируется на интерфейсе Node, который поддерживает объект W3C Node. Узлы представляют единичные узлы дерева документа и все, что встречается - текст, комментарии и теги - трактуются как узлы. Интерфейс узла имеет все методы, которые вы можете использовать для работы с узлами и для перемещения по DOM'у. Давайте взглянем на следующий код из примера:
for
(
Node node =
doc.getDocumentElement
()
.getFirstChild
()
;
node !=
null
;
node = node.getNextSibling
()) {
Этот цикл for начинает свою работу с использования метода интерфейса документа getDocumentElement( ) для получения корневого узла документа. Метод getFirstChild( ) интерфейса узла возвращает узел первого дочернего элемента для корня. До тех пор, пока не будет получено значение null, цикл for продолжит движение. Узлы инкрементируются посредством метода getNextSibling( ), который возвращает узел, следующий за вызываемым.
Плюсы и минусы SAX и DOM
Сразу же вы должны понимать, что DOM может потребовать значительных объемов памяти в зависимости от того, насколько велик ваш XML документ и сколько документов будет открыть одновременно. SAX обрабатывает документ последовательно, и при этом нет необходимости считывать весь документ в память. Однако преимущество DOM состоит в том, что у вас есть полностью загруженное дерево в памяти, и вы имеете возможность произвольного доступа ко всему документу. Таким образом, DOM и SAX как Инь и Янь, каждая сильная сторона являются слабостью - каждая слабая сторона является силой.
SAX чаще всего рассматривается с точки зрения синтаксического анализа документа любого размера. Вы можете также построить свою собственную структуру данных, если дерево не подходит для ваших нужд. Другое преимущество SAX состоит в его выгоде, когда вам нужен только небольшой фрагмент данных из документа.
Сила DOM заключена в структуре. При использовании DOM возможен более сложный поиск. Один из наиболее важных аспектов DOM состоит в возможности сериализации данных для реконструкции их в другой программе.
Сериализация XML
Вы должны заметить, что XML дает вам огромное количество инструментов для управления и работы с вашими данными, а цель XML состоит в переносимости данных, вы увидите, что большинство из манипуляций XML станут шаблонным кодом. В процессе обучения вы захотите освободиться от шаблонов и выполнять прямую сериализацию XML в одни и другую сторону.
Сериализация означает вывод XML. Это может быть файл, OutputStream или Writer. Как вы уже читали в предыдущих главах, в Java существует много форма вывода, но эти три используются наиболее широко.
Одно из применений, в которой DOM был достаточно слаб, это сериализация, вывод объекта документа DOM из памяти в текстовый файл. Фактически, есть возможность использовать DOM для создания объекта Документа, который не может быть сериализован в виде хорошо форматированного XML файла. Сериализация было оставлена на совесть производителя реализации таких классов, как XMLSerializer из Xerces. Однако DOM Level 3 добавил несколько классов для записи XML документов в файл, передачи по сети или в любое другое место, куда вы можете зацепиться через OutputStream.
Сериализация Xerces
Проект Apache XML: Xerces-J - включает пакет org.apache.xml.serialize для записи объектов Document DOM в выходной поток. Хотя этот класс связан с Xerces, он работает с любой реализацией DOM Level 2. Здесь нет зависимости от деталей реализации классов Xerces, а только от стандартных интерфейсов DOM.
Механизм сериализации документа с помощью org.apache.xml.serialize таков:
- Сконфигурировать объект OutputFormat с теми параметрами сериализации, которые вам нужны.
- Соединить OutputStream с местом, в котором вы хотите хранить данные.
- Использовать OutputStream и OutputFormat для создания нового объекта XMLSerializer.
- Передать объект Document, который вы хотите сериализировать, в метод serialize() от XMLSerializer.
Вот пример, который примет tij_menu.xml и сериализует его в System.out:
import
org.apache.xerces.parsers.DOMParser;
import
org.apache.xml.serialize.XMLSerializer;
import
org.apache.xml.serialize.OutputFormat;
import
org.w3c.dom.Document;
public class
menuSerializer
{
static public
void
main
(
String
[]
argv
) {
try
{
// Xerces Parser
DOMParser parser =
new
DOMParser
()
;
parser.parse
(
"file:tij_menu.xml"
)
;
Document doc = parser.getDocument
()
;
// serialize document
OutputFormat format =
new
OutputFormat
(
doc
)
;
XMLSerializer output =
new
XMLSerializer
(
System.out, format
)
;
output.serialize
(
doc
)
;
}
catch
(
Exception e
) {
e.printStackTrace
()
;
}
}
}
XMLSerializer имеет несколько конструкторов, которые вы можете использовать в зависимости от того, хотите ли вы записывать в OutputStream или во Writer и хотите ли вы предоставлять OutputFormat во время создания сериализующего объекта:
public
XMLSerializer
()
;
public
XMLSerializer
(
OutputFormat format
)
;
public
XMLSerializer
(
Writer out, OutputFormat format
)
;
public
XMLSerializer
(
OutputStream out, OutputFormat format
)
;
Вы можете, вероятно, определить формат и поток или Writer, когда вы конструируете XMLSerializer. Вы также можете изменить их с помощью таких методов:
public
void
setOutputFormat
(
OutputFormat format
)
;
public
void
setOutputByteStream
(
OutputStream out
)
;
public
void
setOutputCharStream
(
Writer out
)
;
Сериализация DOM Level 3
В конце концов в DOM Level 3 был добавлен стандартный пакет для загрузки и записи, так что теперь будет возможность писать полную реализацию независимой DOM программы. Этот пакет, org.w3c.dom.ls, идентифицируется характеризующей строкой LS-Load и LS-Save. Загрузка выполняется посредством интерфейса DOMBuilder, а запись основывается на интерфейсе DOMWriter. DOMWriter более мощный класс, чем XMLSerializer, потому что он не ограничен выводом документа, фрагмента документа и элементом. DOMWriter может вывести узел любого рода, а фильтры могут быть установлены при контроле вывода.
Спецификация для этого все еще находится в стадии развития. Последние разработки W3C могут быть найдены в: Document Object Model (DOM) Level 3 Abstract Schemas and Load and Save Specification, и в in Xerces-J 2.0.2.
XPath
To do…
XML Трансформации
В начале этой главы мы сказали, что Java предоставляет переносимый код, а XML предоставляет переносимые данные. Прока мы прошлись по всему XML и узнали как определять его, как структурировать, как манипулировать и как выводить. Но если мы хотим, чтобы в XML были переносимые данные, мы должны быть способны трансформировать XML так, чтобы он мог читаться другим приложением, отображаться или печататься. Extensible Stylesheet Language (XSL) предоставляет возможность для доступа и управления данными из XML документа.
XSL сам по себе является XML диалектом и предоставляет два различных и полезных механизма для обработки и манипуляции XML документом. Многие из конструкторов используются обоими механизмами, но каждый играет разную роль. Один из них занимается форматированием данных, а другой занимается трансформацией данных. Когда XSL используется в качестве языка форматирования, страница стилей состоит из объектов форматирования, которые подготавливают документ для отображения, обычно в браузере.
Когда XSL используется для трансформации, XSL принимает форму Extensible Stylesheet Language Transformation (XSLT). Страница стилей XSLT состоит из шаблонных правил, которые соответствуют разделу спецификации XML документа и позволяют преобразовать содержимое XML документа. XSLT может не только преобразовать XML документ из одного диалекта в другой (чаще всего HTML), но и предоставляет многие другие возможности для получения данных из XML документа и управления этими данными.
Java API for XML Processing (JAXP) Summer 2002 Pack поставлялся с другим инструментом от Apache, называемым Xalan. Xalan - это инструмент от Apache.org для выполнения трансформаций. Для выполнения трансформации необходимо два инструмента: синтаксический анализатор и XSL процессор. Мы будем использовать эти инструменты от Apache.
XSLT документ, называемый страницей стилей, содержит серию шаблонов. Каждый шаблон соответствует элементу, атрибуту или и тому, и другому внутри обрабатываемого XML документа. Основной конструктор для шаблонов:
<xsl:template match="pattern"> … rule body … </xsl:template>
Шаблон имеет открывающий (<xsl:template>) и закрывающий (</xsl:template>) тэги. Обычно каждый открывающий тэг шаблона имеет соответствующий атрибут, который указывает часть входного XML документа, для которого предназначен шаблон.
Тело шаблона может состоять из следующего:
- Более детализированного условия выбора или условий сравнения и другой логики
- Специфичный тип выполняемого действия или действий
- Текст, который станет частью результата наряду с выбранным содержимым XML документа
В этом месте вы увидите механизм трансформации XSLT. Во-первых, XML должен пройти синтаксический разбор, а XML документ принять форму дерева. Узлы этого дерева становятся важны в механизме создания сравнений. Во-вторых, это дерево передается в XSLT процессор. XSLT процессор сравнивает узлы дерева с инструкциями в странице стилей. Когда XSLT процессор находит соответствие, он выводит фрагмент. И наконец, вывод сериализируется в другой формат, такой как HTML или новый XML файл.
Давайте создадим пример.
XML в HTML: Отображение меню
Вернемся к примеру с меню, предположим, мы объединили усилия с туристическим бюро и хотим отобразить все рестораны и их базы данных точно так же, как и нашу. Они могут выводить XML для нас, но они не используют те же самые тэги и структуру, так что это не читабельно для нашего сервера. Это означает, что мы хотим преобразовать его.
Начнем простейшего варианта. menu0.xsl является наиболее общей страницей стилей:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> </xsl:stylesheet>
Мы запустим это для нашего файла tij_menu.xml с использованием процессора Xalan XSLT с помощью следующей командной стоки:
java org.apache.xalan.xslt.Process
-in tij_menu.xml
-xsl file:menu0.xsl
-out menu0.html
Мы не сможем напечатать полученный вывод здесь, поскольку он очень большой, но я могу описать его. menu0.html содержит часть текста, которая не была признана тэгом или атрибутом. Каждый текстовый узел был напечатан. Нам необходимо получить контроль над этим процессом. Чтобы получить контроль над процессом трансформации, нам необходимо понимать структуру выходного документа, перемещение по элементам и атрибутам, трансформацию их в желательный нам формат.
Корневой Узел
Корневой узел является узлом XPath, который содержит весь XML документ; это лучшее место для старта. В примере tij_menu.xml корневой узел будет содержать элемент <restaurant>. В выражении XPath корневой узел указывается одиночным слешем -/.
Корневой узел отличается, поскольку он не имеет родителя. Он всегда имеет хотя бы один дочерний узел. Строковое значение корневого узла является конкатенацией всех дочерних текстовых узлов корневого узла. Давайте начнем наше преобразование tij_menu.xml в menu.html путем добавления шаблонов действия для корневого узла. Вот menu1.xsl:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <HTML> <HEAD> <TITLE>Menu</TITLE> </HEAD> <BODY> </BODY> </HTML> </xsl:template> </xsl:stylesheet>
Теперь наш вывод приручен, но у нас нет ничего из нашего файла tij_menu.xml. Весь текст из дочерних узлов потерян. Вот menu1.html:
<HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <TITLE>Menu</TITLE> </HEAD> <BODY></BODY> </HTML>
Мы погрузились в наш простой xml файл только до уровня корневого элемента. Мы напечатали явную оболочку HTML файла. Следующая задача - это пройти по структуре данных нашего tij_menu.xml. Так как мы имеем дело с древесной структурой XML документа, и мы только что обработали корневой узел - это означает, что мы просто применяем эти шаблоны для дочерних узлов, которые соответствуют шаблонам. Это выполняется с помощью элемента <xsl:apply-templates>.
В этом месте нам необходимо добавить две части нашего XML файла. Во-первых, нам необходимо больше правил для обработки различных элементов меню. Во-вторых, нам необходимо иметь процессор, заботящийся о содержимом правила.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <HTML> <HEAD> <TITLE>Menu</TITLE> </HEAD> <BODY> <xsl:apply-templates /> </BODY> </HTML> </xsl:template> <xsl:template match="restaurant"> <center> <h2> <xsl:value-of select="name" /> </h2> <h3> <xsl:value-of select="address/addr1" /> <br /> <xsl:value-of select="address/city" /> , <xsl:value-of select="address/state" /> Phone: <xsl:value-of select="phone" /> <br /> </h3> </center> </xsl:template> </xsl:stylesheet>
Внутри корневого правила я добавил тэг <xsl:apply-templates/>. Он трансформирует все дочерние узлы корневого элемента. Так как корневой элемент содержит только один элемент, <restaurant>, правило будет добавлено в обработчик <restaurant>.
<xsl:template match=”restaurant”> является правилом, которое будет отменено, когда XSLT процессор покинет тэг <restaurant>. Так как только в этом тэге нам необходимо трансформировать данные. Эти данные станут заголовком для меню нашего ресторана - имя ресторана, адрес и номер телефона.
Вывод после трансляции выглядит так:
<HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=UTF-8"> <TITLE>Menu</TITLE> </HEAD> <BODY> <center> <h2>TIJ's Restaurant</h2> <h3>108 Java Sapien Avenue<br>Wayne, PA<br> Phone: 610-687-1234<br> </h3> </center> </BODY> </HTML>
Теперь давайте построим меню. Каждый ресторан имеет, как минимум, один элемент <menu>, элемент <menu> имеет <menugroup>, а элемент <menugroup> имеет <menuitem>. Так что нам осталось добавить остаток правил для обработки этих элементов.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <HTML> <HEAD> <TITLE>Menu</TITLE> </HEAD> <BODY> <xsl:apply-templates /> </BODY> </HTML> </xsl:template> <xsl:template match="restaurant"> <center> <h2> <xsl:value-of select="name" /> </h2> <h3> <xsl:value-of select="address/addr1" /> <br /> <xsl:value-of select="address/city" /> , <xsl:value-of select="address/state" /> <xsl:value-of select="address/zip" /> </h3> </center> <xsl:apply-templates select="menu" /> </xsl:template> <xsl:template match="menu"> <h2>Menu</h2> <dl> <xsl:apply-templates select="menugroup" /> </dl> </xsl:template> <xsl:template match="menugroup"> <dt> <h3> <spacer type="horizontal" size="25" /> <xsl:value-of select="@desc" /> </h3> </dt> <xsl:apply-templates select="menuitem" /> </xsl:template> <xsl:template match="menuitem"> <dd> <b> <spacer type="horizontal" size="25" /> <xsl:value-of select="name" /> : </b> <br /> <ul> <xsl:apply-templates select="description" /> Price: <xsl:value-of select="price" /> <br /> </ul> </dd> </xsl:template> <xsl:template match="description"> <xsl:value-of select="text()" /> <br /> </xsl:template> </xsl:stylesheet>
Элемент <menu> не имеет текстовых узлов, а только элементы <menugroup>. Таким образом, целью при работе с шаблоном меню является создание групп меню так, чтобы они были правильно разграничены и вызывали шаблон группы меню.
Группа меню имеет атрибут, описывающий тип группы меню. Это атрибут desc элемента <menugroup>. Символ "@" должен быть помещен перед именем атрибута, чтобы было выбрано значение с помощью тэга value-of - <xsl:value-of select="@desc"/>. оставшаяся часть правила, кроме описанной, выполняет установки для элемента списока внутри группы меню - <menuitem>.
Правило для <menuitem> выделяет жирным шрифтом имя продукта, затем создает ненумерованный список для оставшихся элементов <menuitem>. Так как некоторые элементы меню имеют описания, а некоторые не имеют, правило создается специально для описания. Если элемент меню имеет описание, правило будет вызвано, а текстовый узел description будет передан в метод text( ) поля выбранного атрибута.
Вот как выглядит заключительная форма HTML.

Ничего затейливого, но вы должны иметь хорошее представление о возможностях XSLT.
XLink и XPointer
To do…
Заключение
В этой главе было введение в некоторые, но не во все, компоненты, которые были введены Sun в пакете JAX-Pack Summer 2002. Целью XML является предоставление переносимых данных, что позволит приложениям, разрабатываемым полностью отдельно друг от друга, обмениваться информацией. XML является как бы зонтиком, собирающим под собой многие технологии, построенные на корнях XML. Эти технологии продолжают быстро эволюционировать и стандартизироваться. В вашем местном книжном магазине многие полки будут заняты книгам, посвященным XML и многие из них будут обновляться. Если вы хотите найти больше информации или остановиться на текущей разработке в мире XML, вы должны направить ваш браузер на W3C - www.w3.org, а разработка XML выполняется сообществом Apache - www.apache.org.
[1] Это значит, что существует более миллиона номеров, которые быстро заканчиваются. Новый стандарт IP адреса будет использовать 128-битные числа, которые должны производить достаточное количество уникальных IP адресов на обозримое будущее.
[2] Многие клетки мозга умирают в агонии при попытке обнаружить эту информацию.
[3] Создан Дэйвом Бартлеттом (Dave Bartlett).
[4] Дэйв Бартлетт (Dave Bartlett) служил орудием при разработке этого материала, а также раздела JSP.
[5] Главная доктрина Екстримального Программирования (Extreme Programming - XP). Смотрите www.xprogramming.com.
[6] Эта глава была написана Джереми Майером (Jeremy Meyer).
[7] Эта глава была создана Андреа Провалио (Andrea Provaglio).
[8] Эта глава была создана Дэйвом Бартлеттом (Dave Bartlett).
← | Группа аксессоров и объекты значения |