Все о JAXP, часть 2

Преобразование XML с использованием набора инструментальных программ обработки XML фирмы Sun

В первой части статьи этой серии вы познакомились с технологией Java API for XML Processing (JAXP) и его функциями синтаксического анализа и проверки корректности. JAXP также предоставляет Java-программистам возможность трансформирования XML-документов с использованием Extensible Stylesheet Language (XSL). Используя либо прямой программный доступ, либо XSL-шаблоны, JAXP делает преобразование одного XML-формата в другой простой задачей. В данной статье рассказывается, как использовать JAXP для преобразования XML-документов и как кэшировать таблицы стилей XSL для получения наивысшей производительности.

Brett McLaughlin, Автор и редактор, O'Reilly Media, Inc.

Бретт Маклафлин (Brett McLaughlin) работает с компьютерами со времен Logo (помните маленький треугольник?). За последние несколько лет он стал одним из наиболее известных авторов и программистов сообщества по технологиям Java и XML. Он работал в Nextel Communications над реализацией сложных корпоративных систем, в Lutris Technologies, фактически, над созданием сервера приложений, а с недавних пор работает в O'Reilly Media, Inc., где продолжает писать и редактировать книги по данной тематике. Его книга "Java 5.0 Tiger: Заметки разработчика" является первой доступной книгой по новейшей технологии Java, а его классическая "Java и XML" остается одной из наиболее авторитетных работ по использованию технологий XML в языке программирования Java.



31.05.2005

В ранних версиях аббревиатура JAXP обозначала Java API for XML Parsing (Java API для синтаксического анализа XML). Как было сказано в первой части, JAXP является слоем над SAX и DOM, позволяющим Java-программистам выполнять независимый от производителя синтаксический анализ XML. Первоначально это было все, что мог делать JAXP. Но, как говорится, то было раньше, а это сейчас.

Когда-то комбинация Java и XML в основном сама использовалась для синтаксического анализа. Java-приложениям нужно было просто прочитать XML-документ и затем программно что-то сделать с данными этого документа. По мере того, как работающие с XML приложения получили широкое распространение, стало очевидно, что "что-то сделать" для различных приложений потребовало значительного объема одинаковых действий. Для любого хорошего программного обеспечения одинаковые действия приводят к спецификации (а также, со временем, к новым полезным API).

Одной из первых спецификаций, появившихся в результате широкого распространения XML, была XSL (см. раздел "Ресурсы"). Приложения постоянно принимают XML-данные, добавляют некоторое форматирование и выдают в пользовательские интерфейсы – обычно HTML, XHTML или WML. XSL взяла на себя эту задачу; была создана спецификация, что дало возможность отказаться в приложениях от частного кода преобразования. Вместе со спецификацией XSL появилась спецификация Transformation API for XML (TrAX) (см. раздел "Ресурсы"). TrAX обеспечила простой, непротиворечивый подход к XSL в Java-приложениях. И теперь JAXP (последнее звено в этой довольно длинной цепочке (и предисловии)) объединила TrAX в ядро среды разработки Java. В свете всей этой эволюции, а также последних дополнений, таких как расширенная проверка корректности и поддержка XPath, JAXP сейчас расшифровывается как Java API for XML Processing. В этой статье внимание концентрируется на использование JAXP для обработки, а не для синтаксического анализа.

Из точки А в точку B

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

Источник (XML)

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

Таблица стилей (XSL)

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

Цель (*ML)

Наконец, вы должны помнить, что из XSL можно получить только корректный язык разметки данных. Вы не можете выдать документы в формате Microsoft Word или PDF. Вы ограничены только языками разметки, такими как XML, XHTML, WML, или каким-нибудь другим замечательным вариантом *ML (markup language).

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


Ввод и вывод

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

Гибкость JAXP

JAXP не является системой преобразования общего назначения. Он не может преобразовать ваши файлы свойств Java, или текстовые форматы, в XML или какую-нибудь другую форму языка разметки. Фактически ,JAXP не может даже принять HTML, если он не является грамматически правильным (и, следовательно, некоторым производным XHTML). Поэтому, перед тем как вы попробуете из JAXP сделать API более общего назначения, чем он есть на самом деле, вы должны осознавать, что начинать надо с грамматически правильного XML, иначе ничего не будет.

