This chapter describes how to generate XML output from InterSystems IRIS objects.

Creating an XML writer overview

InterSystems IRIS provides tools for generating XML output for InterSystems IRIS objects. You can specify details for XML projections, as described for projecting objects into XML. Then create a Writer method that specifies the overall structure of the XML output: the character encoding, the order in which objects are displayed, whether processing instructions are included, and so on.

Basic requirements are as follows:

  • If the output of a particular object is required, the class definition of that object must be extended to % xml.adaptor. With a few exceptions, the class referenced by this object must also extend % xml.adaptor.

  • The output method must create an instance of % xml.writer and then use the methods of that instance.

The following terminal session shows a simple example in which we access an XML-enabled object and generate output for it:

/// d ##class(Sample.Person).Populate(100)
/// w ##class(PHA.TEST.Xml).Obj2Xml(1)
ClassMethod Obj2Xml(ID)
{
	s obj = ##class(Sample.Person%).OpenId(ID)
	s xml = # #class(%XML.Writer%).New(a)s xml.Indent=1
	s status = xml.RootObject(obj)
	q ""
}

Copy the code
DHC-APP>w ##class(PHA.TEST.Xml).Obj2Xml(1)
<?xml version="1.0" encoding="UTF-8"? > <Person> <Name>yaoxin</Name> <SSN>111-11-1117</SSN>
  <DOB>1990-04-25</DOB>
  <Home>
    <Street>889 Clinton Drive</Street>
    <City>St Louis</City>
    <State>WI</State>
    <Zip>78672</Zip>
  </Home>
  <Office>
    <Street>9619 Ash Avenue</Street>
    <City>Ukiah</City>
    <State>AL</State>
    <Zip>56589</Zip> </Office> <Name> pu Yi </Name> <SSN>111-11-1115</SSN>
    <FavoriteColors>
      <FavoriteColorsItem>Red</FavoriteColorsItem>
      <FavoriteColorsItem>Orange</FavoriteColorsItem>
      <FavoriteColorsItem>Yellow</FavoriteColorsItem>
      <FavoriteColorsItem>Green</FavoriteColorsItem>
    </FavoriteColors>
  </Spouse>
  <FavoriteColors>
    <FavoriteColorsItem>Red</FavoriteColorsItem>
    <FavoriteColorsItem>Orange</FavoriteColorsItem>
    <FavoriteColorsItem>Yellow</FavoriteColorsItem>
  </FavoriteColors>
  <Age>31</Age>
</Person>
Copy the code

Create an output method

The output method constructs an XML document paragraph by paragraph in the specified order. The overall structure of the output method depends on whether you want to output the entire XML document or just a fragment.

Overall structure of the output method

Methods should perform some or all of the following operations in the following order:

  1. If you are using an object that may not be valid, call the object’s%ValidateObject()Method and check the returned status. If the object is invalid, the XML is also invalid.

%XML.WriterObjects are not validated before they are exported. This means that if you have just created an object but have not validated it yet, the object (and the XML) may be invalid (for example, because of a lack of required attributes).

  1. create%XML.WriterClass, and sets its properties as needed.

In particular, the following properties need to be set:

  • IndentIndent – Controls whether the output is generated in indentation and line feeds (if indentation equals 1) or as a single long line (if indentation equals 0). The latter is the default.
  • IndentCharsIndent character – Specifies the character to indent. A string with a default value of two Spaces. If the indent is 0, this property is invalid.
  • CharsetCharacter set – Specifies the character set to use.

For readability, the examples in this document use indentation equal to 1.

  1. Specify the output target.

By default, output is written to the current device. To specify an output target, call one of the following methods before you start writing the document:

  • OutputToDevice()– Directs output to the current device.
  • OutputToFile()– Directs output to the specified file. You can specify an absolute path or a relative path. Note that the directory path must already exist.
  • OutputToString()– Directs output to a string. Later, you can use another method to retrieve this string.
  • OutputToStream()– Directs output to the specified stream.
  1. Start the document. You can use the StartDocument() method. Note that if you have not already started the document with StartDocument(), the following methods will implicitly start the document: Write (), WriteDocType (), RootElement (), WriteComment () and WriteProcessingInstruction ().

  2. You can choose to write the preface line to the document. You can use the following methods:

  • WriteDocType()– Write a DOCTYPE declaration.
  • WriteProcessingInstructions()– Write processing instructions.
  1. Optionally, you can specify a default namespace. The writer uses it for classes with undefined XML namespaces.
  2. Optionally, you can add a namespace declaration to the root element. To do this, you can invoke several utility methods before starting the root element.
  3. Start the root element of the document. The details depend on whether the root element of the document corresponds to an InterSystems IRIS object. There are two possibilities:
  • The root element may correspond directly to an InterSystems IRIS object. This is often the case if you are generating output for a single object.

