structToXml /schema

Convert a Struct to XML using a schema.

Syntax

structToXml/schema {/validate} {/cs}{/location}   XmlTarget, StructSource, Schema  {, StartingPoint}

Switches

  • /schema—generate XML using a schema. For more information, see Schema Concepts Used to Generate XmlTarget.
  • /validate—validate the resulting document against the schema. For more information, see Schema Concepts Used to Validate XmlTarget.
  • /cs—the search for Struct names that match schema definitions is case-sensitive. (The default is case-insensitive because componentToStruct always uses uppercase names.)
  • /location—provide noNamespaceSchemaLocation and/or schemaLocation attributes in the root tag. The locations specified in the Schema parameter are used to fill in these attributes. (An XML document does not require these, so they are not added by default.)

Parameters

  • XmlTarget—variable or parameter of type xmlstream, string, or any to which the converted XML is written
  • StructSource—variable or parameter of type struct or any, that references a Struct or collection of Structs to be converted
  • Schema—schema to which XmlTarget must conform. It can be a file name or URL, an indexed list of schema file names or URLs, or the schema document itself.

    If Schema contains a list of schemas, the first one will be read first, and the rest only if <import>, is encountered without schemaLocation; this list provides the missing schema locations.

    If Schema is the schema document itself, /location does nothing and /validate is not allowed

  • StartingPoint— element or data type in the schema from which the structToXml conversion process should start; in the form:

    "element=ElementName"

    or

    "type=DatatypeName{;namespace=Namespace}"

    For more information, see Starting Point.

Return Values

Values Commonly Returned by $procerror

Error Number

Error Constant

Meaning

-1905

STRUCTERR_INPUT

Input struct data is not valid. For example, the struct variable may have been declared, but not initialized.

Values Commonly Returned by $procerror after structToXml/schema

Value

Error Constant

Meaning

-4

UIOSERR_OPEN_FAILURE

If the schema specified cannot be opened.

-1110

UPROCERR_TOPIC

If the StartingPoint parameter is not of the form 'element=…' or 'type=…'.

-1118

UPROCERR_ARGUMENT

If the StartingPoint parameter is of the correct format but the element or type cannot be found in the schema.

-1190 USTRUCTWARN_MEMBER_NOT_FOUND The schema specifies an element that can contains sub-elements but no character data. The Struct members or the sub-elements can be found, but not the parent element.

-1406

UPROCERR_MEMORY

If not enough memory could be allocated.

The XML produced may not be what is expected if non-fatal errors occurred during conversion, because everything that is not recognized or usable is ignored. Warnings about such conditions are made available in $procReturnContext.

Errors and warnings returned in $procreturncontext

Error

Error Constant Meaning
-1155 USTRUCTERR_MEMBER_NOT_FOUND When the schema dictates the presence of a struct member of a specific name, and it cannot be found.
-1160 USTRUCTERR_TAGVALUE_NOT_APPLICABLE Annotation xmlClass has no value, or an unknown or illegal value (based on the current context)
-1190 USTRUCTWARN_MEMBER_NOT_FOUND The schema specifies an element that can contains sub-elements but no character data. The Struct members or the sub-elements can be found, but not the parent element.

-1503

UXMLERR_PARSE

An error occurred while parsing an XML stream. Possible causes:
  • The specified schema can be opened but cannot be parsed.
  • The specified schema can be parsed as XML but it is not a schema.
-1550 UXMLWARN_PARSE A warning occurred while parsing an XML stream. Possible causes:
  • <anyAttribute> is defined for am element in the schema but the attribute declarations cannot be found.

Use

Allowed in all Uniface component types.

Description

A schema describes a set of user-defined XML elements and data types.

Important: When converting a Struct to an XML document that conforms to a schema, you should have a good understanding of XML schemas and schema concepts. The following web sites are recommended as a good place to start:

Using the provided schema, structToXml/schema searches the input Struct (StructSource) for Struct members that match the schema. Matching is based on both the names of Struct members and the structure of the Struct. Everything in the Struct that does not match the schema is ignored.

