Examples

Data exchange features

General information

Data exchange features ‑ are a set of 1C:Enterprise tools for arranging data exchange between various infobases, as well as between infobases and external software systems. Data exchange features can be divided into two levels:

  • universal data exchange features,
  • distributed infobases.

Universal data exchange features

Universal data exchange features can be used both together and separately, in various combinations, for arranging the data exchange from the 1C:Enterprise infobases with various software systems. Other 1C:Enterprise infobases can act as software systems in which the exchange is arranged with. In this case, the infobases exchanging among themselves may, in general, have different configurations.

In addition, universal data exchange features can be used to arrange an exchange with software that is not based on the 1C:Enterprise. The following factors contribute to this:

  • the data exchange format is based on the XML language, which is currently the generally accepted tool of presenting data;
  • due to their modular arrangement and high flexibility, data exchange tools can be used to arrange various data exchange schemes;
  • protocols provided by data exchange features are simple and can be replicated in external software systems.

Distributed infobases

The distributed Infobase is a hierarchical structure consisting of separate infobases of the 1C:Enterprise ‑ the nodes of the distributed Infobase, between which data exchange is arranged in order to synchronize the configuration and data.

Distributed Infobase management features are based on universal data exchange features but contain some additional functions that are not available through universal features.

The main difference between distributed infobases and universal data exchange features is that universal data exchange features allow building fairly arbitrary data exchange schemes, while distributed infobases have a narrower specialization and also transfer configuration changes to subordinate nodes.

Universal data exchange features

General information

The universal data exchange features may include:

  • XML documents reading and writing tools,
  • XML serialization,
  • exchange plans.

XML documents reading and writing tools

The participants of the data exchange are supposed to exchange messages in XML format. Thus, the XML documents reading and writing tools are the basic level of data exchange.

XML documents reading and writing tools ensure that XML documents are handled in the most general way. This set of tools does not define the methods for presenting data of the 1C:Enterprise in XML format.

The XML documents reading and writing tools provided by 1C:Enterprise include: ReadXML, WriteXML and XSLTransform. The platform also supports handling XML data in the FastInfoset format, for which purpose the FastInfosetWriter and FastInfosetReader objects exist.

XML serialization

The main task of XML serialization ‑ is to support 1C:Enterprise data objects reading/writing of to/from XML.

Basic tools for reading and writing XML documents do not provide a sufficient basis for solving this problem. They do not define the presentation of the 1C:Enterprise data in XML and do not provide tools for reading/writing data objects to/from XML in the accepted format as a whole.

Data representation in XML serialization

Ultimately, each data object of the 1C:Enterprise is represented as an XML element containing the value of the data object.

In terms of representation in XML, the value types are divided into simple and complex.

Simple data types include the types in which values are represented by the XML serialization subsystem as XML elements with text content only.

The values of complex types are represented as XML elements containing nested elements.

An XML data type is assigned to each of 1C:Enterprise data types, the values of which can be represented in XML.

Each XML data type is characterized by the type name and the namespace which the type belongs to.

