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 type) 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.
Using XData (XML Example)
To access an XML document in an arbitrary XData block programmatically, you use %Dictionary.CompiledXData 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:
/// called by EPI.Utils.GenerateData 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.
Using XData (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() }
Using XData (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 ! } } }