Getting Started With Visual Studio

From Symgate Developer's Wiki
Jump to: navigation, search

This document explains how to use Microsoft Visual Studio to develop Symgate-enabled applications with CSharp, or VB.NET.

If you have not already done so, you might want to read Getting Started: Basic Concepts first.

Contents

Setting Up Your Project

Setting up your project is easy, and identical for both languages. Simply go to "Project" -> "Add Web Reference" in the Visual Studio IDE, and enter http://www.symgate.com/cml/symgate.wsdl in the URL box. It may save typing to enter 'symgate' as the web reference name, instead of the default 'com.symgate.www' - the examples on this site assume you have done this.

Sge webref.png

Performing an operation

About Requests and Responses

Each operation within the symboliser takes a single request object, and returns a repsonse object.

Information on what type of object is required for, and returned by each operation is an important part of the Reference Documentation.

Account Parameters

Request objects will always require an accountID object (as it's creds member) which contains your account name and key.

Example: Creating your accountID object in C#:

/************************** create accountID **************************/
// create the main accountID object
symgate.accountID creds = new symgate.accountID();
creds.account = "your_username";
creds.key = "your_key";

Example: Creating your accountID object in VB:

' ************************** create accountID **************************
' create the main accountID object
Dim myCreds As New symgate.accountID
myCreds.account = "your_username"
myCreds.key = "your_key"

Request Options

Parse Options

Request objects that process text-based input (plain text, or HTML) will require a symboliserParseOptions object, as their options member - this contains information required to convert the text to symbolised data. At present, this defines the language you want to use (or whether you want to use automatic language detection), as well as some options governing how the text is parsed, and how the CML is generated.

You should specify the language parameter if you want to define the actual language you want the symboliser to use.

Alternatively, you can use language detection if you are unsure of the input language. To do this, you should specify the fallbackLanguage and englishDialect parameters instead of the language parameter. This causes the symboliser to detect the language by analysing the input text, choosing the fallbackLanguage if it is unsure (which is sometimes the case when symbolising a small number of words). The englishDialect parameter is used to specify which version of English to use if the input is determined to be English, as language detection cannot detect between UK, American, and Australian English.

The schema defines a choice of either language, or fallbackLanguage and englishDialect. You should not try and mix them.

The other options available are booleans, which govern how the CML is generated:

  • collapseWhitespace - if this is set to true, any groups of whitespace characers in the input will be collapsed to a single space before processing. If false, then sending sequences of spaces will result in additional cmaps being generated. Default: true
  • generateBlankAlternatives - if this is set to true, every symbol will have an additional alternative created for it that contains just the text, and no symbol. This is useful if you always want to have an option to switch a symbol off. Default: false
  • allowRecursiveAltlists - if this is set to true, then the symboliser will generate output in which altlists can contain other altlists. This can result in smaller output, but is harder to parse. Default: false

Example: Creating your symboliserParseOptions object in C#:

/************************** create parse options **************************/
// create the parse options, that define how the cml will be generated from the input text
symgate.symboliserParseOptions parseOpts = new symgate.symboliserParseOptions();
 
// the language of the input.
// the syntax for this is a bit weird, due to the way .net handles xsd:choice elements.
// see: http://msdn.microsoft.com/msdnmag/issues/03/06/XMLFiles/
parseOpts.ItemsElementName = new symgate.ItemsChoiceType[1];
parseOpts.Items = new symgate.language[1];
parseOpts.ItemsElementName[0] = symgate.ItemsChoiceType.language;
parseOpts.Items[0] = symgate.language.English_UK;
 
// to have the symboliser guess the language, instead you should specify a 'fallbackLanguage' 
// (the language used if detection fails) and 'englishDialect' (the dialect of English to use, 
// if English is detected as the language... the symboliser can't tell)
// for example:
// parseOpts.ItemsElementName = new symgate.ItemsChoiceType[2];
// parseOpts.Items = new symgate.language[2];
// parseOpts.ItemsElementName[0] = symgate.ItemsChoiceType.fallbackLanguage;
// parseOpts.Items[0] = symgate.language.Swedish;
// parseOpts.ItemsElementName[1] = symgate.ItemsChoiceType.englishDialect;
// parseOpts.Items[1] = symgate.language.English_UK 
 
// collapseWhitespace tells the symboliser to generate empty cmaps when multiple consecutive space
// characters are entered in the input, or whether to treat all multi-spaces in the input as a single space
parseOpts.collapseWhitespace = true;
 
// generateBlankAlternatives tells the symboliser to generate a 'blank' alternative for each symbol. That
// is, a cmap with just the text, but no symbol, so that the symbol can be 'selected' as switched off
parseOpts.generateBlankAlternatives = false;
 
// when allowRecursiveAltlists is enabled, output in which altlists can contain other altlists will be
// generated. This is harder to parse, but results in smaller output. (See ref docs for more info)
parseOpts.allowRecursiveAltlists = false;

Example: Creating your symboliserParseOptions object in VB:

' ************************** create parse options **************************
' create the parse options, that define how the cml will be generated from the input text
Dim parseOpts As New symgate.symboliserParseOptions
 
' the language of the input.
' the syntax for this is a bit weird, due to the way .net handles xsd:choice elements.
' see: http://msdn.microsoft.com/msdnmag/issues/03/06/XMLFiles/
parseOpts.ItemsElementName = New symgate.ItemsChoiceType() {symgate.ItemsChoiceType.language}
parseOpts.Items = New symgate.language() {symgate.language.English_UK}
 
' to have the symboliser guess the language, instead you should specify a 'fallbackLanguage' 
' (the language used if detection fails) and 'englishDialect' (the dialect of English to use, 
' if English is detected as the language... the symboliser can't tell)
' for example:
' parseOpts.ItemsElementName = New symgate.ItemsChoiceType() {symgate.ItemsChoiceType.fallbackLanguage, symgate.itemsChoiceType.englishDialect}
' parseOpts.Items= = New symgate.language() { symgate.language.Swedish , symgate.language.English_UK }
 
' collapseWhitespace tells the symboliser to generate empty cmaps when multiple consecutive space
' characters are entered in the input, or whether to treat all multi-spaces in the input as a single space
parseOpts.collapseWhitespace = True
 
' generateBlankAlternatives tells the symboliser to generate a 'blank' alternative for each symbol. That
' is, a cmap with just the text, but no symbol, so that the symbol can be 'selected' as switched off
parseOpts.generateBlankAlternatives = False
 
' when allowRecursiveAltlists is enabled, output in which altlists can contain other altlists will be
' generated. This is harder to parse, but results in smaller output. (See ref docs for more info)
parseOpts.allowRecursiveAltlists = False

Rendering Options

Similarly, request objects that perform rendering operations (such as conceptToSymbol, or cmlToXHTML) require a symboliserRenderOptions object as their options member. This contains information on how the symbols should look, for example what symbol set to use.

In many cases, the defaults will be OK. The options available are:

  • symset: defines which symbol system to use. Currently 'Widrebus' is the only supported option, although support for more is planned
  • color: specifies whether to use coloured, or black-and-white symbols. Specify "Colored" for color symbols, or "Black" for black-and-white symbols with black lines. You can also specify a limited number of alternative line colours, see the documentation for what's avaialable.
  • basesize: Where releveant, this controls the base height of the rendered symbols.
  • languageLevel: an ingeger which allows you to control the way symbols are generated. Setting a number > 0 causes certain types of symbols to be switched off, to allow for different comprehension levels. currently unimplemented!
  • qualifierOptions: allows you to switch off certaion types of symbol qualifiers (such as plural qualifiers) to reduce clutter. This may or may not be appropriate, depending on content.
  • conceptFilter: Allows the filtering of certain types of symbol based on their concept code. This is for advanced users, but the default of '??02010' is recommended, as it filters out the sex education symbols.

Example: Creating your symboliserRenderOptions object in C#:

/************************** create render options **************************/
// create the render options, that define how the symbols will be displayed to the user
symgate.symboliserRenderOptions renderOpts = new symgate.symboliserRenderOptions();
 
