IBM®
Перейти к тексту
    в России и странах СНГ [изменить]    Условия использования
 
 
   
    Главная страница    Продукты    Услуги и решения    Поддержка и загрузка    Мой профиль    
Перейти к тексту

developerWorks Россия  >  XML | Технология Java  >

Обработка XML в J2ME-приложениях

Объедините мобильную информацию и мобильный код в вашем мобильном устройстве

developerWorks
Опции документа

Опции документа, требующие включения JavaScript, не отображаются

Обсудить


Выскажите мнение об этой странице

Помогите нам улучшить содержание


Уровень сложности: простой

Сома Гош, старший по разработке приложений, Entigo

27.06.2007

MIDP-программисты уже сегодня могут пользоваться XML в своих приложениях для мобильных устройств. В этой статье мы рассмотрим пример одного такого приложения.

Совместное использование технологий Java и XML представляет очень мощную и эффективную комбинацию переносимого кода и переносимых данных. Но каким образом этот синтез можно заставить работать на платформе Java 2, Micro Edition (J2ME)? В этой статье мы рассмотрим пример одного из урезанных XML-парсеров, который был сжат до таких размеров, что его стало возможным использовать в J2ME-приложениях на платформах с ограниченными системными ресурсами. Для написания нашего приложения для MIDP-платформы, которое будет разбирать XML-документы, мы будем использовать пакет kXML. Но для начала сделаем обзор XML-парсеров и определим, почему они так долго шли к тому, чтобы перейти на платформу J2ME.

Обзор XML-парсеров

Модель обработки XML описывает шаги-операции, которые должно выполнить приложение для обработки полного XML; приложения, которые реализуют такую модель, принято называть XML-парсерами. Вы можете достаточно просто интегрировать любой XML-парсер в любые Java-приложения с помощью Java API for XML Processing (JAXP). JAXP позволяет приложениям разбирать и преобразовывать XML-документы с помощью API, который не зависит от определенной реализации XML-процессора. Благодаря plug-in-подобному механизму, разработчики могут менять реализацию XML-процессора (XML-парсер) на другую без необходимости изменять код самого приложения.

Процесс разбора XML проходит в три фазы:

  1. Обработка входного XML-файла. На этой стадии приложение разбирает исходный документ и осуществляет проверку на соответствие его всем стандартам (спецификации), распознает и ищет нужную информацию по его местоположению или имени тегов в исходном документе; извлекает эту информацию, как только она была обнаружена и, опциально, отображает эту информацию в бизнес-объекты.
  2. Отработка описанной бизнес-логики. Это стадия, на которой выполняется фактическая обработка получаемой информации. Результатом работы на этой стадии может явиться генерация выходной информации.
  3. Обработка выходного представления XML-файла. На этой стадии приложение конструирует модель документа, которая будет представлена с помощью DOM-дерева (Document Object Model). После чего, для получения выходного формата применяются таблицы стилей XSLT или же просто DOM-объект сериализуется напрямую в XML.

SAX (Simple API for XML) и DOM - это наиболее общие модели обработки XML. Если вы используете парсер на основе SAX для обработки XML-документа, вам будет необходимо определить методы для обработки событий, выбрасываемых парсером в случае, когда он обнаружит очередной опознавательный знак языка разметки. Поскольку SAX-парсер генерирует кратковременный поток событий, процесс обработки входного XML-файла (первая фаза разбора XML, упомянутая выше) будет выполнена в одном цикле: каждое возникшее событие немедленно обрабатывается и нужная информация также извлекается автоматически.

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

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



В начало


Обработка XML в среде MIDP

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

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

Существует два наиболее популярных XML-парсера, которые обычно используются для работы на устройствах с ограниченными системными ресурсами. Это kXML и NanoXML. kXML был написан специально для использования на J2ME-платформе (CLDC и MIDP). Что же касается NanoXML, то его версия 1.6.8 для MIDP уже имеет поддержку разбора XML по модели DOM (за более подробной информацией по NanoXML и kXML обращайтесь к ссылкам, приведенным в конце этой статьи).



В начало


Проблемы производительности

