Individualization and the XML Import interface
The purpose of the XML import interface is to let you use existing newsletter content repeatedly. If you have a Content Management System, you or the system can prepare XML files. The structure of the files, in conformity with the XML, is important to the system. These files will be put into the ~/XML Import List. The importable XML files must be built up as seen in the following sample file:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<FILE>
<META NAME="FIELDNAME1">Value1</META>
<META NAME="FIELDNAME2">Value2</META>
</FILE> |
The first line is a standard XML header and must be contained in any file that will be imported. The next XML TAG must be the enclosing <FILE>-TAG containing the data that will be imported later on. Pay attention to capitalization of the TAGs if you work with XML TAGs and XML files.
The data will be handed over within the <META NAME “FIELDNAME">VALUE1</META> submitting blocks. A field name can be an arbitrary variable that can be accessed with the help of GIS_API later on. The contents are submitted between the pointed brackets. Make sure that the contents are in conformity with the XML contents. This means that the signs <, >, and & need to be replaced by the XML entities & lt; & gt; and & amp;. This TAG is identical to the ones that are used in HTML. The files you put into the list ~/XML Import also must fulfill a certain naming convention. The names of the files must have the following construction: 123123.xml, hello.xml etc..
Performance range of the programming language GisAPI
Using the GIS API, you can open the contents that were uploaded using the XML interface, and work with them in your newsletter. In keeping with certain rules, this happens automatically. In addition, the language contains all the elements you need to work under conditions such as IF ... THEN ... ELSE (etc.).This chapter is aimed at the system administrator or programmer. As previously described above, this complex performance range can be provided for the editors and applied simply, due to the functionality of GIS-SUBSTITUTIONS. You can read more about this in Chapter “GIS-SUBSTITUTIONS.” You may insert GIS_API - blocks into any newsletter, at any time. All GIS_API commands must be enclosed by these two TAGs:
<GIS>
You will find the code here!
</GIS>
Note the use of capital versus lower-case letters in writing the commands.
The actual instructions for GIS_API are to be found between the start TAG (<GIS>) and the final TAG (</GIS>). These are explained in detail below. The general procedure consists of feeding certain field values to GIS_API in sorting and distributing the accompanying formatted data. An example follows,where the database field “HEADING” is fed into GIS_API. All the data will be sorted and distributed by topic.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<HEADLINE>>
SORT LATEST FIRST
FOREACH {PRINT "<<HEADLINE>>" }
</GIS> |
This is only one example. In a further example, we assume that the four XML files listed below were imported to BACKCLICK.
File 1:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<FILE>
<META NAME="DIRECTORY">/a/b/c</META>
<META NAME="FILENAME">ABC.HTML</META>
<META NAME="HEADLINE">ABC Headline 1</META>
<META NAME="TEXT">ABC_TESTFILE.HTML</META>
<META NAME="CONTENT_SOURCE">BACKCLICK</META>
<META NAME="CONTENT_ID">1</META>
</FILE> |
File 2:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<FILE>
<META NAME="DIRECTORY">/d/e/f</META>
<META NAME="FILENAME">DEF.HTML</META>
<META NAME="HEADLINE">DEF Headline 1</META>
<META NAME="TEXT">DEF_TESTFILE.HTML</META>
<META NAME="CONTENT_SOURCE">BACKCLICK</META>
<META NAME="CONTENT_ID">2</META>
</FILE> |
File 3:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<FILE>
<META NAME="DIRECTORY">/g/h/i</META>
<META NAME="FILENAME">GHI.HTML</META>
<META NAME="HEADLINE">GHI Headline 1</META>
<META NAME="TEXT">GHI_TESTFILE.HTML</META>
<META NAME="CONTENT_SOURCE">BACKCLICK</META>
<META NAME="CONTENT_ID">3</META>
</FILE> |
File 4:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<FILE>
<META NAME="DIRECTORY">/j/k/l</META>
<META NAME="FILENAME">JKL.HTML</META>
<META NAME="HEADLINE">JKL Headline 1</META>
<META NAME="TEXT">JKL_TESTFILE.HTML</META>
<META NAME="CONTENT_SOURCE">BACKCLICK</META>
<META NAME="CONTENT_ID">4</META>
</FILE> |
All of the following examples will repeatedly refer to the data of these four files. File 1 is the oldest file and file 4 is the youngest. To be able to understand the results, you must put the files into BACKCLICK one by one, at two-minute intervals. This guarantees a temporal classification of the data sets. Now you will switch to the menu item “Change Newsletter” and select the mailing list. Enter the following into the given text entry field:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<HEADLINE>>
SORT LATEST FIRST
FOREACH {PRINT "<<HEADLINE>>\n"}
</GIS> |
Open the preview window and when personalization is activated, you will see the following version:
Basics of the GIS_API language — syntax
The READ command:
As explained above, the READ command is used for sorting all data on <<HEADLINE>>. The double, pointed brackets tell the GIS_API that this is a field name. This field was imported within one of these four XML files and is now available for the system. The process described here for <<HEADLINE>> may be performed for all existing field names. If the field
DIRECTORY (for example) needs to be read in, simply enter READ <<DIRECTORY>>. In addition to the contents of the field that has been read in, you also have access to all other fields of a data set with further commands, as described in the following. If several READ commands are executed behind each other, all the results are inserted into the “hit list” in the sequence of the READ commands.
The SHRINK command:
To augment the above example: The command SHRINK assumes that not all of the headlines should be read out, but only the first two. This will reduce the list of results; for example:
[<GIS>READ <<HEADLINE>>SORT LATEST FIRST SHRINK "2"FOREACH { PRINT <<HEADLINE>>\n" }</GIS>]
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<HEADLINE>>
SORT LATEST FIRST
SHRINK "2"
FOREACH { PRINT "<<HEADLINE>>\n" }
</GIS> |
The consequence of this is that only the two most current headings are displayed. The result then would be:
JKL Headline 1
GHI Headline 1
Using SHRINK "2", the list of results is reduced to the first two elements. Since the list was sorted by topic, the result only consists of the two most current entries. This is because the SHRINK command removes the rest of the list from the list of results.
If you want to distribute only the second to fourth entry (because, for example, the first result should be dealt with separately), enter the following command: SHRINK "2" TO "4". The result would look like this:
GHI Headline 1
DEF Headline 1
ABC Headline 1
With the command SHRINK BY “FIELD NAME”, you can reduce the list of results on the entries that contain the field "FIELD NAME". Assuming that file 4 would not have any TEXT field, and that you would enter the following command sequence:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<HEADLINE>>
SORT LATEST FIRST
SHRINK BY <<TEXT>>
FOREACH { PRINT "<<HEADLINE>> " }
</GIS> |
the result would be:
GHI Headline 1
DEF Headline 1
ABC Headline 1
As of now you have only integrated data sets into your newsletter, without text fields. As you can see, file 4 is missing, since the field TEXT is not inserted into this data set. Using the SHRINK command, you can realize even further restrictions. With the following SHRINK command, it is possible to restrict the hit list to all hits with a certain field value, within certain limits.
SHRINK BY <<UEBERSCHRIFT>> IN "A" TO "D"
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<HEADLINE>>
SORT LATEST FIRST
SHRINK BY <<HEADLINE>> IN "A" TO "D"
FOREACH { PRINT "<<HEADLINE>>\n" }
</GIS> |
If you add the command to the example, the following result will be displayed:
DEF Headline 1
ABC Headline 1
According to the READ command, every data set containing the <<HEADLINE>> field will be available in the hit list. If you enter SORT LATEST FIRST, the hit list will be sorted by topic. The command SHRINK BY <<HEADLINE>> IN "A" TO "D" filters out all data sets not starting with letters between "A" and "D". This function can be used to sort several sections alphabetically. Instead of the field <<HEADLINE>> every field may be used again to reduce the hit list. This SHRINK command does not change anything in the sequence of sorting.
The PRINT command: The PRINT command is responsible for displaying the result.
The command line PRINT "<<HEADLINE>>" is responsible for displaying the value of every hit on the HEADLINE field in the newsletter. To force line breaks (for example), you can use arbitrary line breaks.
PRINT "<<HEADLINE>> "
or
PRINT "<<HEADLINE>>\n"
forces a line break after a HEADLINE has been displayed. You also can use curly brackets instead of the quotation marks.
PRINT {<<HEADLINE>><<TEXT>>}
or
PRINT {<<HEADLINE>>\n<<TEXT>>\n}
The following result will be displayed (if the command line is added to the example again):
JKL Headline 1
JKL_TESTFILE.HTML
GHI Headline 1
GHI_TESTFILE.HTML
DEF Headline 1
DEF_TESTFILE.HTML
ABC Headline 1
ABC_TESTFILE.HTML
The first line break behind <<HEADLINE>> causes a line break between every heading and the contents of the <<TEXT>> fields. The two line breaks behind <<TEXT>> provide the line spacing between the individual hits. As an alternative to a real line break, you can also use the sign sequence \n for a line break at any time.
The FOREACH command:
After a hit list is created using the READ command, the list of results may be sorted (SORT) and filtered (SHRINK) according to arbitrary criteria. Using the FOREACH command, actions (PRINT) may be carried out afterwards on the respective hits.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<HEADLINE>>
SORT LATEST FIRST
SHRINK BY "TEXT"
FOREACH {PRINT "<<HEADLINE>>\n"}
</GIS> |
The FOREACH instruction always consists of the actual command FOREACH and the curly brackets emphasized above. The hit list that has been created using the READ <<HEADLINE>> is now searched entry by entry in the appropriate sorting sequence defined within the curly brackets. All instructions within the curly brackets refer to the respective entry of the hit list. This means that if all data sets with the field <<HEADLINE>> are searched by the FOREACH command, you will have access to all elements of an entry. You will also have access to all other data fields of the respective hit at the same time. The example <<TEXT>> has already been described above. Not just the headline of every data set, but the <<TEXT>> field as well, will be displayed when passing through the list of results. Generally, you can always access ALL fields of a hit. FOREACH loops can also be arbitrarily packed!!!
The SORT command:
Using the SORT command, lists of results may be sorted following different criteria. You have already seen the command line SORT LATEST FIRST above. This command provides sorting according to topic. You may, for example, sort by any arbitrary field with the help of the SORT command: SORT BY <<TEXT>>. It will always be sorted alphabetically!
The VICE VERSA command:
The command VICE VERSA is used to reverse the sequence of a hit list (e.g., display the oldest contributions first, or display everything in reverse alphabetical order). If we change the example as follows:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<HEADLINE>>
SORT LATEST FIRST
VICE VERSA
FOREACH {PRINT "<<HEADLINE>>\n"}
</GIS> |
the following result will be displayed:
ABC Headline 1
DEF Headline 1
GHI Headline 1
JKL Headline 1
As you can see here, the result is in reverse order now but the values are the same!
The commands COPYLIST & READLIST:
After you have produced a hit list, you may produce a temporary copy using the command COPYLIST. If you delete the regular list using the command CLEAR, you can read the list produced with COPYLIST using the command READLIST again. The following example clarifies this function:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<HEADLINE>>
SORT LATEST FIRST
FOREACH {PRINT "<<HEADLINE>>\n"}
PRINT "\n" COPYLIST CLEAR
READ <<TEXT>>
SORT LATEST FIRST
VICE VERSA
FOREACH {PRINT "<<TEXT>>\n"}
READLIST PRINT "\n"
FOREACH {PRINT "<<HEADLINE>>\n"}
PRINT "\n"
</GIS> |
The following result will be displayed:
JKL Headline 1
GHI Headline 1
DEF Headline 1
ABC Headline 1
ABC_TESTFILE.HTML
DEF_TESTFILE.HTML
GHI_TESTFILE.HTML
JKL_TESTFILE.HTML
JKL Headline 1
GHI Headline 1
DEF Headline 1
ABC Headline 1
This version is caused by the COPYLIST and the READLIST commands. After using the CLEAR command in the example, you will enter another list, in another sorting sequence. The hit list that has been put in first is then reactivated, and the contents are distributed once more by READLIST. You can feed in the data fields once more using READ, but COPYLIST and READLIST are faster with large-scale commands! If you want to store several lists parallel to one another, then you can also give names to the copies, and then access single lists specifically. Assuming that you have entered a hit list and would like to store it under the name “List 1,” use the following command lines:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<DIRECTORY>>
COPYLIST "List1"
SHRINK "2"
FOREACH {PRINT "<<DIRECTORY>>\n"}
PRINT "\n\n"
READLIST "List1"
FOREACH {PRINT "<<DIRECTORY>>\n"}
</GIS> |
The result would look like this:
/j/k/l
/g/h/i
/j/k/l
/g/h/i
/d/e/f
/a/b/c
Another variation:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<DIRECTORY>>
COPYLIST "List1" SHRINK "2"
FOREACH {PRINT "<<DIRECTORY>>\n"}
PRINT "\n\n"
COPYLIST "List2" READLIST "List1"
FOREACH {PRINT "<<DIRECTORY>>\n"}
PRINT"\n\n"
READLIST "List2"
FOREACH {PRINT "<<DIRECTORY>>\n"}
PRINT"\n\n"
</GIS> |
The result will be displayed as follows:
/j/k/l
/g/h/i
/j/k/l
/g/h/i
/d/e/f
/a/b/c
/j/k/l
/g/h/i
Using VARIABLES
The Definition of a Variable:
First of all, a variable must be defined in order for it to be available for the system. This is done following these instructions:
VAR #Name# #Value#
#Name# stands for any character string containing alphanumerical signs (no umlaut, no blank spaces etc.), and #Value# stands for a number. Example:
VAR #C1# #0#
The variable C1 is assigned to the Value 0 in this example. Both the name and the value must always be in hash keys (#). Invalid variable names would be for example:
VAR #Hello There# #0#
VAR #Hello# There # #0#
VAR #Hello, There # #0# a.s.o.
PLEASE NOTE: In most cases, you may use existing variables as dummies almost anywhere.
Changing the values of the VARIABLES:
To increase or reduce the value of a variable, there are the two commands ADDVAR and SUBVAR. Assume that the variable C1 has the value 0 by using the following definition: VAR #C1# #0#. ADDVAR #C1# #5# : This command line will increase the value of C1 on 5.
The command line SUBVAR #C1# #3# reduces the value of C1 on 3.
Output of variable values:
To distribute the value of a variable, there is the command sequence # name # (in which # name # stands for the name of the respective variable). Note that # name # may be to used in every normal print instruction.
Example on output of variable values:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
VAR #C1# #0#
PRINT "'#C1#' is the value of C1\n"
ADDVAR #C1# #2#
PRINT "'#C1#' is the value of C1\n"
SUBVAR #C1# #1#
PRINT "'#C1#' is the value of C1\n"
</GIS> |
The output will be displayed as the following:
'0' is the value of C1
'2' is the value of C1
'1' is the value of C1
Special assignments of values on variables:
Using the command sequence #C1# LISTLENGTH you may assign the length of the current list to the variable C1. Assuming that the following lines have been entered:
<GIS>
READ <<DIRECTORY>>
VAR #C1# LISTLENGTH
PRINT "#C1# is the length of the List\s"
</GIS>
These command lines would show the following results:
4 is the length of the list
The length of the list may be useful for the construction of loops. Using #C1# LISTLENGTH "Listname", the length of a list named "Listname" may be assigned.
IF/ELSE-instructions/commands
Even when using the GIS_API, these mechanisms are offered by the IF/ELSE constructs. The general structure of this IF/ELSE instruction command would look like this: IF(CONDITION {ORDER} ELSE{ORDER}
If you know how to do programming, this may already be familiar to you.
In general, the ELSE part is optional, and must not be defined explicitly!
The process follows the format shown here:
If the condition is true (TRUE, > 1) the instructions of the IF block are executed; otherwise the instructions of the ELSE part for (FALSE, < 1) are carried out.
A condition (CONDITION) is a unary or binary operation whose result is either true (TRUE, > 1) or untrue (FALSE, < 1). A unary operation is an operation with only one operand. A binary operation is a comparison or an arbitrary operation with two operands. You can perform a binary operation on arbitrary GIS_API variables under certain conditions. You can access random GIS_API-variables, databank entries, EVAL blocks, and EXPR expressions, under certain conditions. You can also randomly interleave and group them into more complex conditions by using bracket pairs. Selectable operands:
Possible operands | Possible operations |
<<FELDNAME>> | AND (b) |
#Wörter# #Buchstaben# | OR (b) |
#Zahlen# | NOT (u) |
#VARIABLEN# | EQUALS (b) |
EXPR-Anweisungen | LT (less than) (b) |
TRUE | LE (less equal) (b) |
FALSE | GT(greater than) (b) |
GE(greater equal) (b) | |
MATCHES (b) | |
STARTS (b) | |
ENDS (b) |
These facts are best described using the following examples:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<DIRECTORY>>
FOREACH {
IF(<<TEXT>>){
PRINT {The article under <<DIRECTORY>> contains the text <<TEXT>>}}
ELSE{PRINT "There is no text contained in the system for <<DIRECTORY>>" }}
</GIS>
<GIS>
READ <<FILENAME>>
FOREACH {
IF(<<DIRECTORY>> OR <<TEXT>>){
PRINT {The file <FILENAME>> contains data on the DIRECTORY or text"}}ELSE{PRINT "No data found on <<FILENAME>>" }
}
</GIS> |
Interleaving the IF/ELSE-conditions:
As previously mentioned, you can interleave the conditions with the help of brackets.
Example:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
TRUE VAR #C1# #Testing okay#
IF( (#ABCDEF# ENDS #DEF#) OR (#123# GT #12#)){ PRINT "TRUE\n"
IF(#C1# MATCHES #unktio#){
PRINT "Working \n\n"
}
}
ELSE{PRINT "FALSE" }
</GIS> |
Overview of commands: An additional GIS_API command:
All italic signs are names (E.g. #Testname#)
SKIP THIS RECIPIENT
This command ensures that the newsletter is not sent out to all of the current recipients. (This makes sense if no new information on the receiver is available.)
This command distributes the dateof the content data sets. This data is distributed in the format that has been defined in "FORMAT". The format is explained in the file gis_cl.conf. "LANGUAGE" defines in which language certain variables (for example, the names of the months) are distributed. Possible values are 'de', 'en', 'nl', 'fr'.
"LANGUAGE" is an optional value. If this one is not indicated, the language is defined as 'DEFAULT-LANG'.
"FORMAT" is also optional. If this value is left out, the adjusted format is taken into account from the basic configuration.
IF(SUBSCRIBED){}
With this command, you may check to make sure that a subscriber has not canceled his or her account in the time period since the sending started.
IF(NOT SUBSCRIBED){}
The logical opposite.
IF(SUBSCRIBED ON MORE THAN 2){}
More than 2 (or x) subscribed newsletters. Operators may be [ MORE THAN | > | MT ].
IF(SUBSCRIBED ON MORE EQUALS 2){}
Greater/equal to 2 (or x) subscribed newsletters. Operators may be [ MORE EQUAL | MORE EQUALS| >= | ME ].
IF(SUBSCRIBED ON LESS THAN 2){}
Less than 2 (or x) subscribed newsletters. Operators may be [ LESS THAN | < | LT ].
IF(SUBSCRIBED ON LESS EQUALS 2){}
Less than/equal to 2 (or x) subscribed newsletters. Operators may be [ LESS EQUAL | LESS EQUALS| <= | LE ].
IF(SUBSCRIBED ON 2, 4){}
If a subscriber is registered on these particular newsletters: 2 and 4, arbitrary combinations can be indicated. For individualization of the content, the respective option must be activated in the administration or configuration. The individual subscriber fields, such as INTERESTS, FIRST NAME, etc., are accessed within the GIS-API, also with the help of the $$FIELDNAME$$ notation.
Several examples:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
IF($$INTERESTS$$ MATCHES "Sports"){ PRINT"News on soccer ......\n" }
IF($$TITLEE$$ EQUALS "Misses"){ PRINT"The new Parfume of XY pour Femme ....." }
|
PLEASE NOTE: AT conditional branchings (IF/ELSE), always group conditions! This means that you must always put groups of operands into bracket pairs. Here is one example:
IF (($$FIRSTNAME$$ MATCHES "Peter") AND ($$NAME$$ EQUALS "test")) { }
Commands to rewrite data in the profile
The following commands are used to rewrite data that concerns an arbitrary GIS¬¬_API logic in the data set of a current recipient, during the sending of a newsletter. This mechanism can be used (for example) to store content that the subscriber has already received, in the subscriber’s data set.
INSERT $$FIELDNAME$$, "VALUE"
INSERT $$IFELDNAME$$, #VALUEOFVARIABLE#
With this command, a value or the value of a GIS_API variable is added to the subscriber field FIELDNAME. If this field does not yet exist, then it is created in the subscriber’s data set automatically. If If the value already exists, then the value is added without affecting any previous values.
SET $$FIELDNAME$$, "VALUE"
SET $$FIELDNAME$$, #VALUEOFVARIABLE#
The command works exactly like the previous one, with the exception that this command overwrites all previous values of FIELDNAME. In the end, the field FIELDNAME contains only the assigned value.
DELETE $$FIELDNAME$$, "VALUE"
DELETE $$FIELDNAME$$, #VALUEOFVARIABLE#
Using this command, single values may be deleted from several FIELDNAME fields within the subscriber’s data set. The rest of the values will be stored.
REDUCE $$FIELDNAME$$, "NUMBER"
REDUCE $$FIELDNAME$$, #VALUEOFVARIABLE#
With this command, the number of values of the field FIELDNAME can be reduced to a certain number (NUMBER). #VALUEVARIABLE # must be a number here! The values that remain shown are the most current values. This command is designed to provide a maximum number of current values, where current values are assigned without lowering the performance GIS API linearly.
Spezial Variables
The special variable # CONTENTKEY # can be used arbitrarily. The information within the key is current, is used internally, and contains a content data set processing a FOREACH instruction. This variable can be stored in the respectively current subscriber image and can show as a conditional branching whether or not a subscriber has already read the respective content. The following example helps to clarify this. It is a simple example, showing how to bar a subscriber from receiving the same content more than once.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<GIS>
READ <<DIRECTORY>>
SORT LATEST FIRST
SHRINK 100
VAR #TITEL# ##
VAR #COUNTER# #1#
FOREACH {
IF(#COUNTER# le #10#){
IF( <<TITEL>> EQ ## ){}
ELSE{
IF($$PREVCONTENT$$ EQ "#CONTENTKEY#"){
PRINT"We will not send you any content you have already received. \nYou already have this information.'<<TITEL>>'!\n\n"
} ELSE{
INSERT $$PREVCONTENT$$, "#CONTENTKEY#"
REDUCE $$PREVCONTENT$$, 100
PRINT "#COUNTER#. But you haven't read this:\n'<<TITEL>>' until now. \n\n"
ADDVAR #COUNTER# #1#
} }
}
}
</GIS> |