"Propago" questo documento molto interessante su come è
strutturato un file legenda in ArcView...
'AVL' files are in ESRI's 'ODB' (object
database) format. This format is not documented but it is easy to
reverse-engineer, because it is an ASCII text representation of an Avenue object
(a legend object in this case). If you know the full structure of an Avenue
object, its attributes, and their data types, then you're all set.
Below
is an informal quasi-BNF description of an ODB file. The conventions used
include:
* Literals are enclosed in single quotes. (A newline literal is
represented by "NL" without quotes.)
* Zero or more instances of an
element are indicated by following it with a star *.
* Zero or one
instances of an element are indicated by following it with a question mark.
* One or more instances of an element are indicated by following it with
a plus sign.
* Whitespace (spaces and tabs) is indicated by "WS".
* Lines longer than 512 bytes are blocked into 512 bytes per line.
* Blank lines in between records and fields are allowed.
ArcView
is fairly liberal in allowing whitespace and even line breaks in various
locations, but I do not know the full extent of the rules it follows in this
regard.
The semantics are:
'Class' is the name of an internal
object class.
'Id' is a unique positive integer. Usually id values begin
with 1 and increase successively, but this is not a requirement.
'Version' is a decimal number such as "3.2" indicating which version of
ArcView produced the file.
'Attribute' is the name of a record attribute
and usually matches the name given in the help system. Attributes of collection
objects, such as lists, can appear multiple times, in the order in which they
are contained in the collection.
Strings are escaped using C conventions
(e.g., "\n" is a newline).
An 'XRef' is the id of another record in the
same odb file. The target of an XRef *MUST* exist and be of the right type (any
departure from this usually (always?) causes ArcView segmentation violations
when AV tries to read the file). Most references are forward references, but
they do not have to be and exceptions do occur.
'Char' is any ASCII
character.
'Hex2' and 'Hex4' are two- and four-digit hexadecimal values,
respectively. Hex2 and UInt values are also used to indicate enumerated data
types (symbolic values beginning with "#" in Avenue). I suspect that usually
0x00 corresponds to the first enumerated value appearing on the help page, 0x01
to the second, etc., but it's best to reverse-engineer each case as needed.
Apparently, 'Hex2' values are also used for certain short bitmaps, such
as collections of boolean flags.
A 'truth' encodes a boolean value: 0
for false, 1 for true.
A 'date' is a string representing a date, such as
"Tuesday, July 29,
2003
12:09:04 PM".
'Bitpiece' is a string of hex digits
zero to eight bits long; 'Bitblock' is a string if eight hex digits. The
bitblocks in bitmaps are separated by whitespace. Here is an example:
0123457 8a
This represents either the binary string (ArcView
bitmap)
000000010010001101000101011110001010
or
00000001001000110100010101111000101
depending on how many bits
it is supposed to have.
You might notice that an 'XRef' looks just like
a 'UInt'. *** It is impossible to tell from the file structure alone whether an
integral field value stands for that number or whether it is a reference to
another object in the file. *** This is why you *have* to know the object
structure in order to parse an odb file: you cannot separate syntax from
semantics.
That being said, the syntax evidently is simple. Indeed, most
people process ODB files without parsing them at all: they simply search for a
record (using the 'Class' string) or an attribute (using the 'Attribute' string)
and read the desired value. The standard example is to search for "Path:"; any
object with this as attribute is referencing a filename and the corresponding
value is, of course, that filename. This is how one discovers all external file
references embedded within an ODB file. (This form of parsing leads to errors,
of course, because any string value containing the sequence "Path:" will confuse
this method, but most programmers either are unaware of this possibility or
simply ignore it.)
In sum, then, you can easily parse an avl file, but
to do anything with the information you need detailed understanding of the
attributes of an Avenue legend object.
Here is a commented example of a
small (but complete) avl file. (The comments, of course, are not a part of the
original file, nor would they be recognized by AV as such.)
/3.2 ' The header record. Version is AV 3.2.
(ODB.1 ' An 'ODB' object: Record 1.
FirstRootClassName: "Legend" ' A string attribute
Roots: 2 ' A reference to record 2.
Version: 32 ' An integer, representing version 3.2.
)
(Legend.2 ' A legend object. The target of ODB.1[Roots].
SymType: 0x02 ' A type of symbol (a raster fill I believe)
LegType: 0x01 ' The legend type
ClassType: 0x03 ' The type of classification
Symbols: 3 ' A reference to record 3 (a list containing one symbol)
Class: 8 ' A reference to record 8, a Classification object
StdDevs: 1.00000000000000 ' Unused (vestigial)
NullSym: 9 ' A reference to record 9 (a transparent shade with white background)
NullValues: 13 ' A reference to record 13 (an empty NameDictionary)
StatValues: 14 ' A reference to record 14 (an empty NameDictionary)
Precision: -3 ' Rounding precision (3 decimal places)
)
(SymList.3 ' A SymbolList object. (Note the difference between the internal name
' and the Avenue classname.)
Child: 4 ' A reference to the only element of this collection.
)
(BShSym.4 ' A shaded symbol
Color: 5 ' A reference to record 5 (pale yellow)
Outline: 1 ' Index of the outline style in the line type palette
OutlineColor: 6 ' A reference to record 6 (a null color)
OutlineWidth: 0.10000000000000 ' Width in points
BgColor: 7 ' Background color; a reference to record 7 (color white)
)
(TClr.5 ' A color object (very pale yellow)
Red: 0xfeff ' Red intensity (16 bits!)
Green: 0xfcdb
Blue: 0xe618
)
(TClr.6 ' This is a NULL color.
)
(TClr.7 ' This is white: highest intensity of all three color channels.
Red: 0xffff
Green: 0xffff
Blue: 0xffff
)
(LClass.8 ' A Classification object
IsText: 1 ' A boolean value (true)
Precision: -3
)
(BShSym.9
Color: 10
Outline: 1
OutlineColor: 11
OutlineWidth: 0.10000000000000
BgColor: 12
)
(TClr.10
Name: "Transparent"
)
(TClr.11
Name: "Transparent"
)
(TClr.12
Red: 0xffff
Green: 0xffff
Blue: 0xffff
)
(NameDict.13 ' A NameDictionary object. This one is empty.
)
(NameDict.14 ' Another empty NameDictionary object.
)
--------------------------------------
BNF for ODB files
ODB ::= Header Record*
Header ::= '/' Version
Record ::= NL '(' Class '.' Id Field* NL ')'
Id ::= UInt
Field ::= NL Attribute ':' WS Value
Value ::= Int | Float | XRef | String | Hex2 | Hex4 | Bitmap | Truth | Date
Int ::= '-'? UInt
UInt ::= Digit+
Digit ::= '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'
Float ::= Int '.' UInt
XRef ::= UInt
String ::= '"' Char* '"'
Hex2 ::= '0x' HDigit HDigit
Hex4 ::= '0x' HDigit HDigit HDigit HDigit
HDigit ::= Digit | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
Bitmap ::= Bitblock? Bitblock? Bitblock? Bitpiece
Truth ::= '0' | '1'
Date ::= String
Class ::= Char+
Attribute ::= Char+
{end of BNF for ODB files}