Гибкость JAXP заключается в способах представления XML. JAXP может принять XML в виде файла или потока, заключающего в себе файл, что очевидно. Но он может также принять в качестве входной информации DOM Document, представляющий XML-документ, который может не существовать на диске вообще. Или принять последовательность SAX-событий, которые тоже представляют XML-документ. С этой дополнительной гибкостью вы можете вставить JAXP в любую цепочку XML-событий. Например, если у вас имеется код для чтения XML-документа при помощи SAX, передающий определенные части этих данных в другое приложение, вы можете просто вставить JAXP между SAX-кодом и компонентом другого приложения. Он может принимать SAX-события, при необходимости преобразовывать данные и передавать результат компоненту принимающего приложения.

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

Источник входной информации

Интерфейс javax.xml.transform.Source является основой для ввода всех данных в JAXP и API преобразования. Этот интерфейс определяет только два метода: getSystemId() и setSystemId(String systemId). В действительности вы не будете иметь дело с этим интерфейсом непосредственно так часто, как с конкретными реализациями, предоставленными в JAXP:

Программирование интерфейса 101

Если работа с интерфейсами вам в новинку, обратите внимание, что в листинге 1 в левой части оператора присваивания (=) всегда используется интерфейс, а конкретный класс реализации - в правой. Поэтому Source находится слева, а StreamSource, SAXSource, и т.д. - справа.

  • javax.xml.transform.dom.DOMSource передает DOM Node (и его потомков) в JAXP.
  • javax.xml.transform.sax.SAXSource передает результаты функций обратного вызова SAX (из XMLReader) в JAXP.
  • javax.xml.transform.stream.StreamSource передает XML, заключенный в File, InputStream или Reader, в JAXP.

В листинге 1 показано несколько способов создания Source для использования в преобразовании:

Листинг 1. Использование реализаций интерфейса Source
// Создать Source из файла на диске
Source fileSource = 
  new StreamSource(new File("phonebook.xml"));
 
// Создать Source из DOM-дерева
Document myDomDocument = getDocument();
Source domSource = new DOMSource(myDomDocument);

// Создать Source из InputStream
BufferedInputStream bis = 
  new BufferedInputStream(getInputStream());
Source streamSource = new StreamSource(bis);

// Создать Source из reader и SAX InputSource
XMLReader myXMLReader = getXMLReader();
InputSource myInputSource = getInputSource();
Source saxSource = new SAXSource(myXMLReader, myInputSource);

Листинг 1 не требует пояснений. Как только вы получили Source - вы готовы передать ваш XML в обрабатывающую XSL часть JAXP.

Результат для вывода

Перед переходом к самим преобразованиям я дам обзор выводимого эквивалента Source - javax.xml.transform.Result. Он даже имеет такие же два основных метода, как и Source: getSystemId() и setSystemId(String systemId).

Как и в ситуации с входным эквивалентом, вы будете обычно использовать конкретные реализации Result:

  • javax.xml.transform.dom.DOMResult передает преобразованные данные в DOM Node.
  • javax.xml.transform.sax.SAXResult передает результаты преобразования в SAX ContentHandler.
  • javax.xml.transform.stream.StreamResult передает преобразованный *ML в File, OutputStream, или Writer.

В листинге 2 показано несколько простых примеров, почти аналогичных тем, что приведены для Source в листинге 1:

Листинг 2. Использование реализаций интерфейса Result
// Записать в файл на диске
Result fileResult = 
  new StreamResult(new File("output.xml"));
 
// Записать результат в DOM-дерево (вставленный в предоставленный Document)
Document myDomDocument = getDocument();
Result domResult = new DOMResult(myDomDocument);

// Создать Result из OutputStream
BufferedOutputStream bos = 
  new BufferedOutputStream(getOutputStream());
Result streamResult = new StreamResult(bos);

// Создать Result для записи в SAX ContentHandler
ContentHandler myContentHandler = new MyContentHandler();
Result saxResult = new SAXResult(myContentHandler);

После того, как вы начнете понимать интерфейсы Source и Result (и реализации, включенные в JAXP), - вы на полпути к овладению XML-преобразованиями.


Выполнение преобразований с использованием JAXP

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

Получение конструктора

Преобразования настолько просты, что являются почти тривиальными. Прежде всего, вам необходимо установить входные и выходные объекты. Заключите в Source ваш входной XML-документ и вашу таблицу стилей. Затем создайте объект для записи результатов преобразования и заключите его в интерфейс Result.

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

Листинг 3. Создание нового экземпляра TransformerFactory
try {
  // Установка входных документов
  Source inputXML = new StreamSource(
    new File("phonebook.xml"));

  Source inputXSL = new StreamSource(
    new File("phonebook.xsl"));

  // Установка выходного объекта
  Result outputXHTML = new StreamResult(
    new File("output.html"));

  // Настройка конструктора для преобразований
  TransformerFactory factory = TransformerFactory.newInstance();

} catch (TransformerConfigurationException e) {
  System.out.println("The underlying XSL processor " +
    "does not support the requested features.");
} catch (TransformerException e) {
  System.out.println("Error occurred obtaining " +
    "XSL processor.");
}

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