// the base size (in pixels) for the symbols
renderOpts.basesize = "100";
 
// the colour to use for the symbols
renderOpts.color = symgate.symsetcol.Colored;
 
// the symbol set to use (currently Widrebus is the only one supported in the web service)
renderOpts.symset = symgate.symset.Widrebus;
 
// the 'language filter'. This allows you to filter out certain symbols, based on their concept information
// currently it is recommended you pass at least '??02010', which filters out the sex-ed symbols
renderOpts.conceptFilter = new String[1];
renderOpts.conceptFilter[0] = "??02010";
 
// the 'language level'. Different language levels will hide certain symbols, targeting the output at readers
// of different levels. (Currently unimplemented: pass "1")
renderOpts.languageLevel = "1";
 
// the qualifier options: allows control over whether certain types of symbol qualifiers are displayed
renderOpts.qualifierOptions = new symgate.symboliserQualifierOptions();
// show all qualifier types
renderOpts.qualifierOptions.showPlurals = true; // plural qualifiers
renderOpts.qualifierOptions.showSuperlatives = true; // er/est qualifiers
renderOpts.qualifierOptions.showTenses = true; // past/future tenses

Example: Creating your symboliserRenderOptions object in VB:

' ************************** create render options **************************
' create the render options, that define how the symbols will be displayed to the user
Dim renderOpts As New symgate.symboliserRenderOptions
 
' the base size (in pixels) for the symbols
renderOpts.basesize = "100"
 
' the colour to use for the symbols
renderOpts.color = symgate.symsetcol.Colored
 
' the symbol set to use (currently Widrebus is the only one supported in the web service)
renderOpts.symset = symgate.symset.Widrebus
 
' the 'language filter'. This allows you to filter out certain symbols, based on their concept information
' currently it is recommended you pass at least '??02010', which filters out the sex-ed symbols#
renderOpts.conceptFilter = New String() {"??02010"}
 
' the 'language level'. Different language levels will hide certain symbols, targeting the output at readers
' of different levels. (Currently unimplemented: pass "1")
renderOpts.languageLevel = "1"
 
' the qualifier options: allows control over whether certain types of symbol qualifiers are displayed
renderOpts.qualifierOptions = New symgate.symboliserQualifierOptions
' show all qualifier types
renderOpts.qualifierOptions.showPlurals = True ' plural qualifiers
renderOpts.qualifierOptions.showSuperlatives = True ' er/est qualifiers
renderOpts.qualifierOptions.showTenses = True ' past/future tenses

Wordlist Options

Many requests take a wordlistInfo object as their wordlists member. These allow you to reference any additional wordlists you may have defined, to add vocabulary. You will probably not be using them immediately, but it is important to remember that any call to a rendering-type operation should have wordlist information that is identical to the parsing-type operation that generated the input for it.

However, for your inital usage of the symboliser, it is best to leave this option empty (null object). See Using Wordlists if you want to get started with these.

Other parameters

Finally, request objects will contain the input for the operation itself, such as the text member in the textToCML operation.

There may also be additional operation-specific input options seperate from the parse/render options. These will be described in the documentation for the specific operation.

Putting it together: Performing a request

Once you have created your request object, getting your response is simple. All you need to do is invoke the relevant symboliser operation and obtain the result.

Operations are invoked through a symbolisationBinding object for most symboliser operations. (A wordlistManagerBinding object is available for wordlist-management operations, also.)

Here is an example of how to symbolise "Hello World!"

textToCML in C#:

/************************** the text to process **************************/
String myText = "This is a test of the emergency broadcast system.";
 
 
/************************** converting the text to CML **************************/
// create the symbolisation engine object
symgate.symbolisationBinding symbolisationEngine = new symgate.symbolisationBinding();
 
// create a request, providing the text, creds, and parse options
symgate.symboliserTextInput textToCmlInput = new symgate.symboliserTextInput();
textToCmlInput.creds = creds;
textToCmlInput.options = parseOpts;
textToCmlInput.text = myText;
textToCmlInput.wordlists = null;
 
// fire off the request
symgate.cml cml_result = symbolisationEngine.textToCML(textToCmlInput);
 
// we now have our CML!

textToCML in VB:

' ************************** the text to process **************************
Dim myText As String
myText = "This is a test of the emergency broadcast system."
 
 
' ************************** converting the text to CML **************************
' create the symbolisation engine object
Dim symbolisationEngine As New symgate.symbolisationBinding
 
' create a request, providing the text, creds, and parse options
Dim textToCmlInput As New symgate.symboliserTextInput
textToCmlInput.creds = myCreds
textToCmlInput.options = parseOpts
textToCmlInput.text = myText
textToCmlInput.wordlists = Nothing
 
' fire off the request
Dim cml_result As New symgate.cml
cml_result = symbolisationEngine.textToCML(textToCmlInput)
 
' we now have our CML!

Parsing CML

The basic structure if CML is described in Getting Started: Basic Concepts.

This section will show you how to iterate over a CML document, and thus learn something about it's structure and how to access and manipulate the objects that it contains.

Iterating over CML

Example Description

This example assumes we are converting from plain text, not HTML (which produces more complex output).

A cml object contaions a body and a header. The header will be blank if we are symbolising from plain text. The body contains a list of elements which will be paragraphs or horizontal lines (again, the latter will not be present with a plain text source.)

Paragraphs, contain a list of sentences, and these contain a list of elements which can be cmaps or altlists (and with an HTML source, also links, linebreaks, images or form controls.)

Cmaps contain the text to be displayed along with a list of concept codes which can be passed back to the symboliser to produce a symbol.

Altlists contain a list of 'alternatives' describing the same part of the document. Each alternative can contain any of the elements that a sentence can, although in practice the symboliser does not generate recursive altlists (calts that contain further altlists) for the sake of simplicity.

This example will take some CML, and iterate over the result, printing text information to the console about all of the object types that it finds.

Example Code

Download an example program that converts some text to CML, and iterates over the result (as shown below) here:

Example: Iterating over a CML document in C#:

/************************** Iterating over the CML **************************/
int iParagraph = 0;
 
// iterate over the body elements:
foreach (object body_element in cml_result.body.Items)
{
    //normally they will be paragraphs, but they may be a horizontal line
    if (body_element.GetType().Name == "hr")
    {
        Console.WriteLine("--Horizontal Rule--");
    }
 
    if (body_element.GetType().Name == "cp")
    {
        //convert the object to the correct (paragraph) type
        symgate.cp paragraph = (symgate.cp)body_element;
 
        Console.WriteLine("--Paragraph {0}, Language: {1}--", iParagraph, paragraph.language);
 
        int iSentence = 0;
 
        //each paragraph contains several sentences:
        foreach (symgate.cs sentence in paragraph.cs)
        {
            Console.WriteLine(" --Sentence {0}--", iSentence);
 
            int iElement = 0;
 
            foreach (object sentence_element in sentence.Items)
            {
                // this is the hard part. sentences usually consist of cmaps and altlists when converting
                // from plain text, but when converting from HTML they may also contain links, linebreaks,
                // images and form controls. For simplicity, we will only handle cmaps and altlists here for now
 
                if (sentence_element.GetType().Name == "cmap")
                {
                    symgate.cmap cmap = (symgate.cmap)sentence_element;
 
                    //it's a cmap, display the concept code count and text
                    Console.WriteLine("  --element {0}, type: cmap with {1} conceptcodes, text: {2}--",
                        iElement,
                        cmap.cc == null ? 0 : cmap.cc.Length,
                        cmap.text);
                }
 
                if (sentence_element.GetType().Name == "altlist")
                {
                    symgate.altlist altlist = (symgate.altlist)sentence_element;
 
                    // it's an altlist, display the alternative count, and then ...
                    Console.WriteLine("  --element {0}, type: altlist with {1} alternatives--",
                        iElement,
                        altlist.calt.Length);
 
                    // ... display the contents of each alternative
 
                    int iAlternative = 0;
 
                    foreach (symgate.calt alternative in altlist.calt)
                    {
                        Console.WriteLine("   --alternative {0}, priority: {1}, preferred: {2}--",
                        iAlternative,
                        alternative.priority,
                        alternative.preferred);
 
                        int iAltElement = 0;
 
                        foreach (object alternative_element in alternative.Items)
                        {
                            // again, this element can be a cmap, altlist, or any of the HTML-related entities
                            // mentioned above. *however*, while it is allowed bt the schema, the symboliser will
                            // not generate recursive altlists (calts that contain altlists) as they are harder
                            // for client applications to parse. thus, we are likely to have a cmap here
 
                            if (alternative_element.GetType().Name == "cmap")
                            {
                                symgate.cmap cmap = (symgate.cmap)alternative_element;
 
                                //it's a cmap, display the concept code count and text
                                Console.WriteLine("    --element {0}, type: cmap with {1} conceptcodes, text: {2}--",
                                    iAltElement,
                                    cmap.cc == null ? 0 : cmap.cc.Length,
                                    cmap.text);
                            }
 
                            iAltElement++;
                        }
 
                        iAlternative++;
                    }
 
                }
 
                iElement++;
            }
 
            iSentence++;
        }
 
        iParagraph++;
    }
}

