XML

To generate XMLs, I recommend using ElementTree to build xml documents instead of having to mix and match the XML and XSD schemas.

Schema

The schema can be found within the same parent directory of Siemens.Engineering.dll with the name Schemas. Currently, I am playing with C:\Program Files\Siemens\Automation\Portal V18\PublicAPI\V18\Schemas.

I don’t know how to read XMLSchemas so I am using xmlschema library.

I dump out the parts of schema instead.

import xmlschema

schema = xmlschema.XMLSchema(<<XSD FILE PATH HERE>>)

print("Elements:")
for element in schema.elements:
    print(f"- {element} : {schema.elements[element]}")

print("\nTypes:")
for type_name, schema_type in schema.types.items():
    print(f"- {type_name} : {schema_type}")

Each schemas in the directory are not dependent of each other. I think they act as a reference guide rather than a fully built XML schema (what I am thinking of is a generator or a builder).

Schemas
  • SW.Common_v3.xsd

  • SW.Interface.Snapshot.xsd

  • SW.InterfaceSections_v5.xsd

  • SW.PlcBlocks.Access_v4.xsd

  • SW.PlcBlocks.CompileUnitCommon_v4.xsd

  • SW.PlcBlocks.Graph_v5.xsd

  • SW.PlcBlocks.InstanceSupervisions_v3.xsd

  • SW.PlcBlocks.LADFBD_v4.xsd

  • SW.PlcBlocks.SCL_v3.xsd

  • SW.PlcBlocks.STL_v4.xsd

  • SW.PlcBlocks.TypeSupervisions_v3.xsd

  • SW.TechnologicalObjects_AdditionalDataAxis_v1.xsd

  • SW.TechnologicalObjects_AdditionalDataKinematics_v1.xsd

  • SW.TechnologicalObjects_AdditionalDataMeasuringInput_v1.xsd

  • SW.TechnologicalObjects_AdditionalDataOutputCam_v1.xsd

  • SW.TechnologicalObjects_Parameters_v1.xsd

  • SW.TechnologicalObjects_ProfileDataCam_v1.xsd

When converting a decoded XML back to XML, sometimes you get issues such as this and this. To fix this, simply add preserve_root=True on both decoding and encoding phase.

obj = schema.decode(xxx, preserve_root=True)
collection = schema.encode(obj, preserve_root=True)
collection

This code is based on the documentation.

SW.InterfaceSections_v5.xsd

Validates the Sections child element of Interface.

This schema is useful for creating multi instancedb.

For example:

<Interface>
	<Sections>
		<Section Name="Input" />
		<Section Name="Output" />
		<Section Name="InOut" />
		<Section Name="Static">
			<Member Name="Data_Point_Instance" Datatype="&quot;Data_Point&quot;" Accessibility="Public">
				<AttributeList>
					<BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute>
					<BooleanAttribute Name="ExternalVisible" SystemDefined="true">true</BooleanAttribute>
					<BooleanAttribute Name="ExternalWritable" SystemDefined="true">true</BooleanAttribute>
					<BooleanAttribute Name="UserVisible" Informative="true" SystemDefined="true">true</BooleanAttribute>
					<BooleanAttribute Name="UserReadOnly" Informative="true" SystemDefined="true">false</BooleanAttribute>
					<BooleanAttribute Name="UserDeletable" Informative="true" SystemDefined="true">true</BooleanAttribute>
					<BooleanAttribute Name="SetPoint" SystemDefined="true">true</BooleanAttribute>
				</AttributeList>
				<Sections>
					<Section Name="Input">
						<Member Name="Gate 2" Datatype="Bool" />
						<Member Name="Gate 1" Datatype="Bool" />
					</Section>
					<Section Name="Output">
						<Member Name="Open" Datatype="Bool" />
					</Section>
					<Section Name="InOut" />
					<Section Name="Static" />
				</Sections>
			</Member>
		</Section>
		<Section Name="Temp" />
		<Section Name="Constant" />
	</Sections>
</Interface>

If the element Section contains an attribute, the validation will fail.

FlgNet

Wires

Every network calls (instances) will always have a wire named "en".

...
<NameCon UId="21" Name="en" />
...

New wires will be created similar to "en" with its specific parameter name from the parts with the UId of the call.

...
<NameCon UId="21" Name="Wire 1" />
...

...
<NameCon UId="21" Name="Wire 2" />
...

...
<NameCon UId="21" Name="Wire 3" />
...

If a wire is not connected to anything, it will always have "OpenCon" in its element.

...
<OpenCon UId="23" />
<NameCon UId="21" Name="en" />
...

Wire "en" will always connect to a network call, thus it will never have "OpenCon" as its connection at the end.

Organization Block

In general, UIds for all attributes should be unique to avoid errors. An example of this error is There are at least two definitions for UIds. The incorrect unique ID is '132'.

Main Body
<?xml version="1.0" encoding="utf-8"?>
<Document>
	<SW.Blocks.OB ID="0">
		<AttributeList>
			<Name>$NAME</Name>
			<Namespace />
			<Number>$NUMBER</Number> (1)
			<ProgrammingLanguage>$PROGRAMMING_LANGUAGE</ProgrammingLanguage>
			<SecondaryType>ProgramCycle</SecondaryType>
		</AttributeList>
		<ObjectList>
			<MultilingualText ID="1" CompositionName="Comment">
				<ObjectList>
					<MultilingualTextItem ID="2" CompositionName="Items">
						<AttributeList>
							<Culture>en-US</Culture>
							<Text />
						</AttributeList>
					</MultilingualTextItem>
				</ObjectList>
			</MultilingualText>
			   <SW.Blocks.CompileUnit />  (2)
			<MultilingualText ID="D" CompositionName="Title">
				<ObjectList>
					<MultilingualTextItem ID="E" CompositionName="Items">
						<AttributeList>
							<Culture>en-US</Culture>
							<Text>"Main Program Sweep (Cycle)"</Text>
						</AttributeList>
					</MultilingualTextItem>
				</ObjectList>
			</MultilingualText>
		</ObjectList>
	</SW.Blocks.OB>
</Document>
1 Acceptable values must be within this range: 1; 123-32767.
2 Refer to this XML attribute: SW.Blocks.CompileUnit.
SW.Blocks.CompileUnit
<SW.Blocks.CompileUnit ID="$ID" CompositionName="CompileUnits">
	<AttributeList>
		<NetworkSource>
			<FlgNet
				xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4">
				<Parts>
					$PARTS
				</Parts>
				<Wires>
					<Wire /> (1)
				</Wires>
			</FlgNet>
		</NetworkSource>
		<ProgrammingLanguage>$PROGRAMMING_LANGUAGE</ProgrammingLanguage>
	</AttributeList>
</SW.Blocks.CompileUnit>
1 Refer to this XML attribute: Wire (First) or Wire.
Call
<Call UId="$UID">
	<CallInfo Name="$NAME" BlockType="$BLOCK_TYPE">
		<IntegerAttribute Name="BlockNumber" Informative="true">$BLOCK_NUMBER</IntegerAttribute>
		<Instance Scope="GlobalVariable" UId="$INSTANCE_UID">
			<Component Name="$COMPONENT_NAME" />
			<Address Area="DB" Type="$DB_TYPE" BlockNumber="$DB_BLOCK_NUMBER" BitOffset="0" Informative="true" />
		</Instance>
	</CallInfo>
</Call>
Wire (First)
<Wire UId="$UID">
	<Powerrail />
	<NameCon UId="$EN_UID" Name="en" /> (1)
</Wire>
1 Must be a value from a Call UId.
Wire
<Wire UId="$UID">
	<NameCon UId="$ENO_UID" Name="eno" />
	<NameCon UId="$EN_UID" Name="en" /> (1)
</Wire>
1 Must be a value from a Call UId.

Default XMLs

The base template of what’s needed when building your own XML.

Notice below that there are 5 common elements AttributeList:

  1. Interface

  2. Name

  3. Namespace

  4. Number

  5. ProgrammingLanguage