Тождественность преобразования

Одна версия TransformerFactory.newTransformer() не принимает никаких аргументов (и, следовательно, не принимает таблицу стилей XSL). Она позволяет выполнять тождественные преобразования, которые просто преобразуют входной XML-документ из одной формы (например потока) в другую (например DOM-дерево). Вы предоставляете XML как Source в одном формате и получаете его как Result в другом формате. Это хороший прием, который стоит запомнить.

Сам класс конструктора используется для получения экземпляра Transformer (обсуждаемого в следующем разделе) и для выполнения простой конфигурации. Вы можете использовать метод setFeature(String feature, boolean value) для активизации функций в процессоре. Естественно, любые функции, установленные в конструкторе, будут применены ко всем экземплярам Transformer, созданным с его помощью.

Создание Transformer

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

Листинг 4. Использование TransformerFactory для создания Transformer
try {
  // Установка входных документов
  Source inputXML = new StreamSource(
    new File("phonebook.xml"));

  Source inputXSL = new StreamSource(
    new File("phonebook.xsl"));

  // Установка выходного объекта
  Result outputXHTML = new StreamResult(
    new File("output.html"));

  // Настройка конструктора для преобразований
  TransformerFactory factory = TransformerFactory.newInstance();

  // Получить transformer для этого XSL
  Transformer transformer = factory.newTransformer(inputXSL);

} catch (TransformerConfigurationException e) {
  System.out.println("The underlying XSL processor " +
    "does not support the requested features.");
} catch (TransformerException e) {
  System.out.println("Error occurred obtaining " +
    "XSL processor.");
}

Здесь нет ничего примечательного; единственное, что вы не должны пропустить – соединение между Transformer и конкретной таблицей стилей. Поскольку таблица стилей используется при создании Transformer, это единственный XSL, который вы можете использовать с экземпляром. Если вы хотите выполнить дополнительные преобразования, используя другую таблиц стилей, то можете повторно применить TransformerFactory, но должны создать другой экземпляр Transformer, связанный с новой таблицей стилей.

Выполнение преобразования

Еще вам нужна только одна строка кода для выполнения преобразования. В листинге 5 показано, как использовать метод transform(). Просто передайте в него ваш исходный XML и выходной объект; таблица стилей уже привязана к используемому экземпляру Transformer.

Листинг 5. Использование метода transform()
try {
  // Установка входных документов
  Source inputXML = new StreamSource(
    new File("phonebook.xml"));

  Source inputXSL = new StreamSource(
    newFile("phonebook.xsl"));

  // Установка выходного объекта
  Result outputXHTML = new StreamResult(
    new File("output.html"));

  // Настройка конструктора для преобразований
  TransformerFactory factory = TransformerFactory.newInstance();

  // Получить transformer для этого XSL
  Transformer transformer = factory.newTransformer(inputXSL);

  // Выполнить преобразование
  transformer.transform(inputXML, outputXHTML);

} catch (TransformerConfigurationException e) {
  System.out.println("The underlying XSL processor " +
    "does not support the requested features.");
} catch (TransformerException e) {
  System.out.println("Error occurred obtaining " +
    "XSL processor.");
}

После вызова этого метода результат преобразования записывается в предоставленный объект Result. В листинге 5 это файл, но вы можете также передать результат в SAX ContentHandler или DOM Node. Если вы хотите попробовать все это, дистрибутив содержит простой XML-файл, таблицу стилей XSL и исходный код (См. раздел "Загрузка").


Кэширование таблиц стилей XSL

При такой простоте рассмотренного нами кода использование JAXP подобным образом имеет два серьезных ограничения:

  • Объект Transformer обрабатывает таблицу стилей XSL каждый раз при вызове transform().
  • Экземпляры Transformer не являются потокобезопасными. Вы не можете использовать одни и те же экземпляры в разных потоках.

Оба эти ограничения являются следствием одной и той же проблемы: Transformer должен повторно обрабатывать XSL каждый раз при выполнении преобразования. Если эта обработка выполняется в нескольких потоках, вы можете столкнуться с серьезными проблемами. Кроме проблем с потоками вы должны тратить ресурсы на обработку таблицы стилей XSL снова и снова. Без сомнения вы жаждете найти решение этих проблем. Читайте дальше.