Example: Iterating over a CML document in VB:

' ************************** Iterating over the CML **************************
Dim iParagraph = 0
 
' iterate over the body elements:
Dim body_element
For Each body_element In cml_result.body.Items
    ' normally they will be paragraphs, but they may be a horizontal line
    If body_element.GetType.Name = "hr" Then
        Console.WriteLine("--Horizontal Rule--")
    End If
 
    If body_element.GetType.Name = "cp" Then
        ' convert the object to the correct (paragraph) type
        Dim paragraph As symgate.cp
        paragraph = body_element
 
        Console.WriteLine("--Paragraph {0}, Language: {1}--", iParagraph, paragraph.language)
 
        Dim iSentence = 0
 
        ' each paragraph contains several sentences
        Dim sentence As symgate.cs
        For Each sentence In paragraph.cs
            Console.WriteLine(" --Sentence {0}--", iSentence)
 
            Dim iElement = 0
 
            Dim sentence_element
            For Each sentence_element In sentence.Items
                ' this is the hard part. sentences usually consist of cmaps and altlists when converting
                ' from plain text, but when converting from HTML they may also contain links, linebreaks,
                ' images and form controls. For simplicity, we will only handle cmaps and altlists here for now
 
                If sentence_element.GetType.Name = "cmap" Then
                    Dim cmap As symgate.cmap
                    cmap = sentence_element
 
                    Dim cc_count As Integer
                    cc_count = 0
 
                    If Not cmap.cc Is Nothing Then
                        cc_count = cmap.cc.Length
                    End If
 
                    ' it's a cmap, display the concept code count and text
                    Console.WriteLine("  --element {0}, type: cmap with {1} conceptcodes, text: {2}--", iElement, cc_count, cmap.text)
                End If
 
                If sentence_element.GetType.Name = "altlist" Then
                    Dim altlist As symgate.altlist
                    altlist = sentence_element
 
                    ' it's an altlist, display the alternative count, and then ...
                    Console.WriteLine("  --element {0}, type: altlist with {1} alternatives--", iElement, altlist.calt.Length)
 
                    ' ... display the contentes of each alternative
 
                    Dim iAlternative = 0
 
                    Dim alternative As symgate.calt
                    For Each alternative In altlist.calt
                        Console.WriteLine("   --alternative {0}, priority: {1}, preferred: {2}--", iAlternative, alternative.priority, alternative.preferred)
 
                        Dim iAltElement = 0
 
                        Dim alternative_element
                        For Each alternative_element In alternative.Items
                            ' again, this element can be a cmap, altlist, or any of the HTML-related entities
                            ' mentioned above. *however*, while it is allowed bt the schema, the symboliser will
                            ' not generate recursive altlists (calts that contain altlists) as they are harder
                            ' for client applications to parse. thus, we are likely to have a cmap here
 
                            If alternative_element.GetType.Name = "cmap" Then
                                Dim cmap As symgate.cmap
                                cmap = alternative_element
 
                                Dim cc_count As Integer
                                cc_count = 0
 
                                If Not cmap.cc Is Nothing Then
                                    cc_count = cmap.cc.Length
                                End If
 
                                ' it's a cmap, display the concept code count and text
                                Console.WriteLine("    --element {0}, type: cmap with {1} conceptcodes, text: {2}--", iAltElement, cc_count, cmap.text)
                            End If
 
                            iAltElement += 1
                        Next
                    Next
                End If
 
                iElement += 1
            Next
 
            iSentence += 1
        Next
    End If
 
    iParagraph += 1
Next

Example Output

Calling the above program, using the "Hello World!" example above to set up the request (which was omitted from the example code here), produces the following output:

--Paragraph 0, Language: English_UK--
 --Sentence 0--
  --element 0, type: cmap with 1 conceptcodes, text: Hello--
  --element 1, type: altlist with 2 alternatives--
   --alternative 0, priority: 0, preferred: False--
    --element 0, type: cmap with 1 conceptcodes, text: World!--
   --alternative 1, priority: 1, preferred: False--
    --element 0, type: cmap with 1 conceptcodes, text: World!--

The CML generated by passing "Hello World!" to the textToCML operation, looks like this:

<cml>
 <body>
  <cp size="0" language="English_UK" >
   <cs>
    <cmap>
     <cc base="hello" tags="Noun+Sg" code="30800030690000000" pos="NOUN" />
     <text>Hello</text>
    </cmap>
    <altlist>
     <calt priority="0" >
      <cmap>
       <cc base="world" tags="Noun+Sg" code="30120600010100000" pos="NOUN" />
       <text>World!</text>
      </cmap>
     </calt>
     <calt priority="1" >
      <cmap>
       <cc base="world" tags="Noun+Sg" code="30120600000000000" pos="NOUN" />
       <text>World!</text>
      </cmap>
     </calt>
    </altlist>
   </cs>
  </cp>
 </body>
</cml>

Rendering CML

Once you have a CML document prepared the way you want it, you will want to display it to the user.

This can currently be done by either using the reference XHTML renderer, using the cmlToXHTML symboliser operation, or by rendering the CML yourself.

Using the reference XHTML renderer

Using the reference XHTML renderer is simple. Simply call the cmlToXHTML operation, providing the standard creds and wordlist options, along with your CML object for rendering, a symboliserRenderOptions object describing how you want your CML to be displayed, and an XHTMLOutputFormat parameter, saying whether you want a full document output (complete with <html>, <head> and <body> sections) or just as a partial document fragment to be inserted into another document.

Example: Using the reference renderer in C#:

/************************** Rendering the CML using the reference renderer **************************/
// create a request object for the operation
symgate.cmlToXHTMLRequest cmlToXHTMLRequest = new symgate.cmlToXHTMLRequest();
 
// supply our creds, render options, and cml
cmlToXHTMLRequest.creds = creds;
cmlToXHTMLRequest.options = renderOpts;
cmlToXHTMLRequest.cml = cml_result;
 
// use a full document (not a document fragment)
cmlToXHTMLRequest.outputformat = symgate.XHTMLOutputFormat.FullDocument;
// skip wordlists
cmlToXHTMLRequest.wordlists = null;
 
// process the operation and write the result to stdout
String xhtml_result = symbolisationEngine.cmlToXHTML(cmlToXHTMLRequest);
Console.Write(xhtml_result);

Example: Using the reference renderer in VB:

' ************************** Rendering the CML using the reference renderer **************************
' create a request object for the operation
Dim cmlToXHTMLRequest As New symgate.cmlToXHTMLRequest
 
' supply our creds, render options, and cml
cmlToXHTMLRequest.creds = myCreds
cmlToXHTMLRequest.options = renderOpts
cmlToXHTMLRequest.cml = cml_result
 
' use a full document (not a document fragment)
cmlToXHTMLRequest.outputformat = symgate.XHTMLOutputFormat.FullDocument
' skip wordlists
cmlToXHTMLRequest.wordlists = Nothing
 
