Skip to main content

Defining and Using XData Blocks

An XData block is a class member that consists of a name and a unit of data that you include in a class definition for use by the class after compilation.

Basics

An XData block is a named unit of data that you include in a class definition, typically for use by a method in the class. Most frequently, it is a well-formed XML document, but it could consist of other forms of data, such as JSON or YAML.

You can create an XData block by typing it directly in your Integrated Development Environment (IDE).

An XData block is a named class member (like properties, methods, and so on). The available XData block keywords include:

  • SchemaSpec — Optionally specifies an XML schema against which the XData can be validated.

  • XMLNamespace — Optionally specifies the XML namespace to which the XData block belongs. You can also, of course, include namespace declarations within the XData block itself.

  • MimeType — The MIME type (more formally, the Internet media typeOpens in a new tab) of the contents of the XData block. The default is text/xml.

If used to store XML, the XData block must consist of one root XML element, with any valid contents.

XML Example

To access an XML document in an arbitrary XData block programmatically, you use %Dictionary.CompiledXDataOpens in a new tab and other classes in the %Dictionary package.

An XData block is useful if you want to define a small amount of system data. For example, suppose that the EPI.AllergySeverity class includes the properties Code (for internal use) and Description (for display to the users). This class could include an XData block like the following:

XData LoadData
{
<table>
 <row>1^Minor</row>
 <row>2^Moderate</row>
 <row>3^Life-threatening</row>
 <row>9^Inactive</row>
 <row>99^Unable to determine</row>
</table>
}

The same class could also include a class method that reads this XData block and populates the table, as follows:


ClassMethod Setup() As %Status
{
   //first kill extent
   do ..%KillExtent()
   
   // Get a stream of XML from the XData block contained in this class
   Set xdataID="EPI.AllergySeverity||LoadData"
   Set compiledXdata=##class(%Dictionary.CompiledXData).%OpenId(xdataID)
   Set tStream=compiledXdata.Data
   If '$IsObject(tStream) Set tSC=%objlasterror Quit
   
   set status=##class(%XML.TextReader).ParseStream(tStream,.textreader)
   //check status
   if $$$ISERR(status) do $System.Status.DisplayError(status) quit
   
   //iterate through document, node by node
   while textreader.Read()
   {
       if (textreader.NodeType="chars")
       {
           set value=textreader.Value
           set obj=..%New()
           set obj.Code=$Piece(value,"^",1)
           set obj.Description=$Piece(value,"^",2)
           do obj.%Save()
       }
   }
}

Notice the following:

  • The XML within the XData is minimal. That it, instead of presenting the allergy severities as XML element with their own elements or attributes, the XData block simply presents rows of data as delimited strings. This approach allows you to write the setup data in a visually compact form.

  • The EPI.AllergySeverity class is not XML-enabled and does not need to be XML-enabled.

JSON Example

A class could also include an XData block containing JSON content, like the following:

XData LoadJSONData [MimeType = "application/json"]
{
   {
      "person":"John", 
      "age":30,
      "car":"Ford"
   }
}

The same class could also include a class method that reads this XData block and populates a dynamic object, as follows:

/// Reads a JSON XData block
ClassMethod SetupJSON() As %Status
{
   
   // Get a stream of JSON from the XData block contained in this class
   Set xdataID="Demo.XData||LoadJSONData"
   Set compiledXdata=##class(%Dictionary.CompiledXData).%OpenId(xdataID)
   Set tStream=compiledXdata.Data
   If '$IsObject(tStream) Set tSC=%objlasterror Quit

   // Create a dynamic object from the JSON content and write it as a string
   Set dynObject = {}.%FromJSON(tStream)
   Write dynObject.%ToJSON()

}

YAML Example

A class could also include an XData block containing YAML content, like the following Swagger API specification:

XData SampleAPI [mimetype = "application/yaml"] 
{
swagger: "2.0"
info:
  title: Sample API
  description: API description in Markdown.
  version: 1.0.0
host: api.example.com
basePath: /v1
schemes:
  - https
paths:
  /users:
    get:
      summary: Returns a list of users.
      description: Optional extended description in Markdown.
      produces:
        - application/json
      responses:
        200:
          description: OK
}

This class method reads the XData block and writes its content, line by line:

/// Reads a YAML XData block
ClassMethod SetupYAML() As %Status
{
   
   // Get a stream of YAML from the XData block contained in this class
   Set xdataID="Demo.XData||SampleAPI"
   Set compiledXdata=##class(%Dictionary.CompiledXData).%OpenId(xdataID)
   Set tStream=compiledXdata.Data
   If '$IsObject(tStream) Set tSC=%objlasterror Quit

   // Write the content from the stream, line by line
   While 'tStream.AtEnd { 
      Write tStream.ReadLine(,.sc,.eol) 
      If eol { Write ! } 
   }
}
FeedbackOpens in a new tab