Using Caché XML Tools
Generating XML Schemas from Classes
[Back] [Next]
Go to:

This chapter describes how to use %XML.Schema to generate XML schemas from your XML-enabled classes. It discusses the following:

To generate a complete schema that defines types for multiple classes in the same XML namespace, you build the schema by using %XML.Schema and then generate output for it by using %XML.Writer.
Building a Schema from Multiple Classes
To build an XML schema, do the following:
  1. Create a new instance of %XML.Schema.
  2. Optionally set the properties of your instance:
    You must set these properties before calling the AddSchemaType() method.
  3. Call the AddSchemaType() method of your instance.
    method AddSchemaType(class As %String, 
                         top As %String  = "", 
                         format As %String, 
                         summary As %Boolean  = 0, 
                         input As %Boolean  = 0, 
                         refOnly As %Boolean  = 0) as %Status
    This method returns a status, which should be checked.
  4. Repeat the previous step as necessary.
  5. Optionally, to define the location of imported schemas, call the DefineLocation() method.
    method DefineLocation(namespace As %String, location As %String)
    Here namespace is a namespace used by one or more of the referenced classes, and location is a URL or path and filename of the corresponding schema (XSD file).
    You can call this method repeatedly to add locations for multiple imported schemas.
    If you do not use this method, the schema does include an <import> directive, but does not give the schema location.
  6. Optionally, to define additional <import> directives, call the DefineExtraImports() method.
    method DefineExtraImports(namespace As %String, ByRef imports)
    Here namespace is the namespace into which the <import> directives should be added, and imports is a multidimensional array of the following form:
    Node Value
    arrayname("namespace URI") String that gives the location of the schema (XSD file) for this namespace.
Generating Output for the Schema
After you have created an instance of %XML.Schema as described in the previous section, do the following to generate output:
  1. Call the GetSchema() method of your instance to return the schema as a node of a document object model (DOM).
    This method takes one argument: the URI of the target namespace for the schema. The method returns an instance of %XML.Node, which is described in the chapter Representing an XML Document as a DOM.”
    If the schema does not have a namespace, use "" as the argument for GetSchema().
  2. Optionally modify this DOM.
  3. To generate the schema, do the following:
    1. Create an instance of the %XML.Writer class and optionally set properties such as Indent.
    2. Optionally call the AddNamespace() method and other methods of the writer, to add namespace declarations to the <schema> element. See Adding Namespace Declarations,” earlier in this book.
      Because the schema probably refers to simple XSD types, it is useful to call AddSchemaNamespace() to add the XML schema namespace.
    3. Call the DocumentNode() or Tree() methods of the writer, using your schema as an argument.
      For information on using these methods, see Writing XML Output from a DOM in the chapter Representing an XML Document as a DOM.”
For additional examples, see the class reference for %XML.Schema.
Simple Example
The first example shows the basic steps:
 Set schemawriter=##class(%XML.Schema).%New()
 //add class and package (for example)
 Set status=schemawriter.AddSchemaType("Facets.Test")

 //retrieve schema by its URI
 //which is null in this example
 Set schema=schemawriter.GetSchema("")
 //create writer
 Set writer=##class(%XML.Writer).%New()
 Set writer.Indent=1
 //use writer
 Do writer.DocumentNode(schema)
More Complex Schema Example
Consider the following scenario. The Person class is as follows:
Class SchemaWriter.Person Extends (%Persistent, %XML.Adaptor)

Parameter NAMESPACE = "";

Property Name As %Name;

Property DOB As %Date(FORMAT = 5);

Property PatientID as %String;

Property HomeAddress as Address;

Property OtherAddress as AddressOtherNS ;
The Address class is defined to be in the same XML namespace (""), and the OtherAddress class is defined to be in a different XML namespace ("").
The Company class is also defined to be in the XML namespace "". It is defined as follows:
Class SchemaWriter.Company Extends (%Persistent, %XML.Adaptor)

Parameter NAMESPACE = "";

Property Name As %String;

Property CompanyID As %String;

Property HomeOffice As Address;

Notice that there is no property relationship that connects the Person and Company classes.
To generate a schema for the namespace "", we could use the following:
ClassMethod Demo()
    Set schema=##class(%XML.Schema).%New()
    Set schema.DefaultNamespace=""
    Set status=schema.AddSchemaType("SchemaWriter.Person")
    Set status=schema.AddSchemaType("SchemaWriter.Company")
    Do schema.DefineLocation("","c:/other-schema.xsd")

    Set schema=schema.GetSchema("")

    //create writer
    Set writer=##class(%XML.Writer).%New()
    Set writer.Indent=1
    Do writer.AddSchemaNamespace()
    Do writer.AddNamespace("")
    Do writer.AddNamespace("")
    Set status=writer.DocumentNode(schema)
    If $$$ISERR(status) {Do $system.OBJ.DisplayError() Quit }
The output is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="" 
  <import namespace="" schemaLocation="c:/other-schema.xsd"/>
  <complexType name="Person">
      <element minOccurs="0" name="Name" type="s:string"/>
      <element minOccurs="0" name="DOB" type="s:date"/>
      <element minOccurs="0" name="PatientID" type="s:string"/>
      <element minOccurs="0" name="HomeAddress" type="s01:Address"/>
      <element minOccurs="0" name="OtherAddress" type="s02:AddressOtherNS"/>
  <complexType name="Address">
      <element minOccurs="0" name="State">
          <restriction base="s:string">
            <maxLength value="2"/>
      <element minOccurs="0" name="Zip">
          <restriction base="s:string">
            <maxLength value="10"/>
  <complexType name="Company">
      <element minOccurs="0" name="Name" type="s:string"/>
      <element minOccurs="0" name="CompanyID" type="s:string"/>
      <element minOccurs="0" name="HomeOffice" type="s01:Address"/>
Notice the following: