Using XML substitution to manage complex deployments

Rationale

Problem: You deploy multiple configurations of your system, perhaps choosing between a real and simulated robot, some real and simulated device, etc. You want to parameterize the deployments to reduce the number of files you have to write for the varying configuration combinations

Solution: Use the XML ENTITY element.

Assumptions

  • Works with Xerces only (v2 tested, v3 should also support this). Will not work with the default TinyXML processor.

Compatabilitry

Tested on v1.x trunk on Mac OS X Snow Leopard. These instructions should apply identically to RTT 2.x installations.

Files

See the attachments at the bottom of this page.

Approach

This simple example demonstrates how to deploy a tiny system in two configurations, by simply changing the name of the deployed component. This approach can be (and has been) used to manage deployments with many system configurations.

There is a top-level file per configuration, which specifies all the parameters. Each top-level file then includes a child file which instantiates components, etc.

One top level file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "cpf.dtd"
[
  <!-- internal entities for substituion -->
  <!ENTITY name "Console">
  <!ENTITY lib "liborocos-rtt">
  <!-- external entity for file substitution -->
  <!ENTITY FILE_NAME SYSTEM "test-entity-child.xml">
]
>
 
<properties>
 
  &FILE_NAME;
 
</properties>

The internal entity values are used to substitute component names, and other basic parameters. The external entity value (&FILE_NAME) is used to include child files, so that the entity values defined in the top-level file are available within the child file. Using the Orocos' builtin include statement does not make the top-level entity values available within the child file.

The child file simply substitutes the two internal entities for a library name, and a component name.

<properties>
 
  <simple name="Import" type="string">
    <value>&lib;</value>
  </simple>
  <simple name="Import" type="string">
    <value>liborocos-ocl-common</value>
  </simple>
 
  <struct name="&name;" type="OCL::HMIConsoleOutput">
  </struct>
 
</properties>

The other top level file differs from the first top level file only in the name of the component.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "cpf.dtd"
[
  <!ENTITY name "Console2">
  <!ENTITY lib "liborocos-rtt">
  <!ENTITY file SYSTEM "test-entity-child.xml">
]
>
 
<properties>
 
  &file;
 
</properties>

You can use relative paths within the external entity filename. I have had inconsistent success with this - sometimes the relative path is needed, and other times it isn't. I think that it only needs the path relative to the file being included from, so if that file is already loaded on a relative path then you need to specify the child file only relative to the parent file, and not the current working directory that you started the deployment in.

AttachmentSize
test-entity.xml1.56 KB
test-entity2.xml278 bytes
test-entity-child.xml307 bytes