Загрузка шаблона

Интерфейс, который я еще не обсуждал (javax.xml.transform.Templates), находится рядом с javax.xml.transform.Transformer. Интерфейс Templates является потокобезопасным (снимая второе ограничение) и предоставляет компилированную таблицу стилей (снимая первое ограничение). Перед тем как я перейду к объяснению концепции, просмотрите листинг 6:

Листинг 6. Использование интерфейса JAXP Templates
try {
  // Установка входных документов
  Source inputXML = new StreamSource(
    new File("phonebook.xml"));

  Source inputXSL = new StreamSource(
    new File("phonebook.xsl"));

  // Установка выходного объекта
  Result outputXHTML = new StreamResult(
    new File("output-templates.html"));

  // Настройка конструктора для преобразований
  TransformerFactory factory = TransformerFactory.newInstance();

  // Предкомпиляция команд
  Templates templates = factory.newTemplates(inputXSL);

  // Получить transformer для этого XSL
  Transformer transformer = templates.newTransformer();

  // Выполнить преобразование
  transformer.transform(inputXML, outputXHTML);

} catch (TransformerConfigurationException e) {
  System.out.println("The underlying XSL processor " +
    "does not support the requested features.");
} catch (TransformerException e) {
  System.out.println("Error occurred obtaining " +
    "XSL processor.");
}

Выделенные жирным шрифтом в листинге 6 строки представляют единственные необходимые изменения по сравнению с листингом 5. Вместо использования конструктора для получения Transformer напрямую, используется метод newTemplates(); он возвращает объект Templates, который является потокобезопасным. Вы можете передать этот объект в другие методы (в других потоках) и не беспокоиться ни о чем. Поскольку этот метод выполняет предварительное компилирование команд преобразования из переданного ему XSL, его можно безопасно передать в другие методы и даже потоки.

Далее, вы получаете экземпляр Transformer из метода Templates.newTransformer(). Нет необходимости указывать на этом этапе XSL, поскольку Transformer уже обработал ее (и, фактически, откомпилировал эту XSL, поэтому вы не можете при желании сменить таблицу стилей). Кроме дополнительной строки и изменения существующей строки здесь нет ничего нового. Очень здорово, учитывая насколько становится лучше ваш код в результате этого маленького изменения.

От Transformer к Templates

Последний вопрос, который стоит рассмотреть: когда использовать Transformers непосредственно из конструктора, а когда использовать объекты Templates. Я почти всегда предпочитаю работать с объектом Templates, поскольку, используя XSL, я обычно применяю одну и ту же таблицу стилей неоднократно. Вместо траты времени на несколько проходов по XSL я предпочитаю предварительно откомпилировать команды в объект Templates и выполнить XSL-обработку.

В некоторых случаях лучше работать с Transformer, непосредственно полученным из вашего TransformerFactory. Если вы знаете, что выполните только одно преобразование, используя конкретную таблицу стилей, быстрее будет не выполнять компиляцию в объект Templates (что требует некоторых дополнительных затрат ресурсов). Тем не менее, вы должны быть уверены в отсутствии повторного использования. В моих тестах (полностью ненаучных, с использованием примера меньшего, чем надо, размера) я обнаружил, что как только я дважды использовал таблицу стилей XSL, появляется разница между использованием объекта Templates по сравнению с использованием Transformer напрямую. Если использовать ее три раза - подход с использованием объекта Templates выигрывает. Вы также должны быть уверены, что не собираетесь иметь несколько потоков; это легко определить, что я и оставляю вам на рассмотрение и использование при программировании. Как общее правило: почти всегда безопаснее работать с объектом Templates.


Замена XSL-процессора

В первой части вы видели, что можно заменить реализацию JAXP-анализатора по умолчанию вашей собственной реализацией путем изменения системного свойства. Такие же принципы применимы и для XSL-процессора. JAXP поставляется вместе с Xalan-J (см. раздел "Ресурсы"), который я постоянно использую. Но гибкость – это всегда хорошо. JAXP предоставляет ее.

Если вы хотите использовать процессор, отличный от Xalan, укажите значение системного свойства с названием javax.xml.transform.TransformerFactory. Вам необходимо присвоить этому свойству название класса, экземпляр которого хотите создать. Класс должен расширять javax.xml.transform.TransformerFactory (да, это также название системного свойства для установки) и заполнять абстрактные методы. Просто используйте, например, нечто подобное:

java -Djavax.xml.transform.TransformerFactory=[transformer.impl.class] TestTransformations 
      simple.xml simple.xsl