' process the operation and write the result to stdout
Dim xhtml_result As String
xhtml_result = symbolisationEngine.cmlToXHTML(cmlToXHTMLRequest)
Console.Write(xhtml_result)

The output of this example code, when given the above "Hello World!" example, looks like this.

Rendering CML Yourself

As you have already seen above, and in the "Getting Started: Basic Concepts" section, your CML document is essentially made up of a series of cmap objects, inside various other containers. It is the cmap objects that we wish to render, as they contain the information on the text and graphics that we will want to display.

Choosing which cmaps to display

As you are aware, there can be many symbol alternatives in a document, represented by an altlist. If you are rendering a document to the user for reading (as opposed to an author, for selecting the appropriate alternatives), you will want to iterate over the document as shown above, and choose the alternative that has it's "preferred" attribute set. If no preferred attribute is set for the altlist, you should use the alternative with the lowest 'priority' value.

Getting hold of the graphics to display

For each cmap, you will want to display any symbols it represents, with the contents of it's "text" member displayed underneath.

Getting the information on what symbols to display requires an additional step. Cmaps contain conceptcode elements, which must be passed to the conceptToSymbol operation, which tells you which actual graphic files must be displayed.

Once you have called conceptToSymbol with all the conceptcodes you are interested in rendering, you end up with a collection of CML symbol objects, which tell you which graphics to display for the given symbol.

Displaying your symbol in a web page

We recommend using an HTML table element in order to display the graphics that make up a symbol in the correct places. (The correct places are described in "How To Render Symbols")

We realise that this can cause consternation for developers who have spent the last few years learning why tables are bad, and CSS is good. If this bothers you, you might want to read Why Using Tables for Rendering Symbols is a Good Idea (even on a CSS-powered site.)

Note, this is not the only way symbols can be rendered on a web page, but from experience we find it the simplest.

Symbols can be treated as a table with up to 5 columns, starting with the topLeft and bottomLeft qualifiers in the first column, the full-left in the second, the main and top symbols in the third column, the full-right in the fourth, and the top-right and bottom-right in the fifth.

The following example C# code shows how this might be achieved in some detail:

// start writing the symbol table
Console.WriteLine("<table class='cml_symtable'>");
 
// find out how many rows we need in the table. Normally one, unless
// there are 'short' qualifiers
int nRows = 1;
if (symbol.topleft != null ||
    symbol.bottomleft != null ||
    symbol.topright != null ||
    symbol.bottomright != null)
{
    nRows = 2;
}
 
for (int iRow = 0; iRow < nRows; ++iRow)
{
    Console.WriteLine("<tr class='cml_symtable_row'>");
 
    // write the small-left qualifier column
    if (symbol.topleft != null ||
        symbol.bottomleft != null)
    {
        String qual = iRow == 0 ? symbol.topleft : symbol.bottomleft;
        if (!(qual != null))
        {
            qual = blankQual;
        }
 
        Console.WriteLine("<td class='cml_symtable_cell'>");
        Console.WriteLine("<img class='cml_symbol_image' src='" + qual + "' alt='' />");
        Console.WriteLine("</td>");
    }
 
    // write the full-left qualifier column
    if (symbol.fullleft != null && iRow == 0)
    {
        // if there are 2 rows, make this column cover both
        if (nRows == 2)
            Console.WriteLine("<td class='cml_symtable_cell' rowspan='2'>");
        else
            Console.WriteLine("<td class='cml_symtable_cell'>");
 
        Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.fullleft + "' alt='' />");
 
        Console.WriteLine("</td>");
    }
 
    // write the center column..
    if (iRow == 0)
    {
        String altText = cmap.text;
        altText.Replace("\'", "\\\'"); // escape quotes in the alt text
 
        // if there are 2 rows, make this column cover both
        if (nRows == 2)
            Console.WriteLine("<td class='cml_symtable_cell' rowspan='2'>");
        else
            Console.WriteLine("<td class='cml_symtable_cell'>");
 
        if (symbol.top != null)
        {
            // write a table to justify the top, and main qualifiers
            Console.WriteLine("<table class='cml_inner_symtable'>");
            Console.WriteLine("<tr class='cml_inner_symtable_row'>");
            Console.WriteLine("<td class='cml_inner_symtable_cell'>");
 
            // write the top qualifier
            Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.top + "' alt='' />");
 
            Console.WriteLine("</td>");
            Console.WriteLine("</tr>");
            Console.WriteLine("<tr class='cml_inner_symtable_row'>");
            Console.WriteLine("<td class='cml_inner_symtable_cell'>");
 
            // write the main symbol
            Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.main + "' alt='' />");
 
            Console.WriteLine("</td>");
            Console.WriteLine("</tr>");
            Console.WriteLine("</table>");
        }
        else
        {
            // there is no top qualifer, just write the main symbol
            Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.main + "' alt='' />");
        }
 
        Console.WriteLine("</td>");
    }
 
    // write the full-right qualifier column
    if (symbol.fullright != null && iRow == 0)
    {
        // if there are 2 rows, make this column cover both
        if (nRows == 2)
            Console.WriteLine("<td class='cml_symtable_cell' rowspan='2'>");
        else
            Console.WriteLine("<td class='cml_symtable_cell'>");
 
        Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.fullright + "' alt='' />");
 
        Console.WriteLine("</td>");
    }
 
    // write the small-right qualifier column
    if (symbol.topright != null ||
        symbol.bottomright != null)
    {
        String qual = iRow == 0 ? symbol.topright : symbol.bottomright;
        if (!(qual != null))
        {
            qual = blankQual;
        }
 
        Console.WriteLine("<td class='cml_symtable_cell'>");
        Console.WriteLine("<img class='cml_symbol_image' src='" + qual + "' alt='' />");
        Console.WriteLine("</td>");
    }
}
 
Console.WriteLine("</table>");

Note that the above example uses spacer GIFs to vertically-justify the top and bottom qualifiers. You should also note that it does not attempt to resize the images if there is a top qualifier present. If a top qualifier is present, and you are using fullURI pathnames as the output from conceptToSymbol, you will automatically get a link to a main symbol whose height is 80% of the base, and a top symbol that takes up the other 20%.

You will also want to display the text along with each symbol. Traditionally, the text is rendered underneath the symbol, and centered beneath it. The simplest way to do this might be to use an additional row in the symbol table.

If you want your symbols to wrap, like a conventional text document, the best way that we can find to achieve this is to surround each symbol table with a <div>, with the css attribute "float: left" set. Ideally it might be better to use the "display: inline-block" attribute, but browser support for this is patchy.

Displaying symbols in other applications

There is nothing to stop you from using symbols in a dialog-based application, instead of an HTML one. You will want to use whatever painting tools your framework provides, to render symbols in the correct locations as described in "How To Render Symbols".

How best to achieve this is left as an exercise for the reader.

Putting it all together

Hopefully this will given you an overview of how to do most important CML-related tasks using the symbolisation engine, within the context of your own Visual Studio application.

Example Code

Complete examples of a console application that takes a string, converts it to CML, and then manually renders the relevant cmaps as an HTML page are listed below for both C# and VB.NET.

Note, that this is a very simple implementation of an HTML renderer, which has several drawbacks. These are discussed further in Improving Our Manual Renderer.

You can download the example code here:

Note that this example is in the form of a console application, that prints the rendered HTML to stdout. The Example Output is listed below

Example: Manually rendering CML in csharp (simple)

using System;
using System.Collections.Generic;
using System.Text;
 
namespace SymgateClient
{
    class Program
    {
        static void Main(string[] args)
        {
            /************************** create accountID **************************/
            // create the main accountID object
            symgate.accountID creds = new symgate.accountID();
            creds.account = "your_account";
            creds.key = "your_key";
 
 
            /************************** create parse options **************************/
            // create the parse options, that define how the cml will be generated from the input text
            symgate.symboliserParseOptions parseOpts = new symgate.symboliserParseOptions();
 
            // the language of the input.
            // the syntax for this is a bit weird, due to the way .net handles xsd:choice elements.
            // see: http://msdn.microsoft.com/msdnmag/issues/03/06/XMLFiles/
            parseOpts.ItemsElementName = new symgate.ItemsChoiceType[1];
            parseOpts.Items = new symgate.language[1];
            parseOpts.ItemsElementName[0] = symgate.ItemsChoiceType.language;
            parseOpts.Items[0] = symgate.language.English_UK;
 
            // to have the symboliser guess the language, instead you should specify a 'fallbackLanguage' 
            // (the language used if detection fails) and 'englishDialect' (the dialect of English to use, 
            // if English is detected as the language... the symboliser can't tell)
            // for example:
            // parseOpts.ItemsElementName = new symgate.ItemsChoiceType[2];
            // parseOpts.Items = new symgate.language[2];
            // parseOpts.ItemsElementName[0] = symgate.ItemsChoiceType.fallbackLanguage;
            // parseOpts.Items[0] = symgate.language.Swedish;
            // parseOpts.ItemsElementName[1] = symgate.ItemsChoiceType.englishDialect;
            // parseOpts.Items[1] = symgate.language.English_UK 
 
            // collapseWhitespace tells the symboliser to generate empty cmaps when multiple consecutive space
            // characters are entered in the input, or whether to treat all multi-spaces in the input as a single space
            parseOpts.collapseWhitespace = true;
 
            // generateBlankAlternatives tells the symboliser to generate a 'blank' alternative for each symbol. That
            // is, a cmap with just the text, but no symbol, so that the symbol can be 'selected' as switched off
            parseOpts.generateBlankAlternatives = false;
 
            // when allowRecursiveAltlists is enabled, output in which altlists can contain other altlists will be
            // generated. This is harder to parse, but results in smaller output. (See ref docs for more info)
            parseOpts.allowRecursiveAltlists = false;
 
 
            /************************** create render options **************************/
            // create the render options, that define how the symbols will be displayed to the user
            symgate.symboliserRenderOptions renderOpts = new symgate.symboliserRenderOptions();
 
            // the base size (in pixels) for the symbols
            renderOpts.basesize = "100";
 
            // the colour to use for the symbols
            renderOpts.color = symgate.symsetcol.Colored;
 
            // the symbol set to use (currently Widrebus is the only one supported in the web service)
            renderOpts.symset = symgate.symset.Widrebus;
 
            // the 'language filter'. This allows you to filter out certain symbols, based on their concept information
            // currently it is recommended you pass at least '??02010', which filters out the sex-ed symbols
            renderOpts.conceptFilter = new String[1];
            renderOpts.conceptFilter[0] = "??02010";
 
            // the 'language level'. Different language levels will hide certain symbols, targeting the output at readers
            // of different levels. (Currently unimplemented: pass "1")
            renderOpts.languageLevel = "1";
 
            // the qualifier options: allows control over whether certain types of symbol qualifiers are displayed
            renderOpts.qualifierOptions = new symgate.symboliserQualifierOptions();
            // show all qualifier types
            renderOpts.qualifierOptions.showPlurals = true; // plural qualifiers
            renderOpts.qualifierOptions.showSuperlatives = true; // er/est qualifiers
            renderOpts.qualifierOptions.showTenses = true; // past/future tenses
 
 
            /************************** the text to process **************************/
            String myText = "Hello World!";
 
 
            /************************** converting the text to CML **************************/
            // create the symbolisation engine object
            symgate.symbolisationBinding symbolisationEngine = new symgate.symbolisationBinding();
 
            // create a request, providing the text, creds, and parse options
            symgate.symboliserTextInput textToCmlInput = new symgate.symboliserTextInput();
            textToCmlInput.creds = creds;
            textToCmlInput.options = parseOpts;
            textToCmlInput.text = myText;
            textToCmlInput.wordlists = null;
 
            // fire off the request
            symgate.cml cml_result = symbolisationEngine.textToCML(textToCmlInput);
 
            // we now have our CML!
 
 
            /************************** Write our page header **************************/
            Console.WriteLine("<html>");
            Console.WriteLine("<head>");
            Console.WriteLine("<title>Symbolisation Example</title>");
            Console.WriteLine("<link rel='stylesheet' href='http://www.symgate.com/cml/cml.css'>");
            Console.WriteLine("</head>");
            Console.WriteLine("<body>");
 
 
            /************************** Write out the HTML body **************************/
            // iterate over the body elements. We'll call the WriteCMap helper function for
            // all the relevant cmap objects.
            foreach (object body_element in cml_result.body.Items)
            {
                //normally they will be paragraphs. We can ignore anything else.
                if (body_element.GetType().Name == "cp")
                {
                    //create a new DIV for the paragraph:
                    Console.WriteLine("<div class='cml_paragraph'>");
                    //hack to ensure the float attribute gets properly cleared on all browsers (see cml.css)
                    Console.WriteLine("<div class='cml_paragraph_start'></div>");
 
                    //convert the object to the correct (paragraph) type
                    symgate.cp paragraph = (symgate.cp)body_element;
 
                    //each paragraph contains several sentences. They don't need to be rendered any differently.
                    foreach (symgate.cs sentence in paragraph.cs)
                    {
                        //process each sentence element:
                        foreach (object sentence_element in sentence.Items)
                        {
                            // if the element is a cmap, call the WriteCMap helper function (see below)
                            if (sentence_element.GetType().Name == "cmap")
                            {
                                symgate.cmap cmap = (symgate.cmap)sentence_element;
 
                                WriteCMap(creds, renderOpts, cmap, symbolisationEngine);
                            }
 
                            // otherwise, for an altlist, find the correct alternative to render:
                            if (sentence_element.GetType().Name == "altlist")
                            {
                                symgate.altlist altlist = (symgate.altlist)sentence_element;
                                symgate.calt alternativeToRender = null;
                                int renderedPriority = 65536;
 
                                foreach (symgate.calt alternative in altlist.calt)
                                {
                                    //if the alternative has the preferred value set, choose it
                                    if (alternative.preferred == true)
                                    {
                                        alternativeToRender = alternative;
                                        renderedPriority = -1;
                                    }
 
                                    //otherwise, if the alternative's priority value is lower than any we've
                                    //seen so far, choose it
                                    if (Convert.ToInt32(alternative.priority) < renderedPriority)
                                    {
                                        alternativeToRender = alternative;
                                        renderedPriority = Convert.ToInt32(alternative.priority);
                                    }
                                }
 
                                // now that we've found the alternative to render, render all the items it contains
                                foreach (object alternative_element in alternativeToRender.Items)
                                {
                                    // we're only interested in cmaps here
                                    if (alternative_element.GetType().Name == "cmap")
                                    {
                                        symgate.cmap cmap = (symgate.cmap)alternative_element;
 
                                        WriteCMap(creds, renderOpts, cmap, symbolisationEngine);
                                    }
                                }
                            }
                        }
                    }
 
                    //write our paragraph footer:
                    Console.WriteLine("<div class='cml_paragraph_end'></div>");
                    Console.WriteLine("</div>");
                }
            }
 
 
            /************************** Write our page header **************************/
            Console.WriteLine("</body>");
            Console.WriteLine("</html>");
        }
 
        private static void WriteCMap(SymgateClient.symgate.accountID creds,
            SymgateClient.symgate.symboliserRenderOptions renderOpts,
            SymgateClient.symgate.cmap cmap,
            SymgateClient.symgate.symbolisationBinding symbolisationEngine)
        {
            /************************** Write an HTML header for the cmap **************************/
 
            // create a div for the whole cmap
            Console.WriteLine("<div class='cml_cmap'>");
 
            //generate a div for each symbol
            Console.WriteLine("<div class='cml_symbol'>");
            //another css float hack
            Console.WriteLine("<div class='cml_symbol_start'></div>");
 
            bool rendered = false;
 
            if (cmap.cc != null)
            {
                /************************** Get the symbol(s) from the cmap **************************/
                //NOTE: This is not very efficient. We are calling conceptToSymbol *once per cmap*. This
                //is because the example is more readable that way. In a production environment, you may
                //want to create a list of all your concepts, and then call conceptToSymbol once.
 
                //Note also that this is not the only way that you can write HTML containing symbols, but
                //it's a simple method that works for us, and matches fairly closely what the reference
                //renderer does.
 
                //create the request
                symgate.conceptToSymbolRequest conceptToSymbolRequest = new symgate.conceptToSymbolRequest();
 
                //set up our creds, render options, and concepts
                conceptToSymbolRequest.creds = creds;
                conceptToSymbolRequest.options = renderOpts;
                conceptToSymbolRequest.concept = cmap.cc; // note this is an array of concepts
                conceptToSymbolRequest.wordlists = null;
 
                //we want to use full URI paths to the symbol files
                conceptToSymbolRequest.pathFormat = symgate.imagePathFormat.FullURI;
 
                symgate.symbol[][] symbols_for_concepts = symbolisationEngine.conceptToSymbol(conceptToSymbolRequest);
                // note the output is an array of symbol arrays... One symol array refers to each concept
                // in the input array, as each concept can generate one or more (or zero) symbols
 
                /************************** Write the CMap as HTML **************************/
 
                //we want a blank placeholder image, for short-qualifers (topleft, bottomleft, etc) that are missing
                String blankQual;
                blankQual = "http://widrebus.symgate.com/" +
                    creds.account +
                    "/col/" +
                    Convert.ToInt32(renderOpts.basesize) / 2 +
                    "/blank.sym";
                //.sym files are automatically returned as png for firefox and ie7, and gif for ie6
 
                foreach (symgate.symbol[] symbols in symbols_for_concepts)
                {
                    foreach (symgate.symbol symbol in symbols)
                    {
                        // start writing the symbol table
                        Console.WriteLine("<table class='cml_symtable'>");
 
                        // find out how many rows we need in the table. Normally one, unless
                        // there are 'short' qualifiers
                        int nRows = 1;
                        if (symbol.topleft != null ||
                            symbol.bottomleft != null ||
                            symbol.topright != null ||
                            symbol.bottomright != null)
                        {
                            nRows = 2;
                        }
 
                        for (int iRow = 0; iRow < nRows; ++iRow)
                        {
                            Console.WriteLine("<tr class='cml_symtable_row'>");
 
                            // write the small-left qualifier column
                            if (symbol.topleft != null ||
                                symbol.bottomleft != null)
                            {
                                String qual = iRow == 0 ? symbol.topleft : symbol.bottomleft;
                                if (!(qual != null))
                                {
                                    qual = blankQual;
                                }
 
                                Console.WriteLine("<td class='cml_symtable_cell'>");
                                Console.WriteLine("<img class='cml_symbol_image' src='" + qual + "' alt='' />");
                                Console.WriteLine("</td>");
                            }
 
                            // write the full-left qualifier column
                            if (symbol.fullleft != null && iRow == 0)
                            {
                                // if there are 2 rows, make this column cover both
                                if (nRows == 2)
                                    Console.WriteLine("<td class='cml_symtable_cell' rowspan='2'>");
                                else
                                    Console.WriteLine("<td class='cml_symtable_cell'>");
 
                                Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.fullleft + "' alt='' />");
 
                                Console.WriteLine("</td>");
                            }
 
                            // write the center column..
                            if (iRow == 0)
                            {
                                String altText = cmap.text;
                                altText.Replace("\'", "\\\'"); // escape quotes in the alt text
 
                                // if there are 2 rows, make this column cover both
                                if (nRows == 2)
                                    Console.WriteLine("<td class='cml_symtable_cell' rowspan='2'>");
                                else
                                    Console.WriteLine("<td class='cml_symtable_cell'>");
 
                                if (symbol.top != null)
                                {
                                    // write a table to justify the top, and main qualifiers
                                    Console.WriteLine("<table class='cml_inner_symtable'>");
                                    Console.WriteLine("<tr class='cml_inner_symtable_row'>");
                                    Console.WriteLine("<td class='cml_inner_symtable_cell'>");
 
                                    // write the top qualifier
                                    Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.top + "' alt='' />");
 
                                    Console.WriteLine("</td>");
                                    Console.WriteLine("</tr>");
                                    Console.WriteLine("<tr class='cml_inner_symtable_row'>");
                                    Console.WriteLine("<td class='cml_inner_symtable_cell'>");
 
                                    // write the main symbol
                                    Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.main + "' alt='' />");
 
                                    Console.WriteLine("</td>");
                                    Console.WriteLine("</tr>");
                                    Console.WriteLine("</table>");
                                }
                                else
                                {
                                    // there is no top qualifer, just write the main symbol
                                    Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.main + "' alt='' />");
                                }
 
                                Console.WriteLine("</td>");
                            }
 
                            // write the full-right qualifier column
                            if (symbol.fullright != null && iRow == 0)
                            {
                                // if there are 2 rows, make this column cover both
                                if (nRows == 2)
                                    Console.WriteLine("<td class='cml_symtable_cell' rowspan='2'>");
                                else
                                    Console.WriteLine("<td class='cml_symtable_cell'>");
 
                                Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.fullright + "' alt='' />");
 
                                Console.WriteLine("</td>");
                            }
 
                            // write the small-right qualifier column
                            if (symbol.topright != null ||
                                symbol.bottomright != null)
                            {
                                String qual = iRow == 0 ? symbol.topright : symbol.bottomright;
                                if (!(qual != null))
                                {
                                    qual = blankQual;
                                }
 
                                Console.WriteLine("<td class='cml_symtable_cell'>");
                                Console.WriteLine("<img class='cml_symbol_image' src='" + qual + "' alt='' />");
                                Console.WriteLine("</td>");
                            }
                        }
 
                        Console.WriteLine("</table>");
 