The XML data type can be as follows:

  • one of the types defined in the XML Schema Part 2 document: Datatypes of W3C consortium (namespace ‑ http://www.w3.org/2001/XMLSchema);
  • predefined type of 1C:Enterprise (namespace ‑ http://v8.1c.ru/data);
  • type derived from the configuration metadata of the 1C:Enterprise (does not belong to any namespace).

The XML data type can be specified explicitly in the representation of a data object in XML. To specify an XML data type, the XML element containing the value representation must contain a type attribute that belongs to the http://www.w3.org/2001/XMLSchema-instance namespace, which value contains the XML data type.

Another way to specify the XML data type is the name of the XML root element containing the value representation. The name of the root element representing the data object is not strictly specified and can be arbitrary. However, if the name of the root element is not specified when writing a value in XML, it will be set according to the type of the value being written. When reading data from XML, the value type, if it is not specified in the type attribute, can be set based on the root element name.

When considering examples of representing different values in XML and in further discussion, we will proceed from the assumption that the following namespace matches are defined:

xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema instance"
xmlns:v8="http://v8.1c.ru/data"

Representation of simple type values in XML

The simple types it terms of representation in XML are the following 1C:Enterprise types:

  • Number;
  • String;
  • Date;
  • Boolean;
  • BinaryData;
  • NULL;
  • UUID;
  • ValueStorage;
  • all references to database objects;
  • references to enumerations defined in metadata.

Number

Description:

Number type matches the XML decimal data type belonging to the http://www.w3.org/2001/XMLSchema namespace.

The rules for representing values of this type are defined in the XML Schema Part 2 document: Datatypes.

Example:

<!-- Root element name is not explicitly specified -->
<decimal>45684.087</decimal>
<!-- XML root element name is not explicitly specified -->
<Amount>523</Amount>
<!-- XML data type is explicitly specified -->
<Data xsi:type="xsd:decimal">64793.01</Data>

Description:

The String type corresponds to the string data type from the http://www.w3.org/2001/XMLSchema namespace. The string is written in XML as is.

Example:

<!-- Root element name is not explicitly specified -->
<string>This is string</string>
<!-- XML root element name is not explicitly specified -->
<Name>Ivanov</Name>
<!-- XML data type is explicitly specified -->
<Data xsi:type="xsd:string">This is string</Data>

Description:

Date type values are represented as YYYY-MM-DDTHH:MM:SS, where:

  • YYYY ‑ year, represented by four digits;
  • MM ‑ month, represented by two digits;
  • DD ‑ day of a month represented by two digits;
  • T ‑ Latin letter T;
  • HH ‑ Hour of the day;
  • MM ‑ minute;
  • SS ‑ second.

This date format is defined as valid in XML Schema Part 2 document: Datatypes.

Example:

<!-- Root element name is not explicitly specified -->
<dateTime>2008 11 21T12:00:00</dateTime>
<!-- XML root element name is not explicitly specified -->
<Started>2001 10 30T19:00:00</Started>
<!-- XML data type is explicitly specified -->
<Data xsi:type="xsd:dateTime">1980 08 25T10:00:00</Data>

Description:

The Boolean type corresponds to the boolean data type from the http://www.w3.org/2001/XMLSchema namespace.

False value is represented by the false string, and True value ‑ is represented by the true string. This format is provided in XML Schema Part 2 document: Datatypes.

Example:

<!-- Root element name is not explicitly specified -->
<boolean>false</boolean>
<!-- XML root element name is not explicitly specified -->
<Posted>true</Posted>
<!-- XML data type is explicitly specified -->
<Data xsi:type="xsd:boolean">true</Data>

Description:

BinaryData type matches the XML base64Binary data type belonging to the namespace http://www.w3.org/2001/XMLSchema.

The values of this type are specified as binary data encoded by using the Base64 algorithm described in RFC 2045 (http://tools.ietf.org/html/rfc2045.html).

Example:

<!-- Root element name is not explicitly specified -->
<base64Binary>YWJjZGVm</base64Binary>
<!-- XML root element name is not explicitly specified -->
<BinaryData>YWJjZGVm</BinaryData>
<!-- XML data type is explicitly specified -->
<Data xsi:type="xsd:base64Binary">YWJjZGVm</Data>

Description:

Типу NULL type matches the XML Null data type belonging to the namespace http://v8.1c.ru/data. This type has a single value that is manifested by an empty string.

Example:

<!-- Root element name is not explicitly specified -->
<v8:Null/>
<!-- XML root element name is not explicitly specified -->
<Selected/>
<!-- XML data type is explicitly specified -->
<Data xsi:type="v8:Null"/>

Description:

UUID type matches the XML UUID data type belonging to the namespace http://v8.1c.ru/data.

The values of this data type are represented in XML in compliance with common practice and standards (ISO-11578, DCE 1.1: Remote Procedure Call ‑ Universal Unique Identifier).

Example:

<!-- Root element name is not explicitly specified -->
<v8:UUID>3294be0f c039 41a9 bd65 596da0dcfe68</v8:UUID>
<!-- XML root element name is not explicitly specified -->
<Id>da035e32 3f7a 4d87 accf7db8cb4b</Id>
<!-- XML data type is explicitly specified -->
<Data xsi:type="v8:UUID">08839b0b 5ec3 4a53 a9f5 173312316919</Data>

Description:

ValueStorage type matches the XMLValueStorage data type belonging to the namespace http://v8.1c.ru/data.

Values of this type are specified in XML as ValueStorage data saved in a file, and then encoded by using the Base64 algorithm.

Example:

<!-- Root element name is not explicitly specified -->
<v8:ValueStorage>AQEOAAAAAAAAAO+7v3siUyIsIjHQoSJ9</v8:ValueStorage>
<!-- XML root element name is not explicitly specified -->
<Data>AQEOAAAAAAAAAO+7v3siUyIsIjHQoSJ9</Data>
<!-- XML data type is explicitly specified -->
<Data xsi:type="v8:ValueStorage">AQEOAAAAAAAAAO+7v3siUyIsIjHQoSJ9</Data>

Description:

Each type of link to database objects matches its own XML data type. The name of the XML data type for links to database objects matches the English name of the link value type of the 1C:Enterprise system.

So, for example, for the Currencies catalog, the English name of the link type will look like the CatalogRef.Currencies. The corresponding XML data type will be spelled in the same fashion.

XML data types for links to database objects do not belong to any namespace.

Link values are specified in XML as values of the UUID type acquired from links.

Example:

<!-- Root element name is not explicitly specified -->
<CatalogRef.Banks>911b5b8b 11f5 4993 9673 2c9a7a8995d5</CatalogRef.Banks >
<!-- XML root element name is not explicitly specified -->
<Ref>911b5b8b 11f5 4993 9673 2c9a7a8995d5</Ref>
<!-- XML data type is explicitly specified -->
<Data xsi:type="CatalogRef.Banks">
       911b5b8b 11f5 4993 9673 2c9a7a8995d5</Data>

Description:

Each type of link to enumeration values specified in the application matches its own XML data type. The XML data type name for the links to enumeration values corresponds to the English language type name of the 1C:Enterprise system.

Thus, for example, for the AddressTypes enumeration, an English name of this value link type will be EnumRef.AddressTypes. The corresponding XML data type will be spelled in the same fashion.

The XML data type name for the links to enumeration values doesn't belong to any namespace. In XML, links to enumeration values are represented as the name of the corresponding enumeration value.

Example:

<!-- Root element name is not explicitly specified -->
<EnumRef.AddressTypes>Registered</EnumRef.AddressTypes>
<!-- XML root element name is not explicitly specified -->
<Ref>Registered</Ref>
<!-- XML data type is explicitly specified -->
<Data xsi:type="EnumRef.AddressTypes">Business</Data>

Representation of Compound Data Types in XML

Compound data types, the values of which can be declared in XML, include the following types of the 1C:Enterprise system:

  • Type;
  • TypeDescription;
  • ConstantValueManager.<Constant name>;
  • all database objects;
  • Record sets of registers, sequences, recalculations;
  • ObjectDeletion.

Type

Description:

TheType type matches the XML Type data type belonging to the namespace http://v8.1c.ru/data. The XML element representing the value of this type contains the text with the name of the XML type that matches the “1C:Enterprise” system data type.

On the face of it, the Type type should be referred not to the compound data types but to simple ones, since the element representing the value of this type does not contain nested elements. However, it is not the case. Indeed, it doesn't contain nested elements. Yet, the text of the element containing the name of the XML data type contains a namespace prefix of the type that must be defined in an element or one of its parent elements, which makes the text of such element not quite self-contained. That is why the given type does not qualify as a simple one.

Example:

<!-- Root element name is not explicitly specified -->
<v8:Type>v8:ValueStorage</v8:Type>
<!-- XML root element name is not explicitly specified -->
<Tp>xsd:string</Tp>
<!-- XML data type is explicitly specified -->
<Data xsi:type="v8:Type">v8:ValueStorage<Data>

Description:

TypeDescription type matches the XML TypeDescription data type belonging to the namespace http://v8.1c.ru/data. The root element that represents the value of the TypeDescription type includes a series of nested elements, each of them containing a certain part of the type description.

The nested Types element from the namespace http://v8.1c.ru/data contains representations of individual types included in the type description. The NumberQualifiers element belonging to the namespace http://v8.1c.ru/data contains numeric value qualifiers. StringQualifiers and DateQualifiers elements belonging to the same namespace contain a string and date qualifiers, respectively.

Example:

<v8:TypeDescription>
 <v8:Types>
   <v8:Type>v8:UUID</v8:Type>
   <v8:Type>CatalogRef.Banks</v8:Type>
   <v8:Type>xsd:boolean</v8:Type>
   <v8:Type>xsd:decimal</v8:Type>
 </v8:Types>
 <v8:NumberQualifiers>
   <v8:Digits>10</v8:Digits>
   <v8:FractionDigits>2</v8:FractionDigits>
   <v8:AllowedSign>Any</v8:AllowedSign>
 </v8:NumberQualifiers>
 <v8:StringQualifiers>
   <v8:Length>30</v8:Length>
   <v8:AllowedLength>Variable</v8:AllowedLength>
 </v8:StringQualifiers>
 <v8:DateQualifiers>
   <v8:DateFractions>Date</v8:DateFractions>
 </v8:DateQualifiers>
</v8:TypeDescription>

Description:

Each of the ConstantValueManager.<Constant name> type matches the XML the XML ConstantValueManager.<Constant name> data type that does not belong to any namespace.

Example:

<ConstantValueManager.OrganizationName>
<Value>ООО "Moebius"</Value>
</ConstantValueManager.OrganizationName>

Description:

Database objects are represented in XML as a set of values of attributes and tabular sections. The name of the XML data type that matches the corresponding database object is defined as the English name of the value type of the 1C:Enterprise system. XML data types for database objects do not belong to any namespace. The composition of XML elements nested in the root element is determined by a particular object type, as well as by the composition of its attributes and table sections.

Each of the attributes is represented by an XML element whose name matches the attribute name. If an attribute value type cannot be uniquely identified from the metadata, then the XML element representing the attribute contains the xsi: type attribute that indicates the type of the XML value.

Each of the tabular sections is represented by an XML element whose name matches the name of the tabular section.

Each row in a tabular section is represented by an XML element named Row. Attributes of the tabular section are represented by XML elements nested in the Row element.

Example:

Representation of Object of DocumentObject.CustomerOrder type in XML

<DocumentObject.CustomerOrder>
<Ref>8d106783 9726 11d7 9334 0050ba8480bd</Ref>
<DeletionMark>false</DeletionMark>
<Date>2008 04 15T12:00:00</Date>
<Number>00000006</Number>
<Posted>true</Posted>
<CompanyDivision>
317f130d 5a08 11d7 9324 0050ba8480bd</Company Division>
<StructuralUnit xsi:type="CatalogRef.CompanyCashRegisters">
317f12f4 5a08 11d7 9324 0050ba8480bd</StructuralUnit >
<CounterParty>12952ac7 5a08 11d7 9324 0050ba8480bd</CounterParty>
<CounterPartyLegalPrivateEntities xsi:type="CatalogRef.LegalEntities">
0aadfe81 5a08 11d7 9324 0050ba8480bd</CounterPartyLegalPrivateEntities>
<DocumentCurrency>
029156b4 5a08 11d7 9324 0050ba8480bd</DocumentCurrency>
<DocumentCurrencyRate>1</DocumentCurrencyRate>
<ApplyVAT>true</ApplyVAT>
<ApplySalesTax>false</ApplySalesTax>
<SumIncludesVAT>false</SumIncludesVAT>
<SumIncludesSalesTax>false</SumIncludesSalesTax>
<Comment/>
<DocumentSum>44077.14</DocumentSum>
<TransactionType>Invoice</TransactionType>
<OffsetsContract>
b0401f23 6e84 11d7 932c 0050ba8480bd</OffsetsContract>
<CompanyWarehouse>
317f1317 5a08 11d7 9324 0050ba8480bd</CompanyWarehouse>
<PriceType>317f1311 5a08 11d7 9324 0050ba8480bd</PriceType>
<PaymentDate>2008 04 15T00:00:00</PaymentDate>
<AutoProvisioning>false</AutoProvisioning>
<AutoPlacement>false</AutoPlacement>
<OffsetsCurrencyRate>33.4209</OffsetsCurrencyRate>
<DiscountSurchargeType>
00000000 0000 0000 0000 000000000000</DiscountSurchargeType>
<Organization>317f1308 5a08 11d7 9324 0050ba8480bd</Organization>
<ShipmentDate>2008 04 15T00:00:00</ShipmentDate>
<PersonInCharge>
4ff40e0b 5ac5 11d7 9325 0050ba8480bd</PersonInCharge>
<DocumentFactor>1</DocumentFactor>
<OffsetsFactor>1</OffsetsFactor>
<Items>
<Row>
<Products>
297c6534 5a08 11d7 9324 0050ba8480bd</Products>
<MeasurementUnit>
297c6535 5a08 11d7 9324 0050ba8480bd
</MeasurementUnit>
<Price>4537.56</Price>
<Sum>13612.68</Sum>
<VATRate>VAT20</VATRate>
<VATSum>2722.54</VATSum>
<SalesTaxRate>1ac73736 5a08 11d7 9324 0050ba8480bd</SalesTaxRate>
<SalesTaxSum>0</SalesTaxSum>
<ProductSpecification>
00000000 0000 0000 0000 000000000000
</ProductSpecification>
<Placement xsi:nil="true"/>
<Factor>1</Factor>
<Quantity>3</Quantity>
<DiscountSurchargePercent>0</DiscountSurchargePercent>
</Row>
<Row>
<Products>
317f12d8 5a08 11d7 9324 0050ba8480bd</Products>
<MeasurementUnit>
317f12d9 5a08 11d7 9324 0050ba8480bd
</MeasurementUnit>
<Price>4915.55</Price>
<Sum>19662.2</Sum>
<VATRate>VAT20</VATRate>
<VATSum>3932.44</VATSum>
<SalesTaxRate>1ac73736 5a08 11d7 9324 0050ba8480bd</SalesTaxRate>
<SalesTaxSum>0</SalesTaxSum>
<ProductSpecification>
00000000 0000 0000 0000 000000000000
</ProductSpecification>
<Placement xsi:nil="true"/>
<Factor>1</Factor>
<Number>4</Number>
<DiscountSurchargePercent>0</DiscountSurchargePercent>
</Row>
</Items>
<Returnables/>
</DocumentObject.CustomerOrder>

NOTE. In the example above, as well as in other examples of this chapter, there are long lines (for example, <MeasurementUnit> 317f12d9-5a08-11d7-9324-0050ba8480bd </MeasurementUnit>). Due to the limitation imposed by the book formatting, such lines are hyphenated and split with line breaks. In code, such lines are put in the module in one line.


Record Set

Description:

The XML representation of a recordset includes the filter the recordset was filtered by and the records themselves that the resulting selection is composed of. The filtering values are represented in a nested XML element named Filter that does not belong to any namespace. Whereas all the records that make up a recordset are located in a nested element named Records that does not belong to any namespace, either. Records are represented by XML elements named Record, nested in a Records element. Likewise, the element name Record does not belong to any namespace.

Example:

Representation of the Company Product Balance accumulation register record set in XML:

<AccumulationRegisterRecordSet.CompanyProductBalance>
<Filter>
<Recorder xsi:type="DocumentRef.ProductSales">
1725f36e 6f35 11d7 932d 0050ba8480bd</Recorder>
</Filter>
<Records>
<Record>
<Recorder xsi:type="DocumentRef.ProductSales">
1725f36e 6f35 11d7 932d 0050ba8480bd</Recorder>
<Period>2008 04 13T17:45:39</Period>
<MovementType>Expense</MovementType>
<Active>true</Active>
<Products>
297c6556 5a08 11d7 9324 0050ba8480bd</Products>
<CompanyWarehouse>
317f1317 5a08 11d7 9324 0050ba8480bd</CompanyWarehouse>
<Order xsi:nil="true"/>
<RetailPrice>0</RetailPrice>
<ProductSpecification>
00000000 0000 0000 0000 000000000000
</ProductSpecification>
<Number>2</Number>
<CompanyDivision>
317f130d 5a08 11d7 9324 0050ba8480bd
</CompanyDivision>
</Record>
<Record>
<Recorder xsi:type="DocumentRef.ProductSales">
1725f36e 6f35 11d7 932d 0050ba8480bd</Recorder>
<Period>2008 04 13T17:45:39</Period>
<MovementType>Expense</MovementType>
<Active>true</Active>
<Products>
297c6558 5a08 11d7 9324 0050ba8480bd</Products>
<CompanyWarehouse>
317f1317 5a08 11d7 9324 0050ba8480bd</CompanyWarehouse>
<Order xsi:nil="true"/>
<RetailPrice>0</RetailPrice>
<ProductSpecification>
ac47d77e 5ec7 11d7 9329 0050ba8480bd
</ProductSpecification>
<Number>2</Number>
<CompanyDivision>
317f130d 5a08 11d7 9324 0050ba8480bd
</CompanyDivision>
</Record>
</Records>
</AccumulationRegisterRecordSet.CompanyProductBalance>

Description:

The ObjectDeletion type matches the XML ObjectDeletion data type belonging to the http://v8.1c.ru/data namespace. The root element of the XML representation of the ObjectDeletion type value contains one nested element named Ref belonging to the http://v8.1c.ru/data namespace that contains the representation of a link to the database object.

Example:

Representation of Object of ObjectDeletion Type in XML:

<v8:ObjectDeletion xmlns="http://v8.1c.ru/data">
<v8:Ref xsi:type="CatalogRef.Banks">
60c5cec3 7f6f 4ec3 9620 e757fe3614ca</v8:Ref>
</v8:ObjectDeletion>

Access to XML Serialization Tools from 1C:Enterprise Language

To handle XML representations of simple type values, two methods of the global context are utilized, ‑XMLString() and XMLValue().

The XMLString() method has a single parameter,‑ that is the value that you want to get an XML representation for. This value should belong to a simple type, in terms of XML serialization. Otherwise, an exception is thrown. Upon normal completion, the function returns a string that can be used as a text of the XML element representing a simple type value.

The XMLValue() method performs the opposite task. This method has two parameters:

  • the type of value that should be retrieved from a string;
  • and a string itself.

To convert the 1C:Enterprise system data type to the XML data type and vice versa, the XMLType() and FromXMLType() methods are designated. The XMLType() method has one parameter, ‑that is a type that you need to get the corresponding XML data type for. If the corresponding XML data type is identified, the method returns a value of XMLDataType type. Otherwise, if there is no corresponding XML data type, the method returns Unidentified value

The FromXMLType() method has two calling options. For the first option, the method has a single parameter of XMLDataType type. In the second option, there are two parameters: XML type name and namespace. In both cases, the method returns a 1C:Enterprise data type that matches some XML data type, if any, or Unidentified otherwise.

The global context methods WriteXML() and ReadXML() are used to write and read various values to/from XML.

The WriteXML() method has two required parameters. The first parameter‑ is an object of WriteXML type by using which the XML data is getting saved, and the second one ‑ is a value to be saved in XML. Optional parameters form three different method calling options.

In the simplest case, there are three parameters in the calling method, and the third one specifies the enumeration value XMLTypeAssignment that determines whether the XML data type should explicitly be specified in the xsi:type attribute of the root XML element.

The next calling option uses a string value as the third parameter that specifies the name of the root XML element. This implies that the namespace is undefined. The fourth parameter‑ is a value of the XMLTypeAssignment type that specifies whether or not an XML data type should be explicitly indicated.

And finally, the last calling option has one other parameter, ‑a string value designating a namespace which the root element belongs to, following the parameter specifying the root XML element name. Likewise, the last parameter belongs to the XMLTypeAssignment type.

...
Val = "String so and so";
WriteXML(obj, Val);
WriteXML(obj, Val, "Root", XMLTypeAssignment.Explicit);
WriteXML(obj, Val, "Root", "urn:some namespace");
...

Execution of the snippet above will output the following piece of XML code.

...
<string>String so and so</string>
<Root xsi:type="xsd:string">String so and so</Root>
<d1p1:Root xmlns:d1p1="urn:some namespace">String so and so</d1p1:Root>
...

If a value of a type that cannot be represented in XML is passed as the value to be placed in XML, an exception will be thrown.

ReadXML() method is provided for reading values from XML. This method has one required parameter,‑ the ReadXML object which value should be read from. For the second parameter, a type of value that should be read from XML can be specified. If the value type is explicitly specified in XML, then the value of the second parameter can be specified as Undefined, or it can be omitted altogether. In this case, the ReadXML() method tries to identify the type of the value being read by the contents of the xsi:type attribute, or by the element name if the xsi:type attribute is missing. If it fails to identify the type or value of the specified type that cannot be read from XML, then an exception is thrown. On success, the ReadXML() method returns the retrieved value.

Attention should be paid to how constant value managers, database objects, and recordsets are read. Upon success, the ReadXML() method returns the value read from XML, however, this value has not yet been written to the database. If, for example, a catalog item is read, then in order for the catalog item to be getting written to the database, it is necessary to address its Write() method, like it is done during the regular saving of the changed object state. This also applies to other database objects, constant value managers, and record sets.

When reading a database object from XML, the database searches for an object with the same reference value. If such an object is found, then reading from XML looks as though the object was read from the database, and then the values of its properties, tabular sections, etc., are overwritten with the values acquired from XML. Contrariwise, if an object is not found by reference, then reading from XML is similar to generating a new object, setting its reference value, and filling its content with values read from XML.

CanReadXML() method determines whether it is possible to read a value from the ReadXML object located at the current position of an XML document. A ReadXML method is being passed to the given method as its parameter. If the method returns True, then the reading is possible; if False,‑then the value cannot be read.

GetXMLType() method allows to get an XML data type corresponding to the current position of the XML document, from a ReadXML object. This method also has one single parameter, ‑ReadXML.

Exchange plans

Exchange plans form a core in which the rest of the data exchange tools are grouped around. In a single configuration, an arbitrary number of exchange plans can be defined. Each exchange plan specifies a set of data to be exchanged through this exchange plan. Along with the data set, specific presentation formats of this data can be defined.

It is assumed that the data formats are based on XML, but due to the flexibility of XML language and the availability of quite advanced XML tools in the 1C:Enterprise system, there is still a large enough room for creativity in regard to the data presentation methods.

Two most significant components can be distinguished in the exchange plans:

  • message infrastructure,
  • and change registration service.

The data items of an exchange plan are the nodes of this exchange plan, just as the data items of a catalog are the items of that catalog. Each of the exchange plan nodes designates a participant in the exchange of data for this exchange plan. One of the nodes corresponds to this Infobase and the rest of them-to other participants whom this Infobase can exchange data with.

Data is transferred between the nodes by means of messages. Message handling tools form the messaging infrastructure. Each message belongs to a specific exchange plan, it has a specific sending node, a Sender, and a specific receiving node, a Recipient. A message cannot be sent to an unspecified node and cannot be received from an unspecified node. A unique integer number is assigned to each message.

Change registration service is designed to register modifications in data made by the 1C:Enterprise system, in order to transfer only modified data rather than all the data when the data exchange occurs.

Thus, exchange plans define a set of tools designed to organize the data exchange. Let's review these tools in more detail.

Exchange Plan Nodes

When you create a new exchange plan, it automatically creates one node, ‑this node, or the exchange plan node, corresponds to this Infobase. The remaining nodes, that is, nodes which the given node can exchange data with, are not being automatically created as part of the exchange plan.

To each node, a unique code must be assigned, as a node is identified by code in the course of data exchange. Codes of nodes are assigned is such a way that the exchange parties could "recognize" each other.

NOTE. Exchange plan must have a code and a name. In other words, the standard Code and Name attributes of an exchange plan cannot be set to a length of 0.


Suppose it is required to organize data exchange between two infobases through an exchange plan named RemoteWareHouses. One of these infobases serves as the headquarters, and the other ‑as a remote warehouse.

In this case, it would be reasonable to set the code value of this RemoteWareHouses exchange plan in the first Infobase to Office (certainly, if the code length allows), and in the second one‑ to WareHouse1. In this fashion, these nodes will get named. But this is not enough, as you still need to specify the nodes which the data should be exchanged with. To do this, in first Infobase, a RemoteWareHouses exchange plan node with WareHouse1 code should be created, and likewise, in the second Infobase‑ a node with Office code.

Thus, the first Infobase will "get to know' that, within the RemoteWareHouses exchange plan, it is called Office, and it is to exchange data with a node called WareHouse1; and the second Infobase ‑will "get to know" that its name is WareHouse1, and that it is to exchange data with the Office node.

Message infrastructure

The most important part of the messaging infrastructure is the messages themselves. Like it is stated above, the messages are transmitted through an exchange plan from one node to another. That is, each message is strictly associated with a certain exchange plan, it has one Sender and one Recipient.

Let's see what a message is about. The messages are XML documents with a predefined structure. Let's take the following message as an example:

<v8msg:Message xmlns:v8msg="http://v8.1c.ru/messages">
 <v8msg:Header>
   <v8msg:ExchangePlan>RemoteWareHouses</v8msg:ExchangePlan>
   <v8msg:To>WareHouse1</v8msg:To>
   <v8msg:From>Office</v8msg:From>
   <v8msg:MessageNo>20</v8msg:MessageNo>
   <v8msg:ReceivedNo>15</v8msg:ReceivedNo>
 </v8msg:Header>
 <v8msg:Body>
   <!--Message body -->
 </v8msg:Body>
</v8msg:Message>

The entire message is contained inside an XML element named Message belonging to the http://v8.1c.ru/messages namespace. A message consists of the header and the message body. Accordingly, the Message element contains two nested elements named Header and Body. Both belong to the http://v8.1c.ru/messages namespace.

TheHeader element contains a message title. The header structure is strictly fixed. The title's data is presented in several XML elements nested in a Header element. All the elements nested in the Header element belong to the http://v8.1c.ru/messages namespace:

  • ExchangePlan contains the exchange plan name this message belongs to.
  • To contains a code of the node this message is to be sent to.
  • From contains the sending node's code.
  • MessageNo contains the identifying number of this message. The message number is a positive integer and is assigned by a sending node. The number of each subsequent message is equal to the number of the previous sent message incremented by 1.
  • ReceivedNo contains the maximum message number that the message's sending node has received from the receiving node. This value is included in the message header to confirm receipt of the messages.

The message body is contained in an XML element named Body that belongs to the http://v8.1c.ru/messages namespace. This element can have arbitrary content determined by the application needs. The content of the message body is by no means regulated by the message infrastructure.

Change Registration Service

The essence of registering changes is to have a list of modified data items. These data items should be transmitted in the next message to a certain node that the data is exchanged with. With each modification of data, it must be registered that there are changes and that they have to be transferred to all nodes which this data exchange is supported with. Once the receipt of a message in which the changes have been sent is confirmed, the change registration records should be deleted.

Registration of changes can be performed for the following data items:

  • ConstantValueManager.<Constant name>;
  • Database objects:
    • CatalogObject.<Catalog Name>;
    • DocumentObject.<Document Name>;
    • ChartOfAccountsObject.<Chart Of Accounts Name>;
    • ChartOfCharacteristicTypesObject.<Chart Of Characteristic Types Name>;
    • ChartOfCalculationTypesObject.<Chart Of Calculation Types Name>;
    • BusinessProcessObject.<Business Process Name>;
    • TaskObject.<Task Name>.
  • Record Sets:
    • InformationRegisterRecordSet.<Information Register Name>.
    • AccountingRegisterRecordSet.<Accounting Register Name>.
    • AccumulationRegisterRecordSet.<Accumulation Register Name>.
    • SequenceRecordSet.<Sequence Register Name>.
    • CalculationRegisterRecordSet.<Calculation Register Name>.
    • RecalculationRecordSet.<Recalculation Name>.

For each of the data items listed above, its own modification registration table is being maintained. The tables have a varying structure, depending on which data items are recorded for modifications, yet still, the structure of the tables is quite similar. Thus, three components can be recognized in the structure:

  • a data item key the modifications are being registered for;
  • a reference to the node a modification should be passed to;
  • message number a modification was passed in for the first time.

The structure of the change registration tables for different kinds of data differs by key, since the keys for different kinds of data are different, too:

  • for a constant, the key is a constant identifier;
  • for database objects, an object reference is used as a key;
  • for recordsets with a specified recorder, a reference to the recorder object is used as a key;
  • for an information register recordset, if the recorder is not specified, a set of dimensions included in the main filter is used as a key; and if the information register is periodic and the main filter by period is included, then the period is also included in the key.

A data item modification should be registered for all nodes in which the modification is to be passed to. Thus, as a result of a data item modification, N-number of records should appear in the change registration table, where N‑ is the number of nodes which the modifications are registered for. Each of these records contains the same data item key-value and differing values of the reference to a node.

Immediately after registering a modification, the message number is NULL. When a change is being sent for the first time, the number of the message that carries the change is placed in this field.

When configuring an exchange plan, the so-called exchange plan composition is specified. The exchange plan composition includes meta-data objects. If a meta-data object is included in the exchange plan composition, it shows that the data modifications that correspond to this meta-data object can be registered for the nodes of this exchange plan. If the meta-data object is not included in any exchange plan, then a change registration table is not created for this object and no data change registration is performed.

When determining whether a meta-data object is included in the exchange plan, the AutoRecordproperty is specified. Auto-registration can be enabled or disabled. If auto-registration is enabled, then, once the data changes, the registration will be performed automatically. Otherwise, if it is disabled, then the change can be registered manually.

Accessing the Exchange Plan Tools by Means of 1C:Enterprise Language

A set of objects has been designed, to handle exchange plans by means of 1C:Enterprise language.

ExchangePlansManagerobject, apart from the features typical for this kind of managers, contains the following methods to handle the change registration service, RecordChanges(), DeleteChangeRecords(), IsChangeRecorded(), SelectChanges(), as well as methods for generating objects that read and write messages: CreateMessageReader(), CreateMessageWriter().

For the ExchangePlanManager.<Exchange Plan Name> object, the most valuable feature is ThisNode() method that returns a link to the node of this exchange plan corresponding to this Infobase (hereinafter referred to as “this node”). To identify an exchange plan node that corresponds to this Infobase, the standard attribute ThisNode is also of use. The value of ThisNode attribute can be changed. The most common cause of using this operation ‑is the restoration of the Infobase correct state, following the recovery of data from an XML file. In this case, in the restored database, it is necessary to assign “this node” to the exchange plan item that was set in the source database. This is especially relevant in the case when the references to "this node" of the exchange plan were stored in any objects of the Infobase. Let us consider the process of replacing "this node" in more detail.

A regular re-writing of an exchange plan item with the set (or reset) ThisNode property cannot be performed (if there is an exchange plan item in the system with ThisNode property being set),‑ as the system will throw an exception. In order to perform this operation successfully, the following steps should be done:

  • For an item that is planned to be specified as “this node”, ThisNode property in the DataExchange.Download mode should be set to True.
  • For an item that was “this node” previously, ThisNode property should be reset (in a regular way).
  • It is recommended to perform these operations (setting a new node and disabling the old one) in a transaction.

Here is an example of reassigning “this node” item:

BeginTransaction();
 
CurrentThisNode = ExchangePlans.DataExchange.ThisNode();
 
NewObject = NewThisObject.GetObject();
NewObject.DataExchange.Import = True;
NewObject.ThisNode = True;
NewObject.Write();
 
CurrentObject = CurrentThisNode.GetObject();
CurrentObject.ThisNode = False;
CurrentObject.Write();
 
CommitTransaction();

When changing ThisNode, a few peculiarities of the system behavior should be borne in mind:

  • If you shut down the system at a junction when an exchange plan does not have the “this node” item, then the system will automatically create a new exchange plan item at startup, with ThisNode property set to True.
  • If the system has two items with ThisNode property value set to True, then the system behavior grows rather unpredictable.

ExchangePlanObject.<Exchange Plan Name> corresponds to the exchange plan node. SentNo and ReceivedNo properties deserve special attention. The SentNo property contains the number of the last message sent from this infobase to the address of the node that corresponds to the ExchangePlanObject.<Exchange Plan Name> object. The ReceivedNo property contains the largest of the message numbers received by this Infobase from the node that corresponds to the ExchangePlanObject.<Exchange Plan Name> object.

Change Registration

As mentioned above, the registration of changes can be performed automatically when recording or removing a data item. Let us see how this happens. Each of the objects whose modifications can be registered by an exchange plan has DataExchange property of DataExchangeParameters type. This read-only property is designed to manage various parameters in the course of data exchange.

DataExchangeParameters object has Recipients property of NodeSet type. This property stores a list of nodes whose modifications will be recorded when writing or removing data. The list of recipients is automatically populated prior to calling the BeforeWrite() handler when data writing is being performed, or BeforeDelete() handler when data deletion is carried out. However, the automatic filling will be performed only if the AutoFill property of the NodeSet object is set to True (with True being the default value for the AutoFill property). With AutoRecord on, the list of recipients gets links to all nodes of all exchange plans that include the corresponding metadata object, provided that the value of the Auto-Registration property is Enabled. It goes without saying that the nodes corresponding to this Infobase will not be included in the list of recipients. Prior to automatic filling, a list of recipients is cleared.

In BeforeWrite() (and/or BeforeDelete()) handler, changes to the list of recipients can be made, by adding or removing links to the nodes. Yet, it should be remembered that the list of recipients can only contain links to nodes related to those exchange plans that include the corresponding metadata object.

In the example below, BeforeWrite() handler rules out from the list of recipients a node with the code Special of the RemoteWareHouses exchange plan.

Procedure BeforeWrite()
 Node = ExchangePlans.RemoteWareHouses.FindByCode("Special");
 DataExchange.Recipients.Remove(Node);
EndProcedure

By setting the AutoFill property to False, one can ensure that the recipient list will not be automatically populated. In this case, operations with the list of recipients can be performed not only in the BeforeWrite() handler but also in any code fragment, as shown in the example.

Object = Link.GetObject();
Node = ExchangePlans.RemoteWareHouses.FindByCode("WareHouse1");
Object.DataExchange.Recipients.AutoFill = False;
Object.DataExchange.Recipients.Add(Node);
Object.Write();

A number of methods for registering changes contain ExchangePlansManagerobject. First of all, it is RecordChanges() method. This method allows registering modifications for single data items or for entire groups for one or more nodes. The first parameter of this method‑ is a link to an exchange plan node or an array of links to nodes whose changes are registered. If the first parameter is a single link to a node, then the second parameter can be omitted. Meanwhile, the registration of changes for all data items that are currently present in the database and whose modifications can be registered for this node is being performed.

This can be of use when configuring the initial transfer of data to a newly created node.

Node = ExchangePlans.RemoteWareHouses.FindByCode("New");
ExchangePlans.RecordChanges(Node);

If the first parameter is an array of links to nodes, then the second parameter must be specified. However, the second parameter may also be present if the first parameter‑ is a single node link. Depending on the method of specifying the second parameter, there is an option to register the modifications of either a single data item or all data related to one metadata object.

To register changes to one item, the data element itself, a link to a database object, or a link to an object of the ObjectDeletion type can be specified as the second parameter.

If a data item is specified, then its modification is registered. If a link to a database object is specified, then a modification of this object is registered.

If the second parameter is of the ObjectDeletion type, then a modification to the database object, a link to which is contained by the ObjectDeletion object, is registered.

Nodes = New Array(2)
Nodes[0] = ExchangePlans.RemoteWareHouses.FindByCode("WareHouse1");
Nodes[1] = ExchangePlans.RemoteWareHouses.FindByCode("WareHouse2");
Data = Catalogs.Products.FindByCode("TP00127");
ExchangePlans.RecordChanges(Nodes, Data);

To register changes in all data related to the metadata object, the corresponding metadata object must be specified as the second parameter.

Nodes = New Array(2)
Nodes[0] = ExchangePlans.RemoteWareHouses.FindByCode("WareHouse1");
Nodes[1] = ExchangePlans.RemoteWareHouses.FindByCode("WareHouse2");
ExchangePlans.RecordChanges(Nodes, Metadata.Catalogs.Products);

To remove records of registration changes, ExchangePlansManagerobject has DeleteChangeRecords() method. By using it, one can delete change registration records for all data items that are registered for a node.

Node = ExchangePlans.RemoteWareHouses.FindByCode("WareHouse1");
ExchangePlans.DeleteChangeRecords(Node);

One can remove the change registration records for a specific data item for one or more nodes.

Nodes = New Array(2)
Nodes[0] = ExchangePlans.RemoteWareHouses.FindByCode("WareHouse1");
Nodes[1] = ExchangePlans.RemoteWareHouses.FindByCode("WareHouse2");
Data = Catalogs.Products.FindByCode("TP00127");
ExchangePlans.DeleteChangeRecords(Nodes, Data);

One can also delete records of all modifications made to a metadata object for one or several nodes.

Nodes = New Array(2)
Nodes[0] = ExchangePlans.RemoteWareHouses.FindByCode("WareHouse1");
Nodes[1] = ExchangePlans.RemoteWareHouses.FindByCode("WareHouse2");
ExchangePlans.DeleteChangeRecords(Nodes, Metadata.Catalogs.Products);

Moreover, if a single node is specified as the first parameter, a message number can be specified as the second parameter. In this case, DeleteChangeRecords() method deletes from all the change registration tables all the entries related to a specified node whose message number is less than or equal to the value of the second parameter (but not NULL).  This form of the method is earmarked to remove the change registration records with acceptance of changes confirmed from the node specified in the first parameter.

To check whether a data item change is registered for a particular node, use IsChangeRecorded() method. The first parameter of this method ‑is a node-link, and the second parameter ‑is a Data item, a link to a database object, or an ObjectDeletion.

Recording Data Exchange Messages

To record messages, use ExchangeMessageWriterobject.

ExchangeMessageWriterobjectis generated when addressingCreateMessageWriter() method of ExchangePlansManager object.

ExchangeMessageWriter object has three methods:

  • BeginWrite(),
  • EndWrite(),
  • CancelWrite().

BeginWrite() method has two parameters: an object of WriteXML type, through which the message will be recorded, and a link to the node which the message is addressed to. BeginWrite() method calculates the message number by incrementing the number of the previous message by 1; it records the opening part of the XML element containing the whole message, the entire message header, as well as the opening part of the XML element containing the message body. Following that, one can start recording the contents of the message body.

To complete the recording of a message in a regular way, use the EndWrite() method. When calling this method, the closing part of the XML element containing the message body and the closing part of the XML element containing the entire message are recorded. Upon successful recording of the XML elements that conclude the message, the message is considered to be sent, and its number is stored as the number of the last message sent from this node to the receiving node.

If there is a need to interrupt the recording of a message and not to consider it sent, CancelWrite() method should be addressed.

The following is a typical code snippet that records a data exchange message.

WriteXML = New WriteXML();
WriteXML.OpenFile(MessageFileName);
Node = ExchangePlans.RemoteWareHouses.FindByCode(NodeCode);
MessageRecord = ExchangePlans.CreateMessageWriter();
MessageRecord.BeginWrite(WriteXML, Node);
// Recording the message body
MessageRecord.EndWrite();

The message body can contain any data presented in XML, depending on what format is adopted for a particular exchange plan. Also, we shall consider a case when a message contains data whose modifications have been registered by the change registration service. To implement this, you should select registered changes, iterate them, and put the XML representations of the modified data into the message.

To select changes, use the SelectChanges() method of the ExchangePlansManagerobject. This method has two parameters: a link to the node whose changes are selected, and a number of the message in which the changes should be placed. SelectChanges() method returns an object of DataSelection type containing the keys of the data whose modifications were registered for the node passed as the first parameter. Besides, SelectChanges() method puts the message number passed as the second parameter into the corresponding fields of the selected entries in change registration tables if these fields have previously contained a NULL value.

If a modification has already been selected at the previous access, the message number in the corresponding record of the change registration table is not modified; and if the modification has not yet been selected, then the selection will remember the number of the first message which the modifications have been selected for.

To iterate the selected modifications, the DataSelection object has the Next() and Get() methods. When calling Next() method, a transition to the next key in the selection occurs. When Next() method is addressed for the first time, a transition to the first key takes place. When addressing Get() method, a data item corresponding to the current selection key is selected from the database. Here it is necessary to make a special note with regard to the remote database objects. If the registration of a change in a database object was performed as a result of its deletion, then Get() method will return not a database object, but an object of the type ObjectDeletion.

Placing the XML representation of the data items in a message is performed by using the global context WriteXML() method.

Below is a snippet of code in which a message is formed, and then the registered data modifications are placed in its body.

WriteXML = New WriteXML();
WriteXML.OpenFile(MessageFileName);
 
Node = ExchangePlans.RemoteWareHouses.FindByCode(NodeCode);
 
MessageRecord = ExchangePlans.CreateMessageWriter();
MessageRecord.BeginWrite(WriteXML, Node);
 
Selection = ExchangePlans.SelectChanges(Node, MessageRecord.MessageNo);
While Selection.Next() Loop
 
 Data = Selection.Get();
 WriteXML(XMLWriter, Data);
 
EndDo;
 
MessageRecord.EndWrite();

Reading data exchange messages

The ExchangeMessageReader object is designed to read data exchange messages.

The object is created by calling CreateMessageReader() method of the ExchangePlansManager object.

The ExchangeMessageReader object has three methods:

  • BeginRead(),
  • EndRead(),
  • CancelRead().

The BeginRead() method has two parameters: the object of ReadXML type used to read messages and AllowedMessageNo enumeration value.

The BeginRead() method reads the beginning of XML item, containing all messages. It reads message header and verifies its eligibility:

  • whether the exchange plan is defined, to which the message is attached;
  • whether the sender and receiver are set correctly;
  • whether the message number is acceptable.

The message number eligibility is defined considering the value of the second parameter. If the second parameter value is set to AllowedMessageNo.Any, the message read may have any number. If the second parameter value is set to AllowedMessageNo.Next, the message number must be greater than the maximum number of previously received messages exactly by 1. And if the second parameter is set to AllowedMessageNo.Greater, the message number must be just greater than the numbers of previously received messages. The default value for the second parameter is AllowedMessageNo.Greater.

Then the beginning of XML element containing a message body is read. If the message is not eligible or the error occurred when reading, the exception is called. If everything is fine, the message body can be read.

For the normal ending of the message reading, the EndRead() method is used. This method reads the end of XML element containing the message body and the end of XML element containing all messages. If everything is fine, the message is considered received and the message number (if it's greater than numbers of previously received messages) is recorded as the maximum number of the received message.

The CancelRead() method allows canceling message reading at any moment.

The following code fragment, where the usage of ExchangeMessageReader object is demonstrated, is a standard one.

ReadXML = New ReadXML();
ReadXML.OpenFile(MessageFileName);
MessageReading = ExchangePlans.CreateMessageReader();
MessageReading.BeginRead(ReadXML, AllowedMessageNo.Greater);
// Reading message body
MessageReading.EndRead();

As noted above, the message body may contain any information, but here we will review changed data reading from the message body. The code fragment for reading a message with the changed data looks as follows.

ReadXML = New ReadXML();
ReadXML.OpenFile(MessageFileName);
 
MessageReading = ExchangePlans.CreateMessageReader();
MessageReading.BeginRead(ReadXML);
 
ExchangePlans.DeleteChangeRecords(MessageReading.Sender, MessageReading.MessageNo);
While CanReadXML(ReadXML) Loop
 
 Data = ReadXML( XMLReader);
 Data.DataExchange.Sender = MessageReading.Sender;
 Data.DataExchange.Load = True;
 Data.Write();
 
EndDo;
 
MessageReading.EndRead();

Calling DeleteChangeRecords() method of the ExchangePlansManager object is designed to delete registration records used to confirm the receive. Then the ReadXML() method is used to read data from the message body while there's an opportunity to do so. Before writing data to the database, two properties of DataExchangeParameters object, which belongs to the object providing data read from XML. The node that sent data is specified in Sender property to avoid change registration to be sent to the node, from which the data were just received. Setting True value to the Load property means that the writing is made within data uploading, not simply writing. In this case, some verifications will not be performed when writing.

Guaranteed message delivery

In the examples of data exchange message writing and reading above, it was supposed that the sent messages could be lost for some reason. That's why when writing messages they included all registered changes, including those that were already sent without the receive confirmation.

When receiving, the message with the number that is greater than the maximum number from received messages is acceptable. The changes registration is deleted only for numbers of messages, for which the receive was confirmed.

MessageReading.BeginRead(ReadXML);
ExchangePlans.DeleteChangeRecords(MessageReading.Sender, MessageReading.ReceivedNo);

This logic is standard when data exchange is implemented. However, you can implement an option, where the message delivery is guaranteed. In this case, changes registration must be deleted right after the message is successfully written to avoid sending changes that were already sent. Only messages with the number greater than the maximum number of previously received messages by 1 can be received.

In this case, the above code fragment that writes a message will look as follows.

WriteXML = New WriteXML();
WriteXML.OpenFile(MessageFileName);
 
Node = ExchangePlans.RemoteWareHouses.FindByCode(NodeCode);
 
MessageRecord = ExchangePlans.CreateMessageWriter();
MessageRecord.BeginWrite(WriteXML, Node);
 
Selection = ExchangePlans.SelectChanges(Node, MessageRecord.MessageNo);
While Selection.Next() Loop
 
 Data = Selection.Get();
 WriteXML(XMLWriter, Data);
 
EndDo;
 
MessageNo = MessageRecord.MessageNo;
MessageRecord.EndWrite();
 
ExchangePlans.DeleteChangeRecords(Node, MessageNo);

The code fragment, in which the message is received, will look as follows:

ReadXML = New ReadXML();
ReadXML.OpenFile(MessageFileName);
 
MessageReading = ExchangePlans.CreateMessageReader();
MessageReading.BeginRead(ReadXML, AllowedMessageNo.Next);
While CanReadXML(ReadXML) Loop
 
 Data = ReadXML( XMLReader);
 Data.DataExchange.Sender = MessageReading.Sender;
 Data.DataExchange.Load = True;
 Data.Write();
 
EndDo;
 
MessageReading.EndRead();

Remember that it may be quite hard to set the guaranteed message delivery and in most cases, it's recommended to send changes repeatedly until getting receive confirmation.

Resolving collisions

In the message writing and reading examples above it was not considered that during data exchange the same data item can be changed in two data-sharing nodes at the same time. In this case, it's not clear, which change must be accepted. This situation is called a collision.

One of the ways to resolve collision ‑ to define the master node and the subordinate node. The change made in the master node must be accepted and the change made in the subordinate mode must be denied.

To implement this process during the message received and before writing data, define, whether the data change was registered, and depending on the node role in this sender-receiver pair, decide whether the data should be written or not.

Below is the example of "master ‑ subordinate" strategy implementation when reading messages. It's supposed that the Master attribute of Boolean type was provided in the exchange plan to store node role.

ReadXML = New ReadXML();
ReadXML.OpenFile(MessageFileName);
 
MessageReading = ExchangePlans.CreateMessageReader();
MessageReading.BeginRead(ReadXML);
 
ExchangePlans.DeleteChangeRecords(MessageReading.Sender, MessageReading.MessageNo);
Sender = MessageReading.Sender;
Master = Sender.Master;
While CanReadXML(ReadXML) Loop
 
 Data = ReadXML( XMLReader);
 If Master Or Not ExchangePlans.IsChangeRecorded(Sender, Data) Then
 
   Data.DataExchange.Sender = MessageReading.Sender;
   Data.DataExchange.Load = True;
   Data.Write();
 
 EndIf;         
EndDo;
MessageReading.EndRead();

Namespace Mapping

When writing a message, after executing BeginWrite() method of the ExchangeMessageWriter, no namespace mappings are defined. At the same time, a set of namespaces can be used several times when writing specific data items. In this case, the mappings of the same namespaces will be included in the message body several times. This is why after message writing is started and before whiting the body, it's reasonable to place several code strings that will define the mapping of the most frequently used namespaces.

An example of this is provided in the message writing fragment below.

WriteXML = New WriteXML();
WriteXML.OpenFile(MessageFileName);
 
Node = ExchangePlans.RemoteWareHouses.FindByCode(NodeCode);
 
MessageRecord = ExchangePlans.CreateMessageWriter();
MessageRecord.BeginWrite(WriteXML, Node);
WriteXML.WriteNamespaceMapping("xsd", "http://www.w3.org/2001/XMLSchema");
WriteXML.WriteNamespaceMapping("xsi", "http://www.w3.org/2001/XMLSchema instance");
WriteXML.WriteNamespaceMapping("v8", "http://v8.1c.ru/data");
Selection = ExchangePlans.SelectChanges(Node, MessageRecord.MessageNo);
 
While Selection.Next() Loop
 
 Data = Selection.Get();
 WriteXML(XMLWriter, Data);
 
EndDo;
 
MessageNo = MessageRecord.MessageNo;
MessageRecord.EndWrite();
 
ExchangePlans.DeleteChangeRecords(Node, MessageNo);

In some cases, such a method will help to significantly reduce the size of the XML document, in which the data exchange message is located.

Be the first to know tips & tricks on business application development!

A confirmation e-mail has been sent to the e-mail address you provided .

Click the link in the e-mail to confirm and activate the subscription.