Skip to content

Instantly share code, notes, and snippets.

@nalt
Last active June 25, 2023 17:25
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save nalt/dfa2abc9d2e3ae4feb82ca5608090387 to your computer and use it in GitHub Desktop.
Save nalt/dfa2abc9d2e3ae4feb82ca5608090387 to your computer and use it in GitHub Desktop.
Roslaunch XML schema, DTD and XSD
<?xml version="1.0" ?>
<!DOCTYPE launch SYSTEM "https://gist.githubusercontent.com/nalt/dfa2abc9d2e3ae4feb82ca5608090387/raw/roslaunch.dtd">
<launch>
<!-- Enjoy code completion and validation in some IDEs/editors, such as IntelliJ -->
</launch>
<?xml version="1.0" ?>
<launch xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://gist.githubusercontent.com/nalt/dfa2abc9d2e3ae4feb82ca5608090387/raw/roslaunch.xsd">
<!-- Enjoy code completion and validation in some IDEs/editors, e.g. Atom or IntelliJ -->
</launch>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Not updated, not complete. Use XSD. -->
<!ELEMENT launch (node|machine|include|remap|env|param|rosparam|group|test|arg)* >
<!ENTITY % attrs
"if CDATA #IMPLIED
unless CDATA #IMPLIED
">
<!ELEMENT arg EMPTY>
<!ATTLIST arg
%attrs;
name CDATA #REQUIRED
value CDATA #IMPLIED
default CDATA #IMPLIED
doc CDATA #IMPLIED
>
<!ELEMENT env EMPTY>
<!ATTLIST env
%attrs;
name CDATA #REQUIRED
value CDATA #REQUIRED
>
<!ELEMENT group (node|machine|include|remap|env|param|rosparam|test|arg)*>
<!ATTLIST group
%attrs;
ns CDATA #IMPLIED
clear_params (true|false) #IMPLIED
>
<!ELEMENT include (env|arg)*>
<!ATTLIST include
%attrs;
file CDATA #REQUIRED
ns CDATA #IMPLIED
env-loader CDATA #IMPLIED
clear_params (true|false) #IMPLIED
pass_all_args (true|false) #IMPLIED
>
<!ELEMENT node (env|remap|rosparam|param)*>
<!ATTLIST node
%attrs;
pkg CDATA #REQUIRED
type CDATA #REQUIRED
name CDATA #IMPLIED
args CDATA #IMPLIED
machine CDATA #IMPLIED
respawn (true|false) #IMPLIED
respawn_delay CDATA #IMPLIED
required (true) #IMPLIED
clear_params (true|false) #IMPLIED
output (log|screen) #IMPLIED
cwd (ROS_HOME|node) #IMPLIED
launch-prefix CDATA #IMPLIED
ns CDATA #IMPLIED
>
<!ELEMENT test (env|remap|rosparam|param)*>
<!ATTLIST test
%attrs;
pkg CDATA #REQUIRED
type CDATA #REQUIRED
test-name CDATA #REQUIRED
name CDATA #IMPLIED
args CDATA #IMPLIED
clear_params (true|false) #IMPLIED
cwd (ROS_HOME|node) #IMPLIED
launch-prefix CDATA #IMPLIED
ns CDATA #IMPLIED
retry CDATA #IMPLIED
time-limit CDATA #IMPLIED
>
<!ELEMENT machine (env)*>
<!ATTLIST machine
%attrs;
name CDATA #REQUIRED
address CDATA #REQUIRED
env-loader CDATA #IMPLIED
default (true|false|never) #IMPLIED
user CDATA #IMPLIED
password CDATA #IMPLIED
timeout CDATA #IMPLIED
>
<!ELEMENT param EMPTY>
<!ATTLIST param
%attrs;
name CDATA #REQUIRED
value CDATA #IMPLIED
type (string|str|int|double|bool|yaml) #IMPLIED
textfile CDATA #IMPLIED
binfile CDATA #IMPLIED
command CDATA #IMPLIED
>
<!ELEMENT remap EMPTY>
<!ATTLIST remap
%attrs;
from CDATA #REQUIRED
to CDATA #REQUIRED
>
<!ELEMENT rosparam (#PCDATA)*>
<!ATTLIST rosparam
%attrs;
command CDATA #IMPLIED
file CDATA #IMPLIED
param CDATA #IMPLIED
ns CDATA #IMPLIED
subst_value (true|false) #IMPLIED
>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="SubstitutionType">
<xs:restriction base="xs:string">
<xs:pattern value="$\(anon .*|$\(arg .*|$\(dirname .*|$\(env .*|$\(eval .*|$\(find .*|$\(optenv .*"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="BoolType">
<xs:union memberTypes="SubstitutionType">
<xs:simpleType>
<xs:restriction base='xs:string'>
<xs:enumeration value='true'/>
<xs:enumeration value='false'/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
<xs:simpleType name="StringType">
<xs:union memberTypes="SubstitutionType">
<xs:simpleType>
<xs:restriction base='xs:string'>
<xs:pattern value="[^$].*" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base='xs:string'>
<xs:enumeration value=''/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
<xs:element name='launch'>
<xs:complexType>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element ref='node'/>
<xs:element ref='machine'/>
<xs:element ref='include'/>
<xs:element ref='remap'/>
<xs:element ref='env'/>
<xs:element ref='param'/>
<xs:element ref='rosparam'/>
<xs:element ref='group'/>
<xs:element ref='test'/>
<xs:element ref='arg'/>
</xs:choice>
<xs:attribute name='deprecated' type='StringType'/>
</xs:complexType>
</xs:element>
<xs:element name='arg'>
<xs:annotation>
<xs:documentation>
Specifies arguments passed via command-line, via an include, or declared for higher-level files.
Args are not global. Use $(arg name) to read an argument.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name='if' type='StringType'/>
<xs:attribute name='unless' type='StringType'/>
<xs:attribute name='name' type='StringType' use='required'/>
<xs:attribute name='value' type='StringType'/>
<xs:attribute name='default' type='StringType'/>
<xs:attribute name='doc' type='StringType'/>
</xs:complexType>
</xs:element>
<xs:element name='env'>
<xs:annotation>
<xs:documentation>
Set environment variables on nodes that are launched.
When used inside of launch tag, only applies to nodes declared after.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name='if' type='StringType'/>
<xs:attribute name='unless' type='StringType'/>
<xs:attribute name='name' type='StringType' use='required'/>
<xs:attribute name='value' type='StringType' use='required'/>
</xs:complexType>
</xs:element>
<xs:element name='group'>
<xs:complexType>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element ref='group'/>
<xs:element ref='node'/>
<xs:element ref='machine'/>
<xs:element ref='include'/>
<xs:element ref='remap'/>
<xs:element ref='env'/>
<xs:element ref='param'/>
<xs:element ref='rosparam'/>
<xs:element ref='test'/>
<xs:element ref='arg'/>
</xs:choice>
<xs:attribute name='if' type='StringType'/>
<xs:attribute name='unless' type='StringType'/>
<xs:attribute name='ns' type='StringType'/>
<xs:attribute name='clear_params' type="BoolType"/>
</xs:complexType>
</xs:element>
<xs:element name='include'>
<xs:complexType>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element ref='env'/>
<xs:element ref='arg'/>
</xs:choice>
<xs:attribute name='if' type='StringType'/>
<xs:attribute name='unless' type='StringType'/>
<xs:attribute name='file' type='StringType' use='required'/>
<xs:attribute name='ns' type='StringType'/>
<xs:attribute name='env-loader' type='StringType'/>
<xs:attribute name='clear_params' type="BoolType"/>
<xs:attribute name='pass_all_args' type="BoolType"/>
</xs:complexType>
</xs:element>
<xs:element name='node'>
<xs:complexType>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element ref='env'/>
<xs:element ref='remap'/>
<xs:element ref='rosparam'/>
<xs:element ref='param'/>
</xs:choice>
<xs:attribute name='if' type='StringType'/>
<xs:attribute name='unless' type='StringType'/>
<xs:attribute name='pkg' type='StringType' use='required'/>
<xs:attribute name='type' type='StringType' use='required'/>
<xs:attribute name='name' type='StringType'/>
<xs:attribute name='args' type='StringType'/>
<xs:attribute name='machine' type='StringType'/>
<xs:attribute name='respawn' type="BoolType"/>
<xs:attribute name='respawn_delay' type='StringType'/>
<xs:attribute name='required' type="BoolType"/>
<xs:attribute name='clear_params' type="BoolType"/>
<xs:attribute name='output'>
<xs:simpleType>
<xs:union memberTypes="SubstitutionType">
<xs:simpleType>
<xs:restriction base='xs:string'>
<xs:enumeration value='log'/>
<xs:enumeration value='screen'/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:attribute>
<xs:attribute name='cwd'>
<xs:simpleType>
<xs:union memberTypes="SubstitutionType">
<xs:simpleType>
<xs:restriction base='xs:string'>
<xs:enumeration value='ROS_HOME'/>
<xs:enumeration value='node'/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:attribute>
<xs:attribute name='launch-prefix' type='StringType'/>
<xs:attribute name='ns' type='StringType'/>
</xs:complexType>
</xs:element>
<xs:element name='test'>
<xs:complexType>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element ref='env'/>
<xs:element ref='remap'/>
<xs:element ref='rosparam'/>
<xs:element ref='param'/>
</xs:choice>
<xs:attribute name='if' type='StringType'/>
<xs:attribute name='unless' type='StringType'/>
<xs:attribute name='pkg' type='StringType' use='required'/>
<xs:attribute name='type' type='StringType' use='required'/>
<xs:attribute name='test-name' type='StringType' use='required'/>
<xs:attribute name='name' type='StringType'/>
<xs:attribute name='args' type='StringType'/>
<xs:attribute name='clear_params' type="BoolType"/>
<xs:attribute name='cwd'>
<xs:simpleType>
<xs:union memberTypes="SubstitutionType">
<xs:simpleType>
<xs:restriction base='xs:string'>
<xs:enumeration value='ROS_HOME'/>
<xs:enumeration value='node'/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:attribute>
<xs:attribute name='launch-prefix' type='StringType'/>
<xs:attribute name='ns' type='StringType'/>
<xs:attribute name='retry' type='StringType'/>
<xs:attribute name='time-limit' type='StringType'/>
</xs:complexType>
</xs:element>
<xs:element name='machine'>
<xs:complexType>
<xs:sequence minOccurs='0' maxOccurs='unbounded'>
<xs:element ref='env'/>
</xs:sequence>
<xs:attribute name='if' type='StringType'/>
<xs:attribute name='unless' type='StringType'/>
<xs:attribute name='name' type='StringType' use='required'/>
<xs:attribute name='address' type='StringType' use='required'/>
<xs:attribute name='env-loader' type='StringType'/>
<xs:attribute name='default'>
<xs:simpleType>
<xs:union memberTypes="BoolType">
<xs:simpleType>
<xs:restriction base='xs:string'>
<xs:enumeration value='never'/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:attribute>
<xs:attribute name='user' type='StringType'/>
<xs:attribute name='password' type='StringType'/>
<xs:attribute name='timeout' type='StringType'/>
</xs:complexType>
</xs:element>
<xs:element name='param'>
<xs:annotation>
<xs:documentation>
Defines parameter to be set on the Parameter Server as given value, from textfile, binfile or command output.
Inside of a node tag, parameter is treated as a private.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name='if' type='StringType'/>
<xs:attribute name='unless' type='StringType'/>
<xs:attribute name='name' type='StringType' use='required'/>
<xs:attribute name='value' type='StringType'/>
<xs:attribute name='type'>
<xs:simpleType>
<xs:restriction base='xs:string'>
<xs:enumeration value='string'/>
<xs:enumeration value='str'/>
<xs:enumeration value='int'/>
<xs:enumeration value='double'/>
<xs:enumeration value='bool'/>
<xs:enumeration value='yaml'/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name='textfile' type='StringType'/>
<xs:attribute name='binfile' type='StringType'/>
<xs:attribute name='command' type='StringType'/>
</xs:complexType>
</xs:element>
<xs:element name='remap'>
<xs:complexType>
<xs:attribute name='if' type='StringType'/>
<xs:attribute name='unless' type='StringType'/>
<xs:attribute name='from' type='StringType' use='required'/>
<xs:attribute name='to' type='StringType' use='required'/>
</xs:complexType>
</xs:element>
<xs:element name='rosparam'>
<xs:annotation>
<xs:documentation>
Enables rosparam YAML files for loading and dumping parameters to/from Parameter Server.
Can also be used to remove parameters.
Can either reference a YAML file or contain raw YAML text.
If the YAML defines a dictionary, param attribute may be omitted.
</xs:documentation>
</xs:annotation>
<xs:complexType mixed='true'>
<xs:attribute name='if' type='StringType'/>
<xs:attribute name='unless' type='StringType'/>
<xs:attribute name='command' type='StringType'/>
<xs:attribute name='file' type='StringType'/>
<xs:attribute name='param' type='StringType'/>
<xs:attribute name='ns' type='StringType'/>
<xs:attribute name='subst_value' type="BoolType"/>
</xs:complexType>
</xs:element>
</xs:schema>
wget https://gist.githubusercontent.com/nalt/dfa2abc9d2e3ae4feb82ca5608090387/raw/roslaunch.dtd
find /opt/ros -iname '*.launch' -exec xmllint --valid --dtdvalid roslaunch.dtd --noout {} ';' 2>&1 | grep -v "no DTD found" | grep -v '<launch>'
# Missing DOCTYPE is reported as an error.
# $(...) will be rejected by this DTD for enum attributes
wget https://gist.githubusercontent.com/nalt/dfa2abc9d2e3ae4feb82ca5608090387/raw/roslaunch.xsd
find /opt/ros -iname '*.launch' -exec xmllint -schema roslaunch.xsd --noout {} ';'
# $(...) will be rejected
@nalt
Copy link
Author

nalt commented Jan 5, 2018

XML schema (XSD) ans DTD for Roslaunch files. The XSD should be prefered.

Code completion was tested with IntelliJ and Atom with autocomplete-xml.

Issues:

  • $(arg ...) is not allowed in enum attributes

  • group is not allowed within group, but this is often done

  • <param type=string> is often used, but it should be str

@bergercookie
Copy link

This is awesome, thanks!!
I can confirm this also works in vim/neovim with the coc-xml plugin

@bergercookie
Copy link

Please consider adding a license file (MIT?) to make it clear that people can use it in their day to day development freely.

@SubaruArai
Copy link

SubaruArai commented Apr 12, 2022

@nalt First of all, great work and thank you a lot!

Just reporting 2 problems:

  1. as @bergercookie stated, please add a license
  2. line 5 in roslaunch.xsd has a bug:
$\(dirname .*

should be:

$\(dirname\).*

@SubaruArai
Copy link

@nalt
Just forked and changed that line (gist can't do pull requests):
https://gist.github.com/SubaruArai/957b7e2ebe212eb2a07d26a73f9a31c3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment