Create the data schema (xsd) for a Swift data source
After you write a Swift report program that generates XML, you then must write the data schema (xsd) file for that XML. This file is used by the Genero Report Designer to provide a list of data objects for use in the report design.
The data schema file used by the Swift report program is the XML Schema Definition (xsd) file, which is the standard for defining Extensible Markup Language (XML) documents recommended by the W3C consortium. For more information about XSD, please see the W3C site (www.w3.org).
- It describes an instance document (i.e. an XML file or a data stream record) giving the structure and order of the data that should appear as data input for your application.
- It defines the elements and attributes required by your report to reference the data.
It is recommended to use the Genero Report Writer's Business Application Modeler (BAM), which can generate the data schema (xsd) file automatically from your Swift report application source file (.swift). You can also write a generator of schema definition if you wish.
Creating a basic data model for your report application
In a real world situation, the data would be read from another source, and an iterator would read the data into memory and into the data stream one record at a time. Here the data is specified in the code.
...
public class Sales
{
public var content_handler: UnsafeMutablePointer<ContentHandler>
var shopName: String
var zipCode: Int
var day: DateComponents
var items = [SalesItem]()
public init?(_ content_handler: UnsafeMutablePointer<ContentHandler>,
_ shopName: String,
_ zipCode: Int,
_ day: DateComponents)
{
self.content_handler = content_handler
self.shopName = shopName
self.zipCode = zipCode
self.day = day
self.items.append(SalesItem("Tablelamp", SalesItem.Category.Furniture, 23.00, nil));
self.items.append(SalesItem("Tablelamp", SalesItem.Category.Furniture, 267.00, self.items.last));
self.items.append(SalesItem("Officechair", SalesItem.Category.Furniture, 155.00, self.items.last));
self.items.append(SalesItem("Grandfather clock", SalesItem.Category.Furniture, 329.00, self.items.last));
self.items.append(SalesItem("Scissors", SalesItem.Category.Supplies, 19.00, self.items.last));
self.items.append(SalesItem("Measuring tape", SalesItem.Category.Supplies, 23.00, self.items.last));
self.items.append(SalesItem("Sunglasses", SalesItem.Category.Travelling, 15.95, self.items.last));
self.items.append(SalesItem("Penknife", SalesItem.Category.Travelling, 6.25, self.items.last));
self.items.append(SalesItem("Ornateangel", SalesItem.Category.Art, 1.95, self.items.last));
self.fetch()
}
public func fetch()
{
startElement(content_handler, "sales")
attribute(content_handler, "xmlns", "http://www.4js.com/2004/REPORT")
addElement(content_handler, "shopName", shopName)
addElement(content_handler, "zipCode", "\(zipCode)")
addElement(content_handler, "day", convertDateComponentsToString(day)!)
for item in items
{
item.serializeToXML(content_handler)
}
endElement(content_handler, "sales")
}
class SalesItem
{
enum Category: String {
case Furniture, Art, Supplies, Travelling
}
var articleName: String
var category: Category
var price: Double
var runningTotal: Double
// The previous item is passed to allow computing the running total.
init(_ articleName: String, _ category: Category, _ price: Double, _ previousItem: SalesItem?)
{
self.articleName = articleName
self.category = category
self.price = price
self.runningTotal = (previousItem == nil ? price : previousItem!.runningTotal + price)
}
func serializeToXML(_ content_handler: UnsafeMutablePointer<ContentHandler>)
{
startElement(content_handler, "items")
addElement(content_handler, "articleName", articleName)
addElement(content_handler, "category", category.rawValue)
addElement(content_handler, "price", "\(price)")
addElement(content_handler, "runningTotal", "\(runningTotal)")
endElement(content_handler, "items")
}
}
}
You
can create the data schema xsd file based on the properties and fields of
your application's classes as shown in the xsd file below.Example xsd schema
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="sales" type="sales"></xs:element>
<xs:complexType name="sales">
<xs:sequence>
<xs:element name="shopName" type="xs:string" nillable="true"></xs:element>
<xs:element name="zipCode" type="xs:int"></xs:element>
<xs:element name="day" type="xs:dateTime" nillable="true"></xs:element>
<xs:element name="items" type="salesItem" nillable="true" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="salesItem">
<xs:sequence>
<xs:element name="articleName" type="xs:string" nillable="true"></xs:element>
<xs:element name="category" type="category" nillable="true"></xs:element>
<xs:element name="price" type="xs:double"></xs:element>
<xs:element name="runningTotal" type="xs:double"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="category">
<xs:restriction base="xs:string">
<xs:enumeration value="Furniture"></xs:enumeration>
<xs:enumeration value="Art"></xs:enumeration>
<xs:enumeration value="Supplies"></xs:enumeration>
<xs:enumeration value="Travelling"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:schema>
The
sales schema file consists of the following:- A schema element that references the W3C recommended version of
XSD
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- Several subelements identified by the schema's namespace prefix
(xs:element).
- Each element is named to identify it by the data it will contain in the instance document
(i.e. the XML file or the data stream
record)
<xs:element name="zipCode" type="xs:int"></xs:element>
- Each element also has a
type
attribute to specify its data type, simple or complex. When elements do not contain child elements, they are defined as simple types, e.g. xs:string, xs:date, xs:decimal, etc. For more information on the data types that are built in to XML schema, see http://www.w3.org and search for "datatypes".
- Each element is named to identify it by the data it will contain in the instance document
(i.e. the XML file or the data stream
record)
<xs:complexType name="sales">
<xs:sequence>
<xs:element name="shopName" type="xs:string" nillable="true"></xs:element>
<xs:element name="zipCode" type="xs:int"></xs:element>
<xs:element name="day" type="xs:dateTime" nillable="true"></xs:element>
<xs:element name="items" type="salesItem" nillable="true" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
These
types specify how data is modeled specifically in our sales application. The sales type in
the example has four child elements: shopname, zipCode, day, and items. The element "items" is itself of type "salesItems", which is another complextype defined for
the list of items sold. The xs:sequence specifies the order these should
appear in the record. As sales items can be zero or unlimited, the attributes
minOccurs="0"
and maxOccurs="unbounded"
specify this for
validation in the instance document.
The Genero Report Engine does not support optional values;
setting required=true
is mandatory. If a
variable needs to be optional, use
"nillable=true
" and set the variable to
null when there is no value.