Po delší odmlce je zde další článek pro ty, jenž se chtějí opět něco dozvědět o možnostech J2ME. Jak již z názvu plyne, budeme se dnes zabývat XML a jeho použitím v MIDp aplikacích. Cílem článku je ukázat použití knihoven, které můžeme pro práci s XML na internetu nalézt, ukázat jejich možnosti a shrnout jejich vlastnosti. Na konec článku si vytvoříme malý příklad.

Co je to XML?

XML nebo-li eXtended Markup Language je jazyk (formát) pro distribuci dat. XML dokument je pouze nosič dat a záleží pouze na aplikace, jak data reprezentuje (tabulka, graf). Protože formát je čístý text, je lehce čitelný pomocí běžných textových editorů a implementačně nezávislý. Nevýhodou formátu je, že s sebou nese spoustu dalších informací, které jsou nezbytné pro zpracování dat.

XML a J2ME

Chcete-li se svoji MIDp aplikací přistupovat k některým serverovým aplikacím a službám, tak se určitě nevyhnete práci s daty, jenž jsou ve formátu XML. Abychom mohli pracovat s daty v XML potřebujeme příslušný parser. Máme dvě možnosti buď si parser napíšeme sami, nebo použijeme některou z knihoven, které jsou přístupné na internetu. My si představíme dvě knihovny: kXML a NanoXML.

Každá MIDp aplikace je omezena svoji výslednou velikostí z toho plynou i požadavky na XML parser: malá paměťová náročnost a malá velikost zdrojových souborů. Za tuto vlastnost obvykle platíme absencí některých funkcí, které jsou u klasických XML parserů samozřejmostí např. validace XML dokumentu (DTD – Document Type Definition) a zpracování smíšeného obsahu. Můžeme říci, že existují tři základní typy XML parserů:

  • Model – přečte celý dokument a vytvoří jeho reprezentaci v paměti. Tento typ parseru je ze všech tří modelů nejvíce náročný na paměť.
  • Push – prochází celý dokument a podle toho, kterou část dokumentu nalezne vyvolá příslušnou událost.
  • Pull – čte dokument po částech, které jsou postupně zpracovávány aplikací.

kXML parser

Tato knihovna patří do skupiny tzv. Pull parserů. Tyto parsery mají menší paměťové nároky, ale o to více zabírají místa ve výsledném balíku JAR. Jedná se o parser, který byl vytvořen přímo pro použití v MIDp aplikacích. Nepodporuje validaci dokumentu prostřednictvím DTD (Document Type Definition).

Vlastnosti:

  • Podpora jmenných prostorů (namespaces)
  • Parsrování vnořeného/modulového obsahu
  • Malá paměťová náročnost
  • Volitelně podpora kDOM
  • Volitelně podpora WBXML/WML

Další informace o této knihovně můžete nalézt na adrese kxml.enhydra.org.

NanoXML/Lite parser

Tento praser patří do skupiny tzv. modelových a stejně jako předchozí nepodporuje validaci dokumentu a parsrování smíšeného obsahu. Mezi jeho hlavní přednosti je velikost a rychlost zpracování dokumentů. Nevýhodou je větší náročnost na paměť. Další informace o této knihovně můžete nalézt na adrese http://web.wanadoo.be/cyberelf/nanoxml/, kde najdete i dokumentaci.

Příklad parserování XML

Nejdříve si vytvoříme jednoduchý XML soubor s následujícím obsahem a uložíme jej do resource souboru Naší aplikace.

<?xml version=“1.0″?>
<person>
  <attr>Vlastnost c.1</attr>
  <attr>Vlastnost c.2</attr>
  <attr>Vlastnost c.3</attr>
</person>

Získaná data budeme zobrazovat pomocí formuláře. K tomu nám poslouží následující funkce:

private Form getForm(Vector items) {
  Form form = new Form(„“);
  form.addCommand(exitCommand);
  form.setCommandListener(this);
  Enumeration enum = items.elements();
  while(enum.hasMoreElements()) {
    form.append(new StringItem(„“, (String)enum.nextElement()));
  }
  return form;
}

Nyní vytvoříme vlastní metody pro zpracování XML dokumentu. Obě funkce vyžadují parametr InputStreamReader a vrací data ve formě vektoru.

kXML parser

private Vector parsekXML(InputStreamReader reader) {
  Vector items = new Vector();
  boolean inItem = false;
  boolean perform = true;
  try {
    XmlParser parser = new XmlParser(reader);
    while (perform) {
      ParseEvent event = parser.read();
      switch (event.getType()) {
        case Xml.START_TAG:
          if (event.getName().equals(„attr“)) {
            inItem = true;
          }
          break;
      case Xml.END_TAG:
          if (event.getName().equals(„attr“)) {
            inItem = false;
          }
          break;
      case Xml.TEXT:
          if (inItem) {
            items.addElement(event.getText());
          }
          break;
      case Xml.END_DOCUMENT:
          perform = false;
          break;
      }
    }
  } catch (IOException e) {
  }
  return items;
}

NanoXML parser

private Vector parseNanoXML(InputStreamReader reader) {
  Vector items = new Vector();
  XMLElement nanoParser = new XMLElement();
  try {
    nanoParser.parseFromReader(reader);
  } catch (IOException e) {
  } catch (XMLParseException e) {
  }
  Enumeration enum = nanoParser.enumerateChildren();
  while (enum.hasMoreElements()) {
    items.addElement(((XMLElement) enum.nextElement()).getContent());
  }
  return items;
}

Kromě těchto funkcí je zde ještě pomocná metoda, jenž vytváři menu pro výběr použitého parseru. Celá aplikace je řízena v metodě commandListerner. Kompletní zdrojové kódy naleznete v příloze tohoto článku.

Shrnutí

Jak vidíte práce s dokumenty v MIDp aplikacích není příliš složitá. Jsme sice ochuzeni o některé funkce, ale i tak máme možnost pracovat s XML v MIDp aplikacích. Kompletní zdrojové soubory celého příkladu najdete zde. A jaký typ parseru vlastně použít? Záleží na konkrétní situaci, ale modelový parser je vhodnější pro zpracování menších dokumentů, kdežto pro větší dokumenty se hodí Pull parser.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

1 Příspěvěk v diskuzi

  1. Dobrý den,
    prosím Vás o radu s následujícím problémem… mám dvě aplikace, jednu J2SE Swing a druhou J2ME MIDlet, obě ukládají záznamy, bohužel ne stejného formátu (protože midlet to hází do RMS a pc-apliakce do bin. souboru přes serializaci, která v J2ME bohužel nejde udělat – alespoň jsem nepřišel na to jak, když tam není ObjectWriter).

    Teď k problému s XML – z mobilu si přes fileconn vyexportuju xml soubor (tvořený pomocí kXMLElement a addChild, který poté převádím do stringu a ukládám) na paměťovou kartu, pak když se ale snažím načíst stejný soubor zpět tak ani jeden z parserů nefunguje… resp. ne tak jak bych potřeboval. Potřebuji totiž z položek opět získat položky záznamu, kterým apliakce vládne.

    Struktura souboru xml:

    int
    String
    String
    String
    Long

    ….

    Prosím o radu, jak co nejlépe ušít metodu parseru, abych v ní rozpoznal o kterou položku jde, nejlépe už tady vytvořil nový objekt typu záznam a tyto objekty si předal ve Vectoru metodě další.

    Zkouším všechno možné, sedím nad tím už tři dny a nevím si s tím rady..

    Předem děkuji za jakoukoliv radu ;-)

Odpovědět