PackageDescription: SimpleXO


Simple XO

Last published: March 26, 2013 by 'stm'

Defines 21 Classes
Extends 21 Classes


SimpleXO (Simple XML to Object mapping) is a library to map convoluted, not necessarily valid, XML documents to Objects. The main concepts are Types and Mappings.
- A type takes an XML node, creates an object and applies a set of mappings to that node.
- A mapping defines which type a set of nodes is mapped to.

SimpleXOParserParser class>>parseSimpleXO: creates a parser, that maps an XML document/node, from a mapping description. A mapping description is a String as follows.

0. Comments
- # anything up to line end

1. List of namespace declarations:
- namespace = '' ...
- may be empty
- example:
namespace w3="http://www.w3schools.com"
namespace xsd="http://www.w3.org/2001/XMLSchema"


2. List of named types (cdata, element) and group declarations:
- One and only one type must be marked as document root.
root cdata ... or
root element ...

2.a) CDATA
- cdata { class: ; constructor: ; }
- name of type referenced in mappings
-
- qualified for classes in namespaces other than Smalltalk
- may be a shared variable
- binary or keyword message of class that takes a string and returns an Object
- If no constructor is provided #fromString: is sent.
- If no class is provided a String is created.
- example:
cdata STRING {}
cdata SYMBOL {
class: Symbol;
constructor: intern:;
..@id >> STRING (key: ids)
}

2.b) ELEMENT
- element { class: ; constructor: ; }
- constructor message sent to class
- If no constructor is provided #new is sent.
- If no class is provided a Dictionary (say Struct) is created.
- example:
element INTEGER { class: Integer; constructor: fromString: }
element POINT {
class: Point;
constructor: new;
x >> INTEGER;
y >> INTEGER
}

2.c) MAPPING
- map single element:
>>
- tokenize string-value and map each token with type:
>> []
- map collection:
++
- separated by ; (semicolon)
-
- similar to abbreviated relative XPath, no predicates
- nodes in namespace must be prefixed
- can be used in multiple mappings
- * and ? wildcards supported for name tests
- name of a defined type
- >> , []
- can be used together
- collection not set in parent if empty
- must not be provided
- example:
element ++ ELEMENT (aspect: elements);
file?? ++ FILE (aspect: files);
@attribute >> STRING (aspect: value);
@xsd:* >> STRING (aspect: xsd);
..@id >> STRING;
data/value >> STRING (aspect: rawData);
data/value >> VALUE[] (aspect: data);

2.d) OPTIONS
- setter:
- use as setter, e.g. #key: or #++
- aspect:
- same as "setter: :", convenience for structs
- transient
- apply type but do not set value in parent object
- key:
- apply type and use value as key for parent object
- transient mapping by default
- reference:
- apply type and use value to lookup object in
- If aspect and setter are undefined, the name of the last path step or #value is used as setter / key.
- example:
element >> ELEMENT;
# == element >> ELEMENT (aspect: element)
# == element >> ELEMENT (getter: element; setter: element:)
element/text() >> STRING;
# == element/text >> STRING (aspect: text)
node() >> STRING
# == node() >> STRING (aspect: value)
data? >> STRING
# == data? >> STRING (aspect: value)
meta >> META (transient);
# map meta elements, but do not set value in parent object
@id >> STRING (key: ids);
# id string not set in parent object
@xsd:id >> STRING (key: ids; aspect: xsdID);
# id string set in parent object
@ref >> STRING (reference: ids);
# use ref string to lookup and set a referenced object in parent

2.e) GROUPS
- group { }
- syntactic sugar to reference common mappings in different types
- example:
namespace xsd="http://www.w3.org/2001/XMLSchema"

cdata STRING {class: String; constructor: fromString:}

group ids {
@id >> STRING (key: ids; aspect: id);
@xsd:id >> STRING (key: xsdIDs)
}

element E {
# generates a struct
ids;
value/text() >> STRING
}

root element F {
# generates a struct
ids;
@ref >> STRING (reference: ids; aspect: element)
}

See SimpleXOParserBuilder if you want to build a SimpleXOParser programmatically.