                        // we have rendered a symbol
                        rendered = true;
                    }
                }
            }
 
            if (!rendered)
            {
                // if we haven't rendered any symbols, we should use a blank placeholder instead, to ensure the
                // text is positioned correctly
                String blankUri;
                blankUri = "http://widrebus.symgate.com/" +
                    creds.account +
                    "/col/" +
                    renderOpts.basesize +
                    "/blank.sym";
                //.sym files are automatically returned as png for firefox and ie7, and gif for ie6
 
                Console.WriteLine("<div class='cml_symbol_single'>");
                Console.WriteLine("<img class='cml_symbol_image' src='" + blankUri + "' alt='' />");
                Console.WriteLine("</div>");
            }
 
            /************************** Write the text for the cmap, and close the tags **************************/
 
            Console.WriteLine("<div class='cml_symbol_end'></div>");
            Console.WriteLine("</div>");
 
            Console.WriteLine("<div class='cml_cmap_text'>");
 
            if (cmap.emphasis)
                Console.WriteLine("<i>");
            if (cmap.strong)
                Console.WriteLine("<b>");
 
            Console.WriteLine(cmap.text);
 
            if (cmap.strong)
                Console.WriteLine("</b>");
            if (cmap.emphasis)
                Console.WriteLine("</i>");
 
            Console.WriteLine("</div>");
 
            Console.WriteLine("</div>");
        }
    }
}
Module Module1
 
    Sub Main()
        ' ************************** create accountID **************************
        ' create the main accountID object
        Dim myCreds As New symgate.accountID
        myCreds.account = "your_account"
        myCreds.key = "your_key"
 
 
        ' ************************** create parse options **************************
        ' create the parse options, that define how the cml will be generated from the input text
        Dim parseOpts As New symgate.symboliserParseOptions
 
        ' the language of the input.
        ' the syntax for this is a bit weird, due to the way .net handles xsd:choice elements.
        ' see: http://msdn.microsoft.com/msdnmag/issues/03/06/XMLFiles/
        parseOpts.ItemsElementName = New symgate.ItemsChoiceType() {symgate.ItemsChoiceType.language}
        parseOpts.Items = New symgate.language() {symgate.language.English_UK}
 
        ' to have the symboliser guess the language, instead you should specify a 'fallbackLanguage' 
        ' (the language used if detection fails) and 'englishDialect' (the dialect of English to use, 
        ' if English is detected as the language... the symboliser can't tell)
        ' for example:
        ' parseOpts.ItemsElementName = New symgate.ItemsChoiceType() {symgate.ItemsChoiceType.fallbackLanguage, symgate.itemsChoiceType.englishDialect}
        ' parseOpts.Items= = New symgate.language() { symgate.language.Swedish , symgate.language.English_UK }
 
        ' collapseWhitespace tells the symboliser to generate empty cmaps when multiple consecutive space
        ' characters are entered in the input, or whether to treat all multi-spaces in the input as a single space
        parseOpts.collapseWhitespace = True
 
        ' generateBlankAlternatives tells the symboliser to generate a 'blank' alternative for each symbol. That
        ' is, a cmap with just the text, but no symbol, so that the symbol can be 'selected' as switched off
        parseOpts.generateBlankAlternatives = False
 
        ' when allowRecursiveAltlists is enabled, output in which altlists can contain other altlists will be
        ' generated. This is harder to parse, but results in smaller output. (See ref docs for more info)
        parseOpts.allowRecursiveAltlists = False
 
 
        ' ************************** create render options **************************
        ' create the render options, that define how the symbols will be displayed to the user
        Dim renderOpts As New symgate.symboliserRenderOptions
 
        ' the base size (in pixels) for the symbols
        renderOpts.basesize = "100"
 
        ' the colour to use for the symbols
        renderOpts.color = symgate.symsetcol.Colored
 
        ' the symbol set to use (currently Widrebus is the only one supported in the web service)
        renderOpts.symset = symgate.symset.Widrebus
 
        ' the 'language filter'. This allows you to filter out certain symbols, based on their concept information
        ' currently it is recommended you pass at least '??02010', which filters out the sex-ed symbols#
        renderOpts.conceptFilter = New String() {"??02010"}
 
        ' the 'language level'. Different language levels will hide certain symbols, targeting the output at readers
        ' of different levels. (Currently unimplemented: pass "1")
        renderOpts.languageLevel = "1"
 
        ' the qualifier options: allows control over whether certain types of symbol qualifiers are displayed
        renderOpts.qualifierOptions = New symgate.symboliserQualifierOptions
        ' show all qualifier types
        renderOpts.qualifierOptions.showPlurals = True ' plural qualifiers
        renderOpts.qualifierOptions.showSuperlatives = True ' er/est qualifiers
        renderOpts.qualifierOptions.showTenses = True ' past/future tenses
 
 
        ' ************************** the text to process **************************
        Dim myText As String
        myText = "Hello World!"
 
 
        ' ************************** converting the text to CML **************************
        ' create the symbolisation engine object
        Dim symbolisationEngine As New symgate.symbolisationBinding
 
        ' create a request, providing the text, creds, and parse options
        Dim textToCmlInput As New symgate.symboliserTextInput
        textToCmlInput.creds = myCreds
        textToCmlInput.options = parseOpts
        textToCmlInput.text = myText
        textToCmlInput.wordlists = Nothing
 
        ' fire off the request
        Dim cml_result As New symgate.cml
        cml_result = symbolisationEngine.textToCML(textToCmlInput)
 
        ' we now have our CML!
 
 
        ' ************************** Write our page header **************************
        Console.WriteLine("<html>")
        Console.WriteLine("<head>")
        Console.WriteLine("<title>Symbolisation Example</title>")
        Console.WriteLine("<link rel='stylesheet' href='http://www.symgate.com/cml/cml.css'>")
        Console.WriteLine("</head>")
        Console.WriteLine("<body>")
 
 
        ' ************************** Write out the HTML body **************************
        ' iterate over the body elements. We'll call the WriteCMap helper function for
        ' all the relevant cmap objects.
        Dim body_element
        For Each body_element In cml_result.body.Items
            ' normally they will be paragraphs. We can ignore anything else.
            If body_element.GetType.Name = "cp" Then
                ' create a new DIV for the paragraph:
                Console.WriteLine("<div class='cml_paragraph'>")
                ' hack to ensure the float attribute gets properly cleared on all browsers (see cml.css)
                Console.WriteLine("<div class='cml_paragraph_start'></div>")
 
                ' convert the object to the correct (paragraph) type
                Dim paragraph As symgate.cp
                paragraph = body_element
 
                ' each paragraph contains several sentences. They don't need to be rendered any differently.
                Dim sentence As symgate.cs
                For Each sentence In paragraph.cs
                    ' process each sentence element:
                    Dim sentence_element
                    For Each sentence_element In sentence.Items
                        ' if the element is a cmap, call the WriteCMap helper function (see below)
                        If sentence_element.GetType.Name = "cmap" Then
                            Dim cmap As symgate.cmap
                            cmap = sentence_element
 
                            WriteCMap(myCreds, renderOpts, cmap, symbolisationEngine)
                        End If
 
                        ' otherwise, for an altlist, find the correct alternative to render:
                        If sentence_element.GetType.Name = "altlist" Then
                            Dim altlist As symgate.altlist
                            altlist = sentence_element
 
                            Dim alternativeToRender As symgate.calt = Nothing
                            Dim renderedPriority = 65536
 
                            Dim alternative As symgate.calt
                            For Each alternative In altlist.calt
                                ' if the alternative has the preferred value set, choose it
                                If alternative.preferred = True Then
                                    alternativeToRender = alternative
                                    renderedPriority = -1
                                End If
 
                                ' otherwise, if the alternative's priority value is lower than any we've
                                ' seen so far, choose it
                                If Convert.ToInt32(alternative.priority) < renderedPriority Then
                                    alternativeToRender = alternative
                                    renderedPriority = Convert.ToInt32(alternative.priority)
                                End If
                            Next
 
                            If Not alternativeToRender Is Nothing Then
                                ' now that we've found the alternative to render, render all the items it contains
                                Dim alternative_element
                                For Each alternative_element In alternativeToRender.Items
                                    ' we're only interested in cmaps here
                                    If alternative_element.GetType().Name = "cmap" Then
                                        Dim cmap As symgate.cmap
                                        cmap = alternative_element
 
                                        WriteCMap(myCreds, renderOpts, cmap, symbolisationEngine)
                                    End If
                                Next
                            End If
                        End If
                    Next
                Next
 
                ' write our paragraph footer:
                Console.WriteLine("<div class='cml_paragraph_end'></div>")
                Console.WriteLine("</div>")
            End If
        Next
 
 
        ' ************************** Write our page header **************************
        Console.WriteLine("</body>")
        Console.WriteLine("</html>")
    End Sub
 
    Sub WriteCMap(ByVal creds As symgate.accountID, ByVal renderOpts As symgate.symboliserRenderOptions, ByVal cmap As symgate.cmap, ByVal symbolisationEngine As symgate.symbolisationBinding)
        ' ************************** Write an HTML header for the cmap **************************
 
        ' create a div for the whole cmap
        Console.WriteLine("<div class='cml_cmap'>")
 
        ' generate a div for each symbol
        Console.WriteLine("<div class='cml_symbol'>")
        ' another css float hack
        Console.WriteLine("<div class='cml_symbol_start'></div>")
 
        Dim rendered As Boolean = False
 
        If Not cmap.cc Is Nothing Then
            ' ************************** Get the symbol(s) from the cmap **************************
            ' NOTE: This is not very efficient. We are calling conceptToSymbol *once per cmap*. This
            ' is because the example is more readable that way. In a production environment, you may
            ' want to create a list of all your concepts, and then call conceptToSymbol once.
 
            ' Note also that this is not the only way that you can write HTML containing symbols, but
            ' it's a simple method that works for us, and matches fairly closely what the reference
            ' renderer does.
 
            ' create the request
            Dim conceptToSymbolRequest As New symgate.conceptToSymbolRequest
 
            ' set up our creds, render options, and concepts
            conceptToSymbolRequest.creds = creds
            conceptToSymbolRequest.options = renderOpts
            conceptToSymbolRequest.concept = cmap.cc ' note this is an array of concepts
            conceptToSymbolRequest.wordlists = Nothing
 
            ' we want to use full URI paths to the symbol files
            conceptToSymbolRequest.pathFormat = symgate.imagePathFormat.FullURI
 
            Dim symbols_for_concepts As symgate.symbol()()
            symbols_for_concepts = symbolisationEngine.conceptToSymbol(conceptToSymbolRequest)
            ' note the output is an array of symbol arrays... One symol array refers to each concept
            ' in the input array, as each concept can generate one or more (or zero) symbols
 
 
            ' ************************** Write the CMap as HTML **************************
 
            ' we want a blank placeholder image, for short-qualifers (topleft, bottomleft, etc) that are missing
            Dim blankQual As String
            blankQual = "http://widrebus.symgate.com/" + creds.account + "/col/" + Convert.ToString(Convert.ToInt32(renderOpts.basesize / 2)) + "/blank.sym"
            ' .sym files are automatically returned as png for firefox and ie7, and gif for ie6
 
            Dim symbols As symgate.symbol()
            For Each symbols In symbols_for_concepts
                Dim symbol As symgate.symbol
                For Each symbol In symbols
                    ' start writing the symbol table
                    Console.WriteLine("<table class='cml_symtable'>")
 
                    ' find out how many rows we need in the table. Normally one, unless
                    ' there are 'short' qualifiers
                    Dim nRows = 1
                    If Not symbol.topleft Is Nothing Or Not symbol.bottomleft Is Nothing Or Not symbol.topright Is Nothing Or Not symbol.bottomright Is Nothing Then
                        nRows = 2
                    End If
 
                    Dim iRow = 0
                    For iRow = 0 To nRows - 1
                        Console.WriteLine("<tr class='cml_symtable_row'>")
 
                        ' write the small-left qualifier column
                        If Not symbol.topleft Is Nothing Or Not symbol.bottomleft Is Nothing Then
                            Dim qual As String
                            If iRow = 0 Then
                                qual = symbol.topleft
                            Else
                                qual = symbol.bottomleft
                            End If
 
                            If qual Is Nothing Then
                                qual = blankQual
                            End If
 
                            Console.WriteLine("<td class='cml_symtable_cell'>")
                            Console.WriteLine("<img class='cml_symbol_image' src='" + qual + "' alt='' />")
                            Console.WriteLine("</td>")
                        End If
 
                        ' write the full-left qualifier column
                        If Not symbol.fullleft Is Nothing And iRow = 0 Then
                            ' if there are 2 rows, make this column cover both
                            If nRows = 2 Then
                                Console.WriteLine("<td class='cml_symtable_cell' rowspan='2'>")
                            Else
                                Console.WriteLine("<td class='cml_symtable_cell'>")
                            End If
 
                            Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.fullleft + "' alt='' />")
 
                            Console.WriteLine("</td>")
                        End If
 
                        ' write the center column..
                        If iRow = 0 Then
                            Dim altText As String = cmap.text
                            altText.Replace("\'", "\\\'") ' escape quotes in the alt text
 
                            ' if there are 2 rows, make this column cover both
                            If nRows = 2 Then
                                Console.WriteLine("<td class='cml_symtable_cell' rowspan='2'>")
                            Else
                                Console.WriteLine("<td class='cml_symtable_cell'>")
                            End If
 
                            If Not symbol.top Is Nothing Then
                                ' write a table to justify the top, and main qualifiers
                                Console.WriteLine("<table class='cml_inner_symtable'>")
                                Console.WriteLine("<tr class='cml_inner_symtable_row'>")
                                Console.WriteLine("<td class='cml_inner_symtable_cell'>")
 
                                ' write the top qualifier
                                Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.top + "' alt='' />")
 
                                Console.WriteLine("</td>")
                                Console.WriteLine("</tr>")
                                Console.WriteLine("<tr class='cml_inner_symtable_row'>")
                                Console.WriteLine("<td class='cml_inner_symtable_cell'>")
 
                                ' write the main symbol
                                Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.main + "' alt='' />")
 
                                Console.WriteLine("</td>")
                                Console.WriteLine("</tr>")
                                Console.WriteLine("</table>")
                            Else
                                ' there is no top qualifer, just write the main symbol
                                Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.main + "' alt='' />")
                            End If
 
                            Console.WriteLine("</td>")
                        End If
 
                        ' write the full-right qualifier column
                        If Not symbol.fullright Is Nothing And iRow = 0 Then
                            ' if there are 2 rows, make this column cover both
                            If nRows = 2 Then
                                Console.WriteLine("<td class='cml_symtable_cell' rowspan='2'>")
                            Else
                                Console.WriteLine("<td class='cml_symtable_cell'>")
                            End If
 
                            Console.WriteLine("<img class='cml_symbol_image' src='" + symbol.fullright + "' alt='' />")
 
                            Console.WriteLine("</td>")
                        End If
 
                        ' write the small-right qualifier column
                        If Not symbol.topright Is Nothing Or Not symbol.bottomright Is Nothing Then
                            Dim qual As String
                            If iRow = 0 Then
                                qual = symbol.topright
                            Else
                                qual = symbol.bottomright
                            End If
 
                            If qual Is Nothing Then
                                qual = blankQual
                            End If
 
                            Console.WriteLine("<td class='cml_symtable_cell'>")
                            Console.WriteLine("<img class='cml_symbol_image' src='" + qual + "' alt='' />")
                            Console.WriteLine("</td>")
                        End If
                    Next
 
                    Console.WriteLine("</table>")
 
                    ' we have rendered a symbol
                    rendered = True
                Next
            Next
        End If
 
        If Not rendered Then
            ' if we haven't rendered any symbols, we should use a blank placeholder instead, to ensure the
            ' text is positioned correctly
            Dim blankUri As String = "http://widrebus.symgate.com/" + creds.account + "/col/" + renderOpts.basesize + "/blank.sym"
            ' .sym files are automatically returned as png for firefox and ie7, and gif for ie6
 
            Console.WriteLine("<div class='cml_symbol_single'>")
            Console.WriteLine("<img class='cml_symbol_image' src='" + blankUri + "' alt='' />")
            Console.WriteLine("</div>")
        End If
 
        ' ************************** Write the text for the cmap, and close the tags **************************
 
        Console.WriteLine("<div class='cml_symbol_end'></div>")
        Console.WriteLine("</div>")
 
        Console.WriteLine("<div class='cml_cmap_text'>")
 
        If (cmap.emphasis) Then
            Console.WriteLine("<i>")
        End If
        If (cmap.strong) Then
            Console.WriteLine("<b>")
        End If
 
        Console.WriteLine(cmap.text)
 
        If (cmap.strong) Then
            Console.WriteLine("</b>")
        End If
        If (cmap.emphasis) Then
            Console.WriteLine("</i>")
        End If
 
        Console.WriteLine("</div>")
        Console.WriteLine("</div>")
    End Sub
 