Существует ряд проблем производительности приложений, которые вы должны иметь в виду при разборе XML в своих MIDP-приложениях:

  • Увеличенный размер. Использование XML-парсеров зачастую приводит к значительному увеличению кода приложения. Это особенно болезненно в случае с MIDP-устройствами. Однако существует несколько приемов, применив которые, вы, возможно, сможете избежать излишнего расширения кода вашего приложения. Во-первых, вы должны удалить файлы ресурсов, которые вы используете. Помимо этого, крайне желательно воспользоваться обфускаторами (obfuscators), которые удалят за вас неиспользуемые классы, методы и различные переменные из JAD-файла.
  • Разбор крупных строк. XML-парсеры используют нагруженные строки для выполнения своей работы. Таким образом, они сильно перегружают MIDP-приложения, оставляя для его работы слишком мало оперативной памяти. XML-документы для разбора в J2ME-приложениях должны состоять только из небольших строк и содержать как можно больше именно полезной (необходимой) информации.
  • Медлительные отклики. Как только MIDP-приложение приступит к разбору относительно больших объемов XML-данных, то время на их обработку очевидно возрастет. Поэтому XML-файлы, которые будут разбираться, должны быть небольшими и обработка этих файлов должна происходить в отдельном вычислительном потоке от основного приложения.

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



В начало


Разбор XML в J2ME-приложении

В этой части статьи, приступим к разработке J2ME-приложения, ParseXML, которое будет разбирать XML-документы в формате стандарта RSS (Rich Site Summary) и отображать информацию, закодированную в этих документах на экране телефона. RSS - это сравнительно простой XML-формат, который определяет стандарт определения заголовков и описаний новостей, которые размещаются на новостном или обычном сайтах. Ниже приведен пример RSS-документа:


Листинг 1.RSS-данные, которые будут обрабатываться приложением
                
<?xml version="1.0"?>
<!DOCTYPE rss PUBLIC 
"-//Netscape Communications//DTD RSS 0.91//EN" 
"http://my.netscape.com/publish/formats/rss-0.91.dtd"
>
<rss version="0.91"> 
<channel> 
<title>Meerkat: An Open Wire Service</title> 
<link>http://meerkat.oreillynet.com</link> 
<description>
Meerkat is a Web-based syndicated content reader based on RSS ("Rich Site Summary"). 
RSS is a fantastic, simple-yet-powerful syndication system rapidly gaining momentum.
</description>
</channel>
</rss>

Во время выполнения ParseXML выводит на экран телефона заголовок и описание к нему, которые он берет из приведенного выше RSS-файла. Все вопросы организации пользовательского интерфейса (UI) берет на себя пакет javax.microedition.lcdui.

В этом приложении используется XML-парсер kXML версии 1.2. Для того чтобы сделать классы kXML доступными приложению, необходимо скачать файл kxml.zip. Он содержит все пакеты этого парсера. Этот файл можно найти на официальном сайте проекта kXML (смотрите раздел "Ресурсы" в конце статьи). После этого необходимо скопировать содержимое архива в нужную папку разрабатываемой вами системы. Если вы используете инструментарий J2ME от Sun (смотри раздел "Ресурсы"), то скопировать содержимое архива следует в TOOLKIT_HOME\apps\ParseXML\lib.

В начале своей работы J2ME-приложение выводит текстовое поле, кнопку, при нажатии на которую посылается запрос на вывод разобранных данных XML, и кнопку выхода Exit. При нажатии на кнопку "Display XML" вызывается метод viewXML(). В этом методе, приложение создает экземпляр класса XMLParser, который и будет служить обработчиком XML-документа. При нахождении очередной записи, парсер будет искать содержимое этого элемента: title и description, чтобы найти текст, который нужно вывести на дисплей телефона. Этот процесс протекает рекурсивно. Пользователь может прервать его в любой момент, нажав кнопку Exit.

RSS-данные будут доступны ParseXML в форме объекта класса String. Поскольку XML-парсер работает только с потоком байт, то объект класса String конвертируется в массив байтов. Этот массив используется для создания объекта класса ByteArrayInputStream. В свою очередь, ByteArrayInputStream используется для создания экземпляра класса InputStreamReader, который создает экземпляр класса ParseXML. Это процесс проиллюстрирован в листинге, приведенном ниже:


Листинг 2. Создание экземпляра для разбора строки, содержащей RSS-данные
                
byte[] xmlByteArray = xmlStr.getBytes();
		ByteArrayInputStream xmlStream = new 
		ByteArrayInputStream( xmlByteArray );
		InputStreamReader xmlReader = new 
		InputStreamReader( xmlStream );
		 XmlParser parser = new XmlParser( xmlReader );

Для того чтобы получить данные с новостного или любого другого сайта, приложение должно открыть URL-соединение и прочитать RSS-данные из полученного объекта-потока InputStream. Сам же объект класса InputStream доступен для ParseXML посредством объекта InputStreamReader. Ниже приведен отрывок кода, который это реализует:


Листинг 3. Получение RSS-данных с сайта
                
HttpConnection hc = (HttpConnection)Connector.open(url);
InputStream is = hc.openInputStream();
Reader reader = new InputStreamReader(is);
    XmlParser parser = new XmlParser(reader);

Когда метод класса ParseXML read() обнаруживает элемент, он возвращает объект класса ParseEvent. Этот объект содержит важную информацию, например, тип события (это может быть начало тэга, конец тэга, конец документа, текст или пробельные символы), имя события (фактически - это имя тэга) и текст события (это текст, заключенный в начальный и конечный тэги одного элемента). Как будет показано в нижеследующем листинге, в нашем примере парсер ищет тэги с именем title и description, после этого идет дальше, чтобы получить их содержимое для вывода на экран.

Объект ParseEvent генерирует события (Event) типов Xml.START_TAG, Xml.END_TAG, Xml.END_DOCUMENT, Xml.WHITESPACE и Xml.TEXT, когда он обнаруживает начало тэга, конец тэга, конец документа, пробельные символы и текст, заключенный в тэги, соответственно.


Листинг 4. Сбор заголовка и описания из RSS-данных
                 
case Xml.START_TAG:
	 // просмотрите в API doc в StartTag иные способы доступа	 
	 // сбор заголовка для отображения
	  if ("title".equals(event.getName()))
	  	{
			pe = parser.read();
			title = pe.getText();
		}
	 // сбор описания для отображения
	  if ("description".equals(event.getName()))
	  {
	  		pe = parser.read();
	  		desc = pe.getText();
	  }


Следующий листинг содержит полный вариант исходного кода приложения ParseXML.


