AddToRecord (XmlDoc subroutine)

From m204wiki
Jump to navigation Jump to search

Add fields and/or fieldgroups to the current record (XmlDoc class)

This subroutine adds to the current record the fields and/or fieldgroups that are contained in the method XmlDoc object according to the structure created by the LoadFromRecord subroutine. AddToRecord must be contained within a “record loop” (for example, an FRN block), and must not be contained in a fieldgroup context.

Syntax

doc:AddToRecord[( [DisableFieldConstraints= boolean], [CopyIDs= boolean], - [IgnoreUndefinedFields= boolean])] Throws AddToRecordError

Syntax terms

doc The method object is an XmlDoc whose structure conforms to that created by the LoadFromRecord subroutine. "Structure of XmlDoc for AddToRecord" describes the structure in detail.
DisableFieldConstraints This name required argument is a Boolean value. If True, various field constraints (such as LENGTH-EQ, which is generally available as of Model 204 V7R5) are not checked when the fields are added to the record.

The default is False.

CopyIDs This name required argument is a Boolean value. If True, the fieldgroup IDs are copied, if possible, from the XmlDoc (stored as the "groupID" attribute of "fieldgroup" elements) to the record, and the "maxGroupID" attribute value of the "Record" element is also used as the maximum fieldgroup ID in the record, if possible.

On any given "fieldgroup" element, a "groupID" attribute may be 0, or missing, or not greater than the current maximum fieldgroup ID; in any of these cases, a new fieldgroup ID is generated for the fieldgroup occurrence.

If False, new fieldgroup IDs are generated.

The default is False.

IgnoreUndefinedFields This name required argument is a Boolean value. If True, then:
  • If a field in the XmlDoc is not defined in the current file, the field is ignored.
  • If a fieldgroup in the XmlDoc is not defined in the current file, the fieldgroup, and all descendants of the fieldgroup element, are ignored.

If False, any field or fieldgroup in the XmlDoc that is not defined in the current file throws an AddToRecordError exception.

The default is False.

Usage notes

  • The XmlDoc structure used by AddToRecord is also created by the NewFromRecord and ToXmlDoc functions.
  • Fields in the XmlDoc that are defined as CAT or CTO are ignored by AddToRecord.
  • Any fieldgroup update tracking fields in a fieldgroup are automatically set when that fieldgroup is created by AddToRecord, but no other updated tracking fields are automatically set by the updates performed by AddToRecord.
  • Any fields in the XmlDoc that are defined as update tracking fields are copied to the record. See "Removing update tracking fields from an XmlDoc" for an example of removing update tracking fields from AddToRecord's XmlDoc; generally this will not be needed, but it may be useful in certain situations.
  • This method was actually introduced in version 7.6 of the Sirius Mods, although until version 7.8 of the Sirius Mods an exception was thrown if the version of Model 204 in use was older than V7R2.

Examples

Copying a record from one file to another

The basic approach to copying a record from one file to another is:

In SRCFILE FRN %source %doc = %doc:NewFromRecord End For In TARGFILE Store Record End Store %targ = $CurRec In TARGFILE FRN %targ %doc:AddToRecord End For

Some additional examples of record copying are shown in "Copying from multiple source records".

Copying from multiple source records

Since the LoadFromRecord subroutine can extract from a record into a subtree of an Element node in an XmlDoc, you can use it, together with AddToRecord, to combine multiple source records into one target record.

As a simple example, you can put the fields from two records “side by side” into a target record:

FRN %x %doc = %doc:NewFromRecord End For %top = %doc:SelectSingleNode('*') FRN %y %top:LoadFromRecord End For Store Record End Store %rn = $CurRec FRN %rn %doc:AddToRecord End For

The XmlDoc that is input to AddToRecord would have a structure similar to the following:

<Record ...> <field ...> ... first field from record %x </field> ... <field ...> ... first field from record %y </field> ... </Record>

Of course, you could also accomplish this particular objective by using two XmlDoc objects:

FRN %x %doc1 = %doc1:NewFromRecord End For FRN %y %doc2 = %doc2:NewFromRecord End For Store Record End Store %targ = $CurRec FRN %targ %doc1:AddToRecord %doc2:AddToRecord End For

You can also use LoadFromRecord to modify the fieldgroup structure within a record (using V7R5 of Model 204). For example, you could take the “outer” fields of one record and move them to be fieldgroup members in the target record:

In SRCFILE FRN %x %doc = %doc:NewFromRecord End For %fg = %doc:SelectSingleNode('*/fieldgroup[@name="GRP"]') In SRCFILE FRN %y %fg:LoadFromRecord End For In TARGFILE Store Record End Store %rn = $CurRec In TARGFILE FRN %rn %doc:AddToRecord PAI End For

The use of a separate source and target file above (which in general is a typical usage of the record copying methods) is more or less required here, because the fields in SRCFILE are defined as outer fields, but in TARGFILE they are defined as members of fieldgroup GRP (or they would need to be “FIELDGROUP *” fields). So, for example, definitions for SRCFILE might include:

DEFINE FIELD FOO DEFINE FIELDGROUP GRP

and definitions for TARGFILE might include:

DEFINE FIELDGROUP GRP DEFINE FIELD FOO WITH FIELDGROUP GRP

And the XmlDoc that is input to the above AddToRecord subroutine may look like:

<Record ...> <fieldgroup name="GRP" ...> <field name="FOO"> value of foo </field> </fieldgroup> </Record>

And the corresponding output of the above PAI would be:

    \GRP = 1
     FOO = value of foo
    /GRP = 1

Removing update tracking fields from an XmlDoc

In the simple situation, the record copying operation provided by LoadFromRecord and AddToRecord produces a copy of all of the record's fields, including update tracking fields (such as UPDATE-TIME fields). However, in some circumstances, you may not want some of the update tracking fields to be propagated by AddToRecord. This can readily be accomplished by using DeleteSubtree to remove the tracking fields you want to suppress (of course, DeleteSubtree could be used to remove other fields and/or fieldgroups, as well).

Consider an example in which AddToRecord is being used to add fields to a record that already has fields stored in it:

IN ?&SOURCE DEFINE FIELD REC.UPD WITH UPDATE-TIME IN ?&SOURCE DEFINE FIELD FOO IN ?&TARGET DEFINE FIELD REC.UPD WITH UPDATE-TIME IN ?&TARGET DEFINE FIELD FOO ... Do the following on Monday: In ?&SOURCE Store Record FOO = 'Record stored on Monday' End Store %rn = $CurRec In ?&SOURCE FRN %rn %doc = %doc:NewFromRecord End For %serial = %doc:Serial In LOG Store Record RECORD.XML = %serial End Store ... Do the following on Tuesday: In LOG For 1 Record %doc:LoadXml(RECORD.XML) End For In ?&TARGET Store Record FOO = 'Record stored on Tuesday' End Store %rn = $CurRec In ?&TARGET FRN %rn %doc:AddToRecord End For

In this scenario, GRP.UPD would be set to Monday, overlaying the more recent (and probably desired) value which was set on Tuesday. To prevent this overlay, you can insert the following statement after %doc:LoadXml(RECORD.XML):

%doc:DeleteSubtree('*/fieldgroup/field[@name="GRP.UPD"]')

Structure of XmlDoc for AddToRecord

The method object of the AddToRecord subroutine is an XmlDoc whose structure conforms to that created by the LoadFromRecord subroutine. You can also create an XmlDoc to be used for AddToRecord; the rules for the XmlDoc are described here.

The outline of the XmlDoc is:

<Record [version="1"] [codepage="--codepage name--"] [maxGroupID="--fieldgrouop counter--"] [file="---file name---"] [number="---record number---"]> <field name="---field name---"> ---field value--- </field> <field name="---field name---" encoding="base64"> ---base64 encoded field value--- </field> <fieldgroup name="---fieldgroup name---" [groupID="---fieldgroup ID---"]> <field ... <fieldgroup ... ... </fieldgroup> ... </Record>


The requirements for the XmlDoc are:

Comments and PIs Comment and PI nodes are allowed anywhere in the XmlDoc.
Elements in non-null namespaces In addition to the elements mentioned below for the various elements contained in the XmlDoc, the Record and fieldgroup elements may have any additional child elements that are in any non-null namespace. These additional elements are ignored. For example, the following is a valid AddToRecord XmlDoc representing an empty record:

<Record> <foo:bar xmlns:foo="u:xyz"/> </Record>

However, the only null-namespace child elements permitted of elements in the null namespace are those described for each element type below. For example, the following is an invalid AddToRecord XmlDoc:

<Record> <foo/> </Record>

Attributes in non-null namespaces In addition to the attributes mentioned below for the various elements contained in the XmlDoc, those elements may contain any additional attributes that are in any non-null namespace. These additional attributes are ignored. For example, the following is a valid AddToRecord XmlDoc representing an empty record:

<Record foo:bar="x" xmlns:foo="u:xyz"/>

Of course, elements in non-null namespaces may have any attributes. The only attributes permitted in elements in the null namespace are those described below. For example, the following is an invalid AddToRecord XmlDoc:

<Record foo="x"/>

Record element The top level element of the XmlDoc must be named "Record"; all of its attributes are optional and are described below. The element children of the Record element are optional; they may be:
  • field
  • fieldgroup

The Record element may not have a Text child node.

version attribute of Record element If present, this attribute must have the numeric value "1".
codepage If present, this attribute contains the name of the codepage whose base translation tables are used for converting the Unicode field names and field values (if not base 64 encoded) in the XmlDoc to EBCDIC.
maxGroupID attribute of Record element If present, this attribute contains the value of the maximum fieldgroup ID to be set (if greater than or equal to all of the fieldgroup IDs stored in the record) in the added record, if the CopyIDs=True argument is provided. This must be a non-negative integer value.
file attribute of Record element This attribute is ignored.
number attribute of Record element If present, this must either be "-1", signifying that the input record number is not known, or it must be a non-negative integer value. As noted in "AddToRecord constraint on 'number' attribute", this represents a compatibility issue.
field element The field element may be a child of either the Record or fieldgroup element; it contains a field occurrence. It must have a name attribute, and may have an encoding attribute. It may have one Text child, which is either the value of the occurrence or, if the encoding attribute is present (with the value base64), is the base64 encoded value of the occurrence.
name attribute of field element This attribute is required; it is the name of the field.
encoding attribute of field element This attribute is optional; if present, it must have the value base64, indicating that the Text child of the field element is the base64 encoding of the field value.
fieldgroup element The fieldgroup element may be a child of either the Record or fieldgroup element; it is the top of a subtree representing a fieldgroup occurrence. The element children of the fieldgroup element are optional; they may be:
  • field
  • fieldgroup

The fieldgroup element may not have a Text child node. It must have a name attribute, and may have a groupID attribute.

name attribute of fieldgroup element This attribute is required; it is the name of the fieldgroup.
groupID attribute of fieldgroup element If present, this attribute contains the value of the fieldgroup ID to be set (if possible) for the fieldgroup occurrence in the added record, if the CopyIDs=True argument is provided.