OB

<?xml version="1.0" encoding="utf-8"?>
<Document>
	<SW.Blocks.OB ID="0">
		<AttributeList>
			<Interface>
				<Sections
					xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
					<Section Name="Input">
						<Member Name="Initial_Call" Datatype="Bool" Informative="true">
							<Comment>
								<MultiLanguageText Lang="en-US">Initial call of this OB</MultiLanguageText>
							</Comment>
						</Member>
						<Member Name="Remanence" Datatype="Bool" Informative="true">
							<Comment>
								<MultiLanguageText Lang="en-US">=True, if remanent data are available</MultiLanguageText>
							</Comment>
						</Member>
					</Section>
					<Section Name="Temp" />
					<Section Name="Constant" />
				</Sections>
			</Interface>
			<Name>Main</Name>
			<Namespace />
			<Number>1</Number>
			<ProgrammingLanguage>LAD</ProgrammingLanguage>
			<SecondaryType>ProgramCycle</SecondaryType>
		</AttributeList>
		<ObjectList>
			<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
				<AttributeList>
					<NetworkSource />
					<ProgrammingLanguage>LAD</ProgrammingLanguage>
				</AttributeList>
			</SW.Blocks.CompileUnit>
		</ObjectList>
	</SW.Blocks.OB>
</Document>

FB

<?xml version="1.0" encoding="utf-8"?>
<Document>
	<SW.Blocks.FB ID="0">
		<AttributeList>
			<Interface>
				<Sections
					xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
					<Section Name="Input" />
					<Section Name="Output" />
					<Section Name="InOut" />
					<Section Name="Static" />
					<Section Name="Temp" />
					<Section Name="Constant" />
				</Sections>
			</Interface>
			<Name>FB_1</Name>
			<Namespace />
			<Number>1</Number>
			<ProgrammingLanguage>FBD</ProgrammingLanguage>
		</AttributeList>
		<ObjectList>
			<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
				<AttributeList>
					<NetworkSource />
					<ProgrammingLanguage>FBD</ProgrammingLanguage>
				</AttributeList>
			</SW.Blocks.CompileUnit>
		</ObjectList>
	</SW.Blocks.FB>
</Document>

FC

<?xml version="1.0" encoding="utf-8"?>
<Document>
	<SW.Blocks.FC ID="0">
		<AttributeList>
			<Interface>
				<Sections
					xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
					<Section Name="Input" />
					<Section Name="Output" />
					<Section Name="InOut" />
					<Section Name="Temp" />
					<Section Name="Constant" />
					<Section Name="Return">
						<Member Name="Ret_Val" Datatype="Void" />
					</Section>
				</Sections>
			</Interface>
			<Name>FC_1</Name>
			<Namespace />
			<Number>1</Number>
			<ProgrammingLanguage>FBD</ProgrammingLanguage>
		</AttributeList>
		<ObjectList>
			<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
				<AttributeList>
					<NetworkSource />
					<ProgrammingLanguage>FBD</ProgrammingLanguage>
				</AttributeList>
			</SW.Blocks.CompileUnit>
		</ObjectList>
	</SW.Blocks.FC>
</Document>

DB

GlobalDB
<?xml version="1.0" encoding="utf-8"?>
<Document>
	<SW.Blocks.GlobalDB ID="0">
		<AttributeList>
			<Interface>
				<Sections
					xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
					<Section Name="Static" />
				</Sections>
			</Interface>
			<Name>DB_1</Name>
			<Namespace />
			<Number>1</Number>
			<ProgrammingLanguage>DB</ProgrammingLanguage>
		</AttributeList>
		<ObjectList>
			<MultilingualText ID="3" CompositionName="Title">
				<ObjectList>
					<MultilingualTextItem ID="4" CompositionName="Items">
						<AttributeList>
							<Culture>en-US</Culture>
							<Text />
						</AttributeList>
					</MultilingualTextItem>
				</ObjectList>
			</MultilingualText>
		</ObjectList>
	</SW.Blocks.GlobalDB>
</Document>