Это все!


Заключение

В своих ранних воплощениях JAXP представлял из себя лишь немногим больше, чем тонкую прослойку над SAX и DOM, к тому же над старыми версиями этих API. Сейчас с JAXP 1.3 вы можете выполнять синтаксический анализ, проверку корректности и преобразование XML даже без написания одной единственной строчки зависимого от производителя кода. Хотя часто имеет смысл спуститься в SAX-код или использовать такие инструменты как DTDParser (см. раздел "Ресурсы"), или даже обрабатывать преобразования самостоятельно, вам необходимо иметь JAXP в своем арсенале API и инструментальных средств. Возможно, даже более важным, чем независимость от производителя, является то, что все ваши пользователи и клиенты с последними версиями Java Virtual Machine (JVM) имеют JAXP. Поэтому используйте его, используйте правильно и используйте часто.


Загрузка

ОписаниеИмяРазмер
Sample code for All about JAXP, Part 1x-jaxp2-all-about.zip4 KB

Ресурсы

  • Оригинальная статья "All about JAXP, Part 2"
  • Прочитайте первую часть этой серии статей, в которой дается введение в JAXP и его функций синтаксического анализа и проверки корректности.
  • Посетите форум developerWorksXML and Java technology, который ведет Брэт Маклафлин (Brett McLaughlin), для получения дополнительной информации о работе с этими двумя технологиями.
  • Дополнительную информацию о JAXP можно найти на странице технологий Java и XML фирмы Sun.
  • Если вы новичок в программировании на языке Java, вы можете получить JAXP вместе с полным JDK, загрузив дистрибутив Java 5.0.
  • Стандарты XSL опубликованы на сайте World Wide Web Consortium (W3C).
  • Загрузите Apache Xalan, XSL-процессор в реализации JDK 5.0 фирмы Sun.
  • Sun использует анализатор Apache Xerces в своей реализации JDK 5.0.
  • Прочитайте серию статей (состоящую из двух частей) "Что нового в JAXP 1.3?", содержащую подробный обзор новых функций в JAXP 1.3:
    • В части 1 (ноябрь 2004) предоставляется краткий обзор спецификации JAXP, детально рассматриваются изменения в пакете javax.xml.parsers и описывается схема кэширования и проверка корректности.
    • В части 2 (декабрь 2004) описываются инструменты, добавляющие поддержку определенных в спецификации Namespaces in XML концепций. В ней также описываются изменения в пакете javax.xml.transform.
  • Прочитайте больше о Transformation API for XML (TrAX), который сейчас является частью JAXP.
  • В статье "Работа с XSL-преобразованиями" (developerWorks, октябрь 2001) приведено введение в XSL и обсуждение реального бизнес сценария, в котором успешно используются XSL-преобразования.
  • Прочитайте книгу Бретта Маклафлина (Brett McLaughlin) "Java и XML"№(O'Reilly & Associates, 2001), в которой объясняется использование XML для создания корпоративных Web-приложений.
  • Изучите подробнее API, с которыми работает JAXP. Начните с SAX 2 for Java на web-сайте SAX, а затем взгляните на DOM на Web-сайте W3C.
  • Изучите JDOM, набор инструментальных программ с открытым исходным кодом, обеспечивающий способ представления XML-документов в языке программирования Java для легкого и эффективного чтения, записи и обработки.
  • Прочитайте статью "Работая с XML: Обработка команд и параметров" (developerWorks, сентябрь 2001) для изучения способов использования нескольких таблиц стилей в простой системе управления информацией.
  • В учебнике Дуга Тидвела (Doug Tidwell) "XML-программирование в технологии Java, Часть 1" (developerWorks, январь 2004) рассмотрены основы обработки XML-документов с использованием технологии Java. Во второй части (июль 2004) рассмотрены более сложные темы, такие как работа с пространством имен, проверка корректности XML-документов, построение XML-структур без обычного XML-документа. Наконец, в третьей части (июль 2004) рассматриваются более сложные задачи, такие как генерирование структур XML-данных, обработка этих структур и интерфейс XML-анализаторов с источниками данных формата, отличного от XML.
  • Если вы интересуетесь анализатором, работающим с DTD непосредственно, не через API проверки корректности, обратите внимание на удобный DTDParser от Mark Wutka.
  • На сайте developerWorks Developer Bookstore можно найти множество материалов по XML.
  • Узнайте, как стать IBM Certified Developer в XML и смежных технологиях.

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=XML, Технология Java
ArticleID=96639
ArticleTitle=Все о JAXP, часть 2
publish-date=05312005