April 15, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

The Story of a WML Generator

  • September 19, 2005
  • By Radu Braniste
  • Send Email »
  • More Articles »

This article presents a flexible, compile-time safe way of generating WML and WML-like dialects code. Two contrasting solutions are discussed—one relying on C# without generics and the other one on C++. A rarely used C# idiom is presented, increasing the reusability of the code, but C++ and templates related techniques confer the ultimate level of flexibility.

Throughout the article, WML is used as an example of an XML dialect imposing strict rules on the nesting of its elements, but otherwise any hierarchical based language fills the bill. That's why just a subset of WML is presented and the emphasis is mostly put on the flexible design of the hierarchy of elements and the validation of specific rules governing their composition.

A Short History

Although WML (Wireless Markup Language[1])—a XML-based content language developed in 1999 for WAP—probably will be phased out in the future, it still represents a good standardized example of how XML can be used to create a minimalist language, easy to generate and manipulate.

Generating WML code might look like an easy task, but generating valid WML code is something different. And when additional flexibility is required—to quickly move from WML to a related XML dialect governed by slightly different rules, for example—the task becomes even more daunting.

WML was designed for low-bandwidth, small-display devices and such as it concentrated on wireless transaction efficiency: an application (a deck) has screens (cards) that can be downloaded in bulk on the device and processed as needed. A number of predefined elements can be embedded in cards following a set of rules allowing specific combinations only (for example, from WML DTD 1.2:

<!ELEMENT wml ( head?, template?, card+ )>
<!ELEMENT card (onevent*, timer?, (do | p | pre)*)>
<!ELEMENT go (postfield | setvar)*>

Taking care of all these rules and generating valid WML code is the first goal of your endeavor.

The First Step: C#

You can start with a first implementation attempt, written in C# [3]. Just a subset of WML was used and compositional rules are for demonstrational purpose only [4]:

namespace mlgen
{
   class GenericElement
   {
      public
      GenericElement(string element, string init)
      {
         root_ = init;
         element_ = element;
         inserted_ = false;
         used_ = false;
         openElement();
      }
      public GenericElement(string element) : this(element,
                                                   string.Empty)
      {}
      public override string ToString()
      {
         closeElement();
         return root_;
      }
      protected void genericInsert(GenericElement e)
      {
         whenInserted();
         root_ += e;
      }
      protected void genericAddProperty(string key, string value)
      {
         if (!inserted_)
         {
            root_ += " "
            root_ += key;
            root_ += "="";
            root_ += value;
            root_ += """;
         }
      }
      private void openElement()
      {
         root_ += "<";
         root_ += element_;
      }
      private void whenInserted()
      {
         if (!inserted_)
         {
            root_ += ">";
            inserted_ = true;
         }
         root_ += 'n';
      }
      private void closeElement()
      {
         if (used_)
            return;
         used_ = !used_;
         if (inserted_)
         {
            root_ += 'n';
            root_ += "</";
            root_ += element_;
            root_ += ">";
         }
         else
         {
            root_ += "/>";
         }
      }
      private string root_;
      private readonly string element_;
      bool inserted_;
      bool used_;
   };
   class BreakImpl : GenericElement
   {
      public
         BreakImpl() : base("br")
      { }
   };
   class HeadImpl : GenericElement
   {
      public
         HeadImpl() : base("head")
      { }
      public void insert(BreakImpl e)
      {
         genericInsert(e);
      }
   };
   class ParagraphImpl : GenericElement
   {
      public
         ParagraphImpl() : base("p")
      { }
      };
      class CardImpl : GenericElement
      {
         public
            CardImpl() : base("card")
         {}
         void setID(string id)
         {
            genericAddProperty("id", id);
         }
         public void insert(ParagraphImpl e)
         {
            genericInsert(e);
         }
      };
      class DeckImpl : GenericElement
      {
         public
            DeckImpl() : base("wml",
            "<?xml version="1.0"?>n<!DOCTYPEwml PUBLIC };
              -//PHONE.COM//DTD WML 1.1//EN"n
              "http://www.phone.com/dtd/wml11.dtd" >n" )
            { }
         public void insert(CardImpl e)
         {
            genericInsert(e);
         }
         public void insert(HeadImpl e)
         {
            genericInsert(e);
         }
      };
}




Page 1 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel