Skip to main content
Previous section   Next section

Controlling Transformations of Values

This topic discusses how values are transformed as you export objects to XML and import XML into objects, and it discusses your options for controlling those transformations.

The XML examples in this topic are in literal format.

The following topic discusses null values and missing values.

Class and Property Parameters Discussed in This Topic
  • ESCAPE
  • CONTENT
  • XMLTIMEZONE
  • DISPLAYLIST
  • VALUELIST
  • XMLDEFAULTVALUE
  • XMLLISTPARAMETER
  • XMLSTREAMMODE

Introduction

An XML-enabled object typically includes properties defined by Caché data types. Each data type class defines the LogicalToXSD() and XSDToLogical() methods. Whenever XML output is requested for the object, the Caché XML tools automatically call the LogicalToXSD() method for each property, to convert the data to the appropriate format for use in XML. Similarly, whenever an XML document is used as input, the Caché XML tools call the XSDToLogical() method to convert the data into the correct format for Caché.

For example, in the %Binary data type class, the LogicalToXSD() method converts the outbound value using the $SYSTEM.Encryption.Base64Encode() method. Similarly, the XSDToLogical() method converts the inbound value using the $SYSTEM.Encryption.Base64Decode() method.

A Caché class can also include stream-valued properties, but the stream classes do not define the LogicalToXSD() and XSDToLogical() methods. Instead, the XML tools treat stream classes specially when they are used as properties of an XML-enabled class. Specifically:

  • Character streams are treated in the same way as strings. By default, no changes are made apart from the changes that are necessary due to the presence of XML special characters, as described in the next section.

  • When Caché exports to XML, it converts binary stream properties to strings with base–64 encoding (that is, it encodes the data in that way and then exports it). When Caché imports from XML, it does the reverse.

When you use XML-enabled objects, it is sometimes necessary to consider the special cases of values that cannot be directly projected to XML or values that you want to transform for other reasons. The rest of this topic discusses these cases.

Handling Special XML Characters

Depending on the context, Caché XML support escapes the ampersand character (&) and certain other characters, when it finds those characters within a property of type string or character stream.

Note:

The ESCAPE property parameter controls which characters are recognized as special. This parameter is either "XML" (the default) or "HTML" (not discussed in this book). In the examples in this book, ESCAPE is "XML".

For these special characters, you can control how the escaping is performed by setting the CONTENT property parameter. The details are different for literal and encoded formats, as follows:

Form of Escaping for Literal and SOAP-encoded Formats
Value of CONTENT (Case-insensitive) XML Document in Literal Format XML Document in SOAP-encoded Format
"STRING" (the default) CData CData
"ESCAPE" XML entity XML entity
"ESCAPE-C14N" XML entity* XML entity*
"MIXED" No escaping is done CData

*For "ESCAPE-C14N", the escaping is done in accordance with the XML Canonicalization standard. The main difference is that a carriage return is escaped as 

Examples

Consider the following class:

Class ResearchXForms.CONTENT Extends (%RegisteredObject, %XML.Adaptor)
{

Parameter XMLNAME = "Demo";

Property String1 As %String;

Property String2 As %String(CONTENT = "STRING");

Property String3 As %String(CONTENT = "ESCAPE");

Property String4 As %String(CONTENT = "MIXED");

}
Copy code to clipboard

String2 and String1 are always treated in the same way, because String2 uses the default value for CONTENT.

Literal XML output for this class might look like the following:

<?xml version="1.0" encoding="UTF-8"?>
<Demo>
  <String1><![CDATA[value 1 & value 2]]></String1>
  <String2><![CDATA[value 1 & value 2]]></String2>
  <String3>value 1 &amp; value 2</String3>
  <String4>value 1 & value 2</String4>
</Demo>
Copy code to clipboard

SOAP-encoded XML output would be as follows instead:

<?xml version="1.0" encoding="UTF-8"?>
<CONTENT xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <String1><![CDATA[value 1 & value 2]]></String1>
  <String2><![CDATA[value 1 & value 2]]></String2>
  <String3>value 1 &amp; value 2</String3>
  <String4><![CDATA[value 1 & value 2]]></String4>
</CONTENT>
Copy code to clipboard

Alternative Way to Prevent the Escaping

There is another way to prevent the escaping of special XML characters. You can define the property as one of the special XML types: %XML.String, %XML.FileCharacterStream, or %XML.GlobalCharacterStream. For these data type classes, CONTENT is "MIXED".

Note that your application is responsible for ensuring that the property value is valid for the scenario in which it will be used; the %XML.String and other classes do not provide this validation.

Handling the UTC Time Zone Indicator

For XML-enabled classes, you can specify whether to use the UTC time zone indicator when importing from XML documents. Similarly, you can specify whether to include the UTC time zone indicator on export.

To do so, specify the XMLTIMEZONE parameter. Use one of the following values:

  • "UTC" — In this case, when you import elements with xsd:time or xsd:dateTime, the data is converted to UTC time. This is the default behavior.

    In compliance with the XML Schema specification, Caché XML support treats the time zone indicator as a pure duration and ignores any named time zones such as EDT.

  • "IGNORE" — In this case, the UTC time zone indicator is ignored when you import elements with xsd:time or xsd:dateTime.

On export, UTC time is always used. The XMLTIMEZONE parameter controls the UTC zone indicator is included.

Consider the following class:

Class ResearchXForms.UTC Extends (%Persistent, %XML.Adaptor)
{

Parameter XMLNAME = "Demo";

Property Time1 As %Time;

Property Time2 As %Time(XMLTIMEZONE = "IGNORE");

Property TimeStamp1 As %TimeStamp;

Property TimeStamp2 As %TimeStamp(XMLTIMEZONE = "IGNORE");

}
Copy code to clipboard

XML output for this class might be as follows:

<?xml version="1.0" encoding="UTF-8"?>
<Demo>
  <Time1>17:52:06Z</Time1>
  <Time2>17:52:06</Time2>
  <TimeStamp1>1976-02-18T17:52:06Z</TimeStamp1>
  <TimeStamp2>1976-02-18T17:52:06</TimeStamp2>
</Demo>
Copy code to clipboard

Projecting the Value in DISPLAYLIST

For properties of type %String (or any subclass), the XML projection can use the DISPLAYLIST parameter.

Simple properties can specify the DISPLAYLIST and VALUELIST parameters. The VALUELIST parameter specifies a list of possible values for the property; this defines an enumerated property . Often you also specify the DISPLAYLIST parameter, which specifies the corresponding values to display.

By default, the XML projection uses the value contained in the object, which is one of the values specified by VALUELIST. For properties of type %String, the XMLLISTPARAMETER parameter is meant to indicate which parameter contains the list of alternative values to use in the projection. Typically, you set this equal to "DISPLAYLIST". For example, consider the following data type class:

Class xmldisplaylist.MyEnumString Extends %String
{

Parameter VALUELIST = ",a,b,c";

Parameter DISPLAYLIST = ",apples,bananas,chocolate";

Parameter XMLLISTPARAMETER = "DISPLAYLIST";

}
Copy code to clipboard

Also consider the following class, which uses the preceding data type class:

Class xmldisplaylist.Demo Extends (%RegisteredObject, %XML.Adaptor)
{

Property Property1 As MyEnumString;

Property Property2 As MyEnumString(DISPLAYLIST = ",red,green,blue", VALUELIST = ",r,g,b");

}
Copy code to clipboard

The following shows an example of the XML representation of an instance of this class:

<Demo>
  <Property1>chocolate</Property1>
  <Property2>red</Property2>
</Demo>
Copy code to clipboard

In contrast, if the data type class did not specify the XMLLISTPARAMETER parameter, the XML representation would be as follows:

<Demo>
  <Property1>c</Property1>
  <Property2>r</Property2>
</Demo>
Copy code to clipboard

Controlling the Line Endings of Imported Stream Properties

For each property that is a character stream, you can control the line endings in the stream when you import from XML. To do so, you set the XMLSTREAMMODE property parameter, which can have either of the following values (not case-sensitive):

  • If XMLSTREAMMODE equals "block" (the default), the normalized XML data is copied unchanged to the stream. The LineTerminator property of the stream is set to $CHAR(10), which makes the import compatible with any traditional newline sequence ($CHAR(10), $CHAR(13), $CHAR(13,10)).

  • If XMLSTREAMMODE equals "line", the XML data is broken into lines separated by the character given by the LineTerminator property of the stream; see %Library.AbstractStream.

For example, suppose that we have the following data:

...
<Stream1>
<![CDATA[this is a line
this is another line
this is another line
]]>
</Stream1>
...
Copy code to clipboard

We import this data into an object that has a Stream1 property of type %Stream.GlobalCharacter. By default, XMLSTREAMMODE is "block" for the property. After we import data, this property will contain the following data:

this is a line
              this is another line
                                  this is another line
Copy code to clipboard

If we set XMLSTREAMMODE equal to "line" for this property, and reimported the data, this property would contain the following data:

this is a line
this is another line
this is another line
Copy code to clipboard

In this case, the line endings are determined by the LineTerminator property of the stream class. This property equals $char(13,10) for %Stream.GlobalCharacter.

Specifying a Default Date/Time Value

For the %TimeStamp and %DateTime data type classes, the XMLDEFAULTVALUE parameter specifies the value to use if the date fails validity check by $zdatetimeh. By default, in such a case, a null string is used, and this results in an error when you import data via XMLImport(). Specify a valid value for the class.

For example, for %TimeStamp, and %DateTime, specify a date in YYYY-MM-DD HH:MM:SS.nnnnnnnnn format, starting with any year after 1841. For example: 1841-01-1 00:00:00

Projecting Nonprinting Characters to XML

XML does not permit nonprinting characters, specifically characters below ASCII 32 (except for carriage return, line feed, and tab).

If you need to project a property to XML and that property contains any of these nonprinting characters, that property must be of type %Binary or %xsd.base64Binary (which is equivalent). This value is automatically converted to base–64 encoding on export to XML (or automatically converted from base–64 encoding on import).