In this case, you use the RootObject() method, which writes the specified XML-enabled object as the root element.

  • The root element may simply be a wrapper around a set of elements that are InterSystems IRIS objects.

In this case, the RootElement() method is used, which inserts the root-level element with the specified name.

  1. If you are usingRootElement()Method to generate output for one or more elements within the root element. You can write any element in the root element in any order or logic you choose. There are several ways to write individual elements, and you can use a combination of these techniques:
  • You can useobject()Method that writes xmL-enabled objects. You can specify the name of this element, or you can use a default value defined by the object.
  • You can useelement()Method that writes the opening tag of the element using the name provided. Then, it can be usedWriteAttribute(),WriteChars(),WriteCData()Etc to write content, attributes, and child elements. The child element could be another oneElement()Or it could beObject(). useEndElement()Method indicates the end of the element.
  • You can use%XML.ElementAnd manually construct the elements.
  1. Student: If you use thetaRootElement()Method, callEndRootElement()Methods. This method closes the root element of the document and reduces the indentation, if any, as needed.
  2. If the document is taken fromStartDocument()To start, please callEndDocument()Method to close the document.
  3. If you are directing output to a string, useGetXMLString()Method to retrieve the string.

There are many other possible organizations, but be aware that some methods can only be called in certain contexts. Specifically, once you start a document, you cannot start another document until you finish the first one. If you do, the Writer method returns the following state:

#6275: Cannot output a new XML document or change %XML.Writer properties 
until the current document is completed.

#6275: Cannot output a new XML document or change %XML until the current document is complete. Writer property.Copy the code

The StartDocument() method explicitly launches the document. Implicit start document as mentioned above, other methods, the write (), WriteDocType (), RootElement (), WriteComment () and WriteProcessingInstruction ().

Note: The methods described here are designed to allow specific units to be written to an XML document, but in some cases, more control may be required. An additional method, Write(), is provided in % xml.writer, which can be used to Write arbitrary strings anywhere in the output.

In addition, you can use the Reset() method to reinitialize the writer properties and output methods. This is useful if you have already generated one XML document and want to generate another without creating a new writer instance.

Error checking

Most methods of % xml.writer return state. You should check the status after each step and exit if appropriate.

Insert comment line

As mentioned earlier, insert the comment line using the WriteComment() method. You can use this method anywhere in the document. This method implicitly starts the XML document if it has not already been started.

The sample

/// w ##class(PHA.TEST.Xml).Write()
ClassMethod Write(a) As %Status
{
	s obj = ##class(Sample.Person%).OpenId(1)
    set writer= # #class(%XML.Writer%).New(a)set writer.Indent=1

    set status=writer.OutputToDevice()
    if $$$ISERR(status) {
        do $System.Status.DisplayError(status) 
        quit $$$ERROR($$$GeneralError, "Output target invalid")
    }

    set status=writer.RootObject(obj)
    if $$$ISERR(status) {
        do $System.Status.DisplayError(status) 
        quit $$$ERROR($$$GeneralError, "Error writing to root object")
    }
        
    quit status
}
Copy the code

Note that this method uses the OutputToDevice() method to direct output to the current device (the default target). This is not required, but is for demonstration purposes only.

Of course, the output depends on the class used, but it might look something like this:

DHC-APP>w ##class(PHA.TEST.Xml).Write()
<?xml version="1.0" encoding="UTF-8"? > <Employee> <Name>xiaoli</Name> <SSN>111-11-1111</SSN>
  <Title>test</Title>
  <Salary>2662</Salary>
</Employee>1
Copy the code

More information about indent options

As mentioned earlier, you can use the indent property of the writer to get output that contains additional newlines for better readability. There is no formal specification for this format. This section describes the rules used by % xml. Writer. If indentation equals 1:

  • Any element that contains only space characters is converted to an empty element.
  • Each element is placed on its own row.
  • If an element is a child of a previous element, the element is indented relative to the parent element. The indentation byIndentCharsProperty, which defaults to two Spaces.