Листинг 5. ParseXML-приложение
                
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;
//импорт kxml
import org.kxml.*;
import org.kxml.parser.*;
public class ParseXML extends MIDlet implements CommandListener {
private Command exitCommand; // комманда выхода
private Command displayXML; // По выполнении отображает заголовок и описание 
                            // на экране телефона
private Display display;     // отображение для данного MIDlet
// UI-элементы для отображения заголовка и описания на экране телефона
private static TextBox t;
private static String textBoxString = "";
// XML-строка
private String xmlStr = "";
public ParseXML() {
	 display = Display.getDisplay( this );
	 exitCommand = new Command( "Exit", Command.EXIT, 2 );
	 displayXML  = new Command( "XML", Command.SCREEN, 1 );
	// XML-строка в форме RSS
	StringBuffer xmlString = new StringBuffer();
	xmlString.append("<?xml version=\"1.0\"?>
                <!DOCTYPE rss PUBLIC \"-//Netscape Communications//DTD RSS 0.91//EN\""); 
	xmlString.append("\"http://my.netscape.com/publish/formats/rss-0.91.dtd\">");
	xmlString.append("<rss version=\"0.91\">"); 
	xmlString.append("<channel><title>Meerkat: An Open Wire Service</title>");
	xmlString.append("<link>http://meerkat.oreillynet.com</link>");
	xmlString.append("<description>Meerkat is a Web-based syndicated content
                             reader based on RSS (\"Rich Site Summary\").
                             RSS is a fantastic, simple-yet-powerful syndication 
                             system rapidly gaining momentum.");
	xmlString.append("</description><language>en-us</language>");
	xmlString.append("</channel>");
	xmlString.append("</rss>");
	xmlStr = xmlString.toString();
 }
public void startApp() {
	  // текстовое окно отображает заголовок из RSS-строки
	  t = new TextBox( "MIDlet XML", "kXML", 256, 0 );
	  t.addCommand( exitCommand );
	  t.addCommand( displayXML );
	  t.setCommandListener( this );
	  display.setCurrent( t );
 }
/**
"пауза" является холостой командой, когда нет фоновых 
/**
действий или хранилищ записей, которые необходимо закрыть

*/
public void pauseApp() { }
/**
Удаление должно стирать все, что не обработано сборщиком мусора.
/**
В этом случае стирать нечего.
*/
public void destroyApp(boolean unconditional) { }
/*
Срабатывает на комманды, в том числе выхода.По комманде выхода происходит очистка
/*
и извещение о том, что MIDlet был уничтожен.
*/
public void commandAction(Command c, Displayable s) {
	if ( c == exitCommand ) {
		destroyApp( false );
		notifyDestroyed();
	} 
	else if ( c == displayXML ) {
		try {
			viewXML();
		}
		catch( Exception e ) {
				e.printStackTrace();
		}
	 }
}
// Эта функция устанавливает парсер kxml и вызывает traverse() 
//для полного анализа XML String
public void viewXML() throws IOException {
	 try {
		byte[] xmlByteArray = xmlStr.getBytes();
		ByteArrayInputStream xmlStream = new 
		ByteArrayInputStream( xmlByteArray );
		InputStreamReader xmlReader = new 
		InputStreamReader( xmlStream );
		 XmlParser parser = new XmlParser( xmlReader );
		 try
		 {
			 traverse( parser, "" );
		 }
		 catch (Exception exc)
		 {
			 exc.printStackTrace();
		 }
		return;
} 
catch ( IOException e ) {
	      return ;
	 } finally {
	return ;
	 }
 }
/**
прохождение XML-файла
*/
public static void traverse( XmlParser parser, String indent ) throws Exception
{
	boolean leave = false;
	String title = new String();
	String desc = new String();
	do {
	ParseEvent event = parser.read ();
	ParseEvent pe;
	switch ( event.getType() ) {
	 // Например, <title> 
	 case Xml.START_TAG:
	 // просмотрите в API doc в StartTag иные способы доступа
	 // сбор заголовка для отображения
	  if ("title".equals(event.getName()))
	  	{
			pe = parser.read();
			title = pe.getText();
		}
	 // сбор описания для отображения
	  if ("description".equals(event.getName()))
	  {
	  		pe = parser.read();
	  		desc = pe.getText();
	  }
	  textBoxString = title + " " + desc;
	  traverse( parser, "" ) ; // recursion call for each <tag></tag>
	  break;
	  // Например, </title?
	 case Xml.END_TAG:
	  leave = true;
	  break;
	  // Например, </rss>
	 case Xml.END_DOCUMENT:
	  leave = true;
	  break;
	  // Например, текст между тэгами
	 case Xml.TEXT:
	  break;
	 case Xml.WHITESPACE:
	  break;
	  default:
	  }
	  } while( !leave );
	  t.setString( textBoxString );
  }
}


На изображении показано приложение ParseXML в действии.


Figure 1. приложение ParseXML в действии
приложение ParseXML в действии


В начало


Заключение

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



Ресурсы



Об авторе

Специалист по компьютерам Сома Гош(Soma Ghosh) за последние шесть лет разработала широкий спектр Java-приложений в области электронной коммерции и сетевых вычислений. Она считает, что ближайшим будущим данной отрасли является беспроводная коммерция, и недавно перешла от моделей настольных компьютеров к беспроводным технологиям. Она в настоящее время является старшим разработчиком приложений в Entigo - пионере в B2B-продуктах и решениях в области электронной коммерции. Адрес для контактов: sghosh@entigo.com.




Выскажите мнение об этой странице


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



ДаНетНе знаю
 


 


12345
 


В начало


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

    IBM в России Конфиденциальность Контакты