End Module

HTML Output

Expected HTML output from the above example:

<html>
<head>
<title>Symbolisation Example</title>
<link rel='stylesheet' href='http://www.symgate.com/cml/cml.css'>
</head>
<body>
<div class='cml_paragraph'>
<div class='cml_paragraph_start'></div>
<div class='cml_cmap'>
<div class='cml_symbol'>
<div class='cml_symbol_start'></div>
<table class='cml_symtable'>
<tr class='cml_symtable_row'>
<td class='cml_symtable_cell'>
<img class='cml_symbol_image' src='http://widrebus.symgate.com/widgit/col/100/graphics/widgit rebus/h/hello.svg.sym' alt='' />
</td>
</table>
<div class='cml_symbol_end'></div>
</div>
<div class='cml_cmap_text'>
Hello
</div>
</div>
<div class='cml_cmap'>
<div class='cml_symbol'>
<div class='cml_symbol_start'></div>
<table class='cml_symtable'>
<tr class='cml_symtable_row'>
<td class='cml_symtable_cell'>
<img class='cml_symbol_image' src='http://widrebus.symgate.com/widgit/col/100/graphics/widgit rebus/e/earth 2.svg.sym' alt='' />
</td>
</table>
<div class='cml_symbol_end'></div>
</div>
<div class='cml_cmap_text'>
World!
</div>
</div>
<div class='cml_paragraph_end'></div>
</div>
</body>
</html>
Personal tools