The point at which the matching process starts determines whether the resulting XML output is a complete XML document or an XML snippet. If it is an element, structToXml/schema generates a complete well-formed XML document. If it is a data type, it generates a snippet.

Performance

Using structToXml without /schema is faster than using structToXml/schema.

During conversion with structToXml/schema, the schemas are converted to Structs and subsequently both the schema and source Structs are scanned repeatedly to find type definitions or the source element. This provides a very flexible conversion algorithm, but can result in performance problems, especially when the source Struct contains many repeating members that are groups of members themselves.

To optimize performance, consider the following:

  • Limit the number of occurrences that need to be processed. Do not use structToXml/schema to process millions of records.
  • Try to have the nodes in the Struct in the same order as the elements defined in the schemas. This reduces the number of times that internal processing needs to start from the beginning of the schemas to find a match.

Starting Point

A schema may describe a single global element and its child elements, or it may define multiple global elements and data types, which refer to each other to define a complete XML document. It could even describe more than one type of XML document, depending on which global element you start with.

If the schema describes a single global element, you can omit the StartingPoint parameter; matching will start with the first element.

However, if the schema is more complex, you need to specify the StartingPoint.

If you specify "element=ElementName", structToXml/schema will search for the this global element in the schema, and continue the conversion process from there to generate an XML document. The root of the Struct you provide is assumed to match this element, even if its name does not match.

If you specify StartingPoint as "type=DatatypeName", the resulting XML document cannot be a complete one that can be validated, because the starting element name is unknown. structToXml/schema generates a start element whose tag name is the name of the root member of the Struct. If it has no name, this is not done, and the result is a list of root elements—an XML snippet to be incorporated in another XML document.

If the element or data type used as the starting point is not unique across all schemas that are being read, it may be necessary to further qualify it using its namespace. Add "namespace=namespace" to the StartingPoint parameter, separated by Gold ;. For example:

structToXml/schema /validate vXmlOutput, vInputStruct, "element=shiporder;namespace=http://shiporder.com/order"

Converting Structs to XML Using Schemas

After determining the starting point, structToXML/schema processes each of the schema definitions and references to global definitions in order. For each element or attribute definition encountered, it looks in the input Struct to find a match, and if one is found, produces a line of XML for it before going to the next definition.

For definitions that specify that an element may occur more than once, this is repeated until the defined maximum is reached, or there are no more matches in the Struct. structToXML/schema then checks that the minimum number was reached (producing an error if not), before proceeding to the next definition in the schema.

If structToXML/schema finds the required matches in the Struct, and the values in the input Struct adhere to the restrictions placed upon them by the schema, it produces a valid XML document that adheres to the schema. However, in some cases you may have to modify the Struct before providing it to structToXML/schema:

  • If a schema definition specifies a choice (either element A or element B can be present) and the input Struct contains members for both, the first choice member in the definition is used and the other one is ignored. In this case, you need to ensure that only the desired element is present in the Struct.
  • If a schema definition specifies a maximum number and the corresponding Struct members exceed this number, the child members up to that number are used and the rest ignored. In this case, you need to ensure that the only the desired members are present in the Struct.

Converting Attributes

If a Struct contains attributes, these must be defined in the schema, otherwise they are ignored with no warning.

If <anyAttibute> is defined for an element in the schema, structToXML/schema searches all schemas to find an attribute in the same namespace and uses this to write the attribute to the resulting XML stream. If it does not find an attribute definition, it reports an error in $procreturncontext ("No attributes in schema for element:<elementname>”) and no attributes are written to the XML.

Schema Concepts Used to Generate XmlTarget

The structToXML/schema statement reads the specified schema and then proceeds to process the source Struct, attempting to match the Struct contents with the schema. It recognizes and supports the following schema concepts (as defined in part 1 of the official standard), and applies them as indicated in the following table.

Schema Concepts Used to Generate XmlTarget

Schema Concept

XML Construct

Use by structToXML /schema

Simple type definitions

<simpleType…>

Determine how a value in a Struct member is put in the XML document, and the conversions that are required.

Complex type definitions

<complexType…>

Determine the XML tag structure that must be followed in the XML document.

Element declarations

<element…>

Determine the names of XML tags, and the structure inside a tag that must be generated in the XML document.

Attribute declarations

<attribute…>

Determine the name and simple type of attributes to be written to the XML document.

Attribute group definitions

<attributeGroup…>

Processes each attribute in the group as if it were specified at the position where the reference to the group was encountered.

Model group definitions

<group …>

Processes each model group as if it were defined at the position where the reference to it was encountered.

Model groups

  <all …>

  <sequence …>

  <choice …>

Determine how Struct members that match the sub-elements of the group are put into the XML document.

Model groups describe a set of sub-elements that must occur once in any order (all), zero or more times in the specified order (sequence), or only one of them must occur (choice).

Substitution groups

<substitutionGroup…>

If a Struct member with the name of an element cannot be found, structToXML/schema searches for a Struct member that has the name of the substitutionGroup defined for that element.

Particles

Model groups, element declarations, or wildcards with minOccurs=, maxOccurs=)

The minOccurs= and maxOccurs= attributes determine when to stop searching for another occurrence of a Struct member that represents an element.

Wildcards

<any>

<anyAttribute >

The wildcard allows any global element or attribute defined in the same or another imported schema to appear at that position in the XML document.

structToXML/schema examines all immediate child Structs to find a matching global element or attribute in all allowed schemas (specified using namespace=##all, ##other in the schema), and writes an XML line for the first one encountered. If no match is found among the immediate children, their children are first searched for a match, before moving to the next child level.

Namespaces

<schema …>

If the first schema has a targetNamespace defined and the elementFormDefault is "qualified", the namespace is defined as the default namespace in the first element tag written in the resulting XML document.

If elementFormDefault is "unqualified", the namespace is defined with a prefix, and the prefix is added to global element names. The same is true for attributeFormDefault.

Include, Redefine, Import

<include..>, <redefine…> or <import…>

These concepts are about reading other schema documents.

If the schemaLocation attribute is not set in these definitions, the other schema file names or URLs in the Schema parameter will provide those locations.

Nil values

nillable="true"

Writes nil="true" in the element's tag if one of the following is true:

  • The Struct member corresponding to an element for which nillable="true" has no value or is empty ""

  • No corresponding Struct member can be found for the element (or its sub-elements) and the element is not optional.

If the element is not nillable, this attribute is never written; the element is either omitted or an empty one is written, depending on whether it is optional or not.

Lists

 

If a Struct contains a Uniface list, the GOLD characters used as separators are replaced by spaces.

Unions

 

Takes the value from the Struct node as a string.

A union can contain many different data types, so no attempt is made to find the right one. Use the /validate flag to validate the resulting document, to ensure that the provided data conforms to one of the data types in the union.

It is possible to perform round-trip conversions using xmlToStruct on an XML file that conforms to a schema, and then using structToXML/schema on the resulting Struct, with the same schema. The resulting XML should be the same, including DTD, comments, process instructions, any elements and anyAttribute attributes.

Schema Concepts Used to Validate XmlTarget

The structToXML/schema statement assumes that all values you supply in the input struct conform to restrictions imposed by the schema. To validate the generated XML and ensure that restrictions are applied, you can use the /validate switch.

The following schema constructs are recognized as restrictions by structToXML/schema and used during validation.

Schema Concepts Used to Validate XmlTarget

Schema Construct

Description

Identity-constraint definitions

Enforce unique values and referential integrity between the values of different elements.

Restrictions

Place a restriction on the values that can be written. This is ignored when generating the XML, but can be checked with /validate.

Notation declarations

Considered to be simple string with a restriction; since restrictions are ignored, it is treated as a simple string.

fixed

Places a restriction on the value an attribute or element can have.

default

Determines what to do if an attribute is not in the XML document, or if an element is present in the XML document but is empty.

Note:   Annotations in the schema document the schema itself, providing information to users or applications. They are ignored when generating and validating XML.

Tags Used in Conversion

Annotations (tags) may be present in the SourceStruct (typically as a result of a previous conversion using componentToStruct or xmlToStruct), but they are used to generate XML only in the specific circumstances. If they are not used, they are ignored.

Tags Used in Conversion

Tag

Use

xmlVersion

Generates an XML declaration only if the starting point is an element and this tag is present on the root Struct member. In this case, the xmlStandalone and xmlEncoding tags are also used (if present).

xmlClass="namespace-declaration"

If a struct member matches an element, you can add an xmlns namespace declaration to the element. For example:

..->member->myprefix="http://my/uri"

..->member->$tags->xmlClass="namespace-declaration"

Result: <member xmlns:myprefix="http://my/uri" ....

If the prefix is named "#default", a default namespace declaration xmlns="http://my/uri" is added.

xmlNamespace

If the schema defines a namespace for an element or attribute name, structToXML/schema examines both the xmlNamespace (if present) and the Struct name and to determine whether the Struct member matches the element or attribute name.

  • If the xmlNamespace tag is present, it is used to determine whether there is a match.

  • If a Struct member has the right name but has no xmlNamespace tag, the target namespace of the schema document that contains the element or attribute is used.

Note:  If the Struct originates from an xmlToStruct conversion, and the namespaces used in the original XML document are not the same as the ones in the given schema, you need to remove or change all xmlNamespace tags from the Struct before providing it to structToXML/schema.

xmlClass="doctype" and related DTD tags

Writes a DTD in the same way as structToXML (without /schema). Schema’s do not support entity declarations, so if this is required, the SourceStruct must include a Struct member that defines your entities in the XML document; that is, there must be a Struct with xmlClass="doctype" and child members whose xmlClass="entity-declaration ". For more information, see XML DOCTYPE Declaration.

xmlClass and/or xmlNamespace

Used only when the schema uses multiple wildcard types (any and/or anyAttribute) in the same element, and a child Struct member does not match any other subelement or attribute. In this case, it can be unclear whether the Struct member should be converted to an element of type any or an attribute of type anyAttribute.

xmlClass="comment"

Used to write comments in the XML document at the location determined by the Struct.

Comments have no name and schemas do not determine where comments will be placed, so structToXML/schema relies on the position of comment Structs to determine their placement.

For example, if a comment is to be placed:

  • Inside an element before any subelement—its corresponding Struct member must be the first child member of the element Struct (or the second child if the first one is a processing instruction).

    ; add comment in element root, before anything else
    root->comment1= "The first comment"
    root->comment1->$tags->xmlClass = "comment"
    root->comment1->$index = 1  ; comment must be first
  • Immediately after a subelement, its corresponding Struct member must be a sibling of the subelement Struct member and immediately follow that member.

    ; add comment after the second sub-element, before the third:
    root->more-levels->comment = "Comment between the second and third subelement"
    root->more-levels->comment->$tags->xmlClass = "comment"
    
    ; position the comment after subelement{2} and before subelement{3}
    root->more-levels->comment->$index = root->more-levels->subelement{2}->$index +
  • Just before the end of an element, its corresponding Struct member must be the last child member of the element's Struct node (or next to last, if the last one is a processing instruction).

    ; add comment in element root at the end
    root->comment1= "The last comment"
    root->comment1->$tags->xmlClass = "comment"
    ; (don't need to change $index, new members are placed at the end by default)

xmlClass="process-instruction"

Used to write processing instructions in the XML document at the location determined by the Struct (in the same way a comments).

However, although the name of the struct member does not matter for comments, it does for processing instructions—the name appears immediately after <? and the value follows: <?name value?>

For character data (for elements with mixed="true"), the Struct member must not have a name, and the xmlClass tag must not be present or have the value "CDATA", in which case the character data will be written in <![CDATA[...]]> format.

xmlAlias

If an element or attribute requires a prefix, and the matching Struct member has an xmlAlias, its value is used for the prefix. If the tag is not present, a prefix is generated.

Note:  The first Struct member encountered for any element or attribute that uses the namespace for which you want this prefix must have the xmlAlias tag. If the first one does not have it, Uniface will generate one (ns0, ns1, and so on) and that one will be used, even if subsequent Struct members do have the xmlAlias tag.

Version

Change

9.6.01

Introduced

Uniface Logo A

Send feedback about this topic to Uniface.