User's Guide

XML Mapping Types

VisualAge Smalltalk XML mapping supports the following mapping types:

Mapping Attributes

The attribute mapping maps an XML element that contains an attribute to an attribute of a Smalltalk class. A subelement that is a text element can also be mapped as an attribute. For example, if number is an attribute of Order and Order.date is a subelement that is a text element, both number and Order.date can be mapped using an attribute mapping.

<?xml version="1.0"?>
<!DOCTYPE Order SYSTEM "OrderEnt.dtd">
<Order number="O00001" status="Open">
  <Order.date>2000-02-14</Order.date>
</Order>

The class element mapping follows:

<ClassElementMapping ElementTagName="Order" ClassName="JrcOrder">
     <AttributeMapping ClassAttribute="orderNumber">
         <Attribute>number</Attribute>
     </AttributeMapping>
     <AttributeMapping 
        ClassAttribute="datePlaced" 
        AttributeClassCreationMethod="dateFromIbmIsoString:">
              <Attribute>Order.date</Attribute>
     </AttributeMapping>
</ClassElementMapping>
 

The attribute specification for the datePlaced feature of the JrcOrder class has the attribute class Date. The attribute class creation method AttributeClassCreationMethod, specifies the name of a Date class method. The method is set to dateFromIbmIsoString: in order to create the string as a date. The string in the XML will be passed as the argument.

Note:The #abtXmlFromString: class method provides an alternative way to map strings. The #abtXmlFromString: method can be overridden to create an instance of a simple object from a passed string. The #abtXmlFromString: method is invoked by default when no AttributeClassCreationMethod or StringConversionMethod method is specified in an attribute mapping.

Mapping Subelements

Subelement mapping maps an XML element to a class attribute. For example, if Customer is an attribute of the Order class, the Order element maps to the Order class and the Customer attribute of the Order class maps to the Customer element. The following example creates an instance of JrcOrder and the Customer attribute contains an instance of JrcCustomer:

<ClassElementMapping ElementTagName="Order" ClassName="JrcOrder>
     <AttributeMapping ClassAttribute="orderNumber">
       <Attribute>number</Attribute>
     <AttributeMapping ClassAttribute="customer">
       <SubElement>Customer</SubElement>
     </AttributeMapping>
</ClassElementMapping>
<ClassElementMapping ElementTagName="Customer" ClassName="JrcCustomer">
     <AttributeMapping ClassAttribute="number">
           <Attribute>number</Attribute>
     <AttributeMapping>
     <AttributeMapping ClassAttribute="name">
           <Attribute>name</Attribute>
     </AttributeMapping>
</ClassElementMapping>
 

Mapping Subelement Attributes

Subelement attribute mapping maps an XML element to the attribute of a subelement. For example, the CustomerId subelement contains the name and number of the customer. There is no corresponding CustomerId class in Smalltalk. The name and number of the customer are part of the Customer class. Subelement attribute mapping maps the name and number attributes to the Customer class.

<?xml version="1.0"?>
 
<!DOCTYPE Order SYSTEM "OrderEnt.dtd">
<Order number="O00001" status="Open">
    <Customer>
        <CustomerID name="Joe Smith" number="C135">
        <! other customer stuff deleted >
    </Customer>
    <Order.date>2000-02-14</Order.date>
</Order>

The class element mapping follows:

<ClassElementMapping 
     ElementTagName="Customer" 
     ClassName="JrcCustomer">
    <AttributeMapping ClassAttribute="number">
        <SubElement>CustomerID</SubElement>
        <Attribute>number</Attribute>
    </AttributeMapping>
    <AttributeMapping ClassAttribute="name">
        <SubElement>CustomerID</SubElement>
        <Attribute>name</Attribute>
    </AttributeMapping>
</ClassElementMapping>
 

Mapping Collections

Subelement mappings can map an XML element to a class attribute that is a collection, or a class that demonstrates collection behavior.

For example, an Order contains a collection of line items.

<ClassElementMapping 
     ElementTagName="Order" 
     ClassName="JrcOrder">
<AttributeMapping ClassAttribute="lineItems">	      
    <SubElement>LineItem</SubElement>	
</AttributeMapping>
</ClassElementMapping>
<ClassElementMapping ElementTagName="LineItem" ClassName="JrcLineItem">
     <AttributeMapping ClassAttribute="quantity" StringConversionMethod="asNumber">
       <Attribute>Quantity</Attribute>
     </AttributeMapping>
     <AttributeMapping ClassAttribute="item">
       <SubElement>Item</SubElement>
    </AttributeMapping>
  </ClassElementMapping>
 

The LineItem element maps to the JrcLineItem class. The lineItems class attribute should contain a collection of JrcLineItem. If the attribute specification for lineItems returns true to the method representsCollection, the abtAddItem: method will be called to add the subelement instance of JrcLineItem to the collection.

If you have a class that behaves like a collection, implement the following methods:

abtAddItem:anArray
The anArray class contains index, key and subelement instances.

abtImplementsCollectionMapping
This method is called by the #representsCollection method.
Note:These methods are provided in the Smalltalk collection hierarchy.
 

Mapping to a Dictionary

Mapping subelements to a dictionary is similar to mapping collections except that you must specify a key attribute. The mapping specification indicates which attribute of the subelement must be used as the key in the dictionary.

The following example uses a dictionary to store transaction information. The dictionary uses a key datetime, which is the date and time, to store each record. A record is an instance of CompanyInfo, which contains the user name and the amount of the transaction. The example XML source follows:

<?XML VERSION="1.0" ?> 
<!DOCTYPE bips SYSTEM "d:\bips.dtd"> 
<bips version="1.0"> 
<payment-response> 
<payment-response-id>1</payment-response-id>
<statement datetime = "6/6/2000-11:38:37 AM">
<description>Checking</description>
<contextual-info>113</contextual-info>  "amount in checking"
</statement>
<statement datetime = "6/6/2000-11:38:37 AM">
<description>Cable Company</description>
<contextual-info>-14182</contextual-info> "balance with cable company"
</statement>
</payment-response>
</bips> 

The example mapping specification follows:

<?xml version="1.0"?>
<!DOCTYPE XmlMappingSpec SYSTEM "map.dtd" >
<XmlMappingSpec Name="CustomerMappings">
 
<ClassElementMapping ElementTagName="bips" ClassName="ResponseObject" >
  <AttributeMapping ClassAttribute="transDictionary">
    <SubElement Key="datetime">statement</SubElement>
  </AttributeMapping>
</ClassElementMapping>
 
<ClassElementMapping ElementTagName="statement" ClassName="CompanyInfo" >
  <AttributeMapping ClassAttribute="name">
    <Attribute>description</Attribute>
  </AttributeMapping>
  <AttributeMapping ClassAttribute="amount">
    <Attribute>contextual-info</Attribute>
  </AttributeMapping>
</ClassElementMapping>
</XmlMappingSpec >

Specifying Interface Specifications

The mapping function uses the attribute specifications contained in the class interface specification. However, not all classes have an interface specification. You can use XML to specify interface specifications for classes that do not contain them. The following DTD, abtcldef.dtd, is provided:

<!ELEMENT Model (ClassDefinition)*>
<!ENTITY % FeatureSpec 
    '(AttributeSpec | ActionSpec | EventSpec)'>
<!ELEMENT ClassDefinition InterfaceSpec>
<!ATTLIST ClassDefinition
    Name NMTOKEN #REQUIRED>
<!ELEMENT InterfaceSpec %FeatureSpec;*>
<!ELEMENT AttributeSpec EMPTY>
<!ATTLIST AttributeSpec
    Name NMTOKEN #REQUIRED
    Class  NMTOKEN #REQUIRED
    GetSelector NMTOKEN #IMPLIED
    SetSelector NMTOKEN #IMPLIED>
<!ELEMENT ActionSpec EMPTY>
<!ELEMENT EventSpec EMPTY>

In the above example, the ActionSpec and EventSpec elements are not currently used.

For the AttributeSpec element, get and set selectors are optional. If get and set selectors are not provided, the Name attribute is used to create default selectors. For example, if the AttributeSpec element has a Name of number, the defaults to number and the SetSelector defaults to number:

The instance method privateInterfaceSpec can be overridden in order to answer the parsed interface specification.

The following Smalltalk code reads interface specifications into the cache:

| domSource   |
	domSource := 
		(AbtXmlDOMParser newValidatingParser) 
			parseURI: 'E:\xmlJim\ClassModel.xml'.
	AbtXmlObjectCache current addInterfaceSpecsFromModelDOM: domSource.


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]