Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reference local schema files #535

Draft
wants to merge 9 commits into
base: sdf9
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 16 additions & 12 deletions sdf/1.7/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
set (sdfs
actor.sdf
air_pressure.sdf
altimeter.sdf
atmosphere.sdf
audio_source.sdf
audio_sink.sdf
battery.sdf
box_shape.sdf
camera.sdf
collision_engine.sdf
collision.sdf
contact.sdf
cylinder_shape.sdf
Expand All @@ -21,6 +23,7 @@ set (sdfs
imu.sdf
inertial.sdf
joint.sdf
lidar.sdf
light.sdf
light_state.sdf
link.sdf
Expand Down Expand Up @@ -52,26 +55,27 @@ set (sdfs
state.sdf
surface.sdf
transceiver.sdf
urdf.sdf
visual.sdf
world.sdf
)

set (SDF_SCHEMA)

foreach(FIL ${sdfs})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
set(root root.sdf)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make the same changes to the all the sdf/*/CMakeLists.txt?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

75b33b6 I've made the changes for until 1.5 since 1.4 and older do not print out the schemas


list(APPEND SDF_SCHEMA "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.xsd")
get_filename_component(ABS_FIL ${root} ABSOLUTE)
get_filename_component(FIL_WE ${root} NAME_WE)

add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.xsd"
COMMAND ${RUBY} ${CMAKE_SOURCE_DIR}/tools/xmlschema.rb
ARGS -s ${CMAKE_CURRENT_SOURCE_DIR} -i ${ABS_FIL} -o ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${ABS_FIL}
COMMENT "Running xml schema compiler on ${FIL}"
VERBATIM)
endforeach()
list(APPEND SDF_SCHEMA "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.xsd")

add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.xsd"
COMMAND ${RUBY} ${CMAKE_SOURCE_DIR}/tools/xmlschema.rb
ARGS -s ${CMAKE_CURRENT_SOURCE_DIR} -i ${ABS_FIL} -o ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${ABS_FIL}
COMMENT "Running xml schema compiler on ${root}"
VERBATIM)

add_custom_target(schema1_7 ALL DEPENDS ${SDF_SCHEMA})

Expand Down
7 changes: 4 additions & 3 deletions sdf/1.7/schema/types.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<xsd:simpleType name="vector3">
<xsd:restriction base="xsd:string">
<xsd:pattern value="(\s*(-|\+)?(\d+(\.\d*)?|\.\d+|\d+\.\d+[eE][-\+]?[0-9]+)\s+){2}((-|\+)?(\d+(\.\d*)?|\.\d+|\d+\.\d+[eE][-\+]?[0-9]+))\s*"/>
<xsd:pattern value="(\s*(-|\+)?(\d+(\.\d*)?|\.\d+|\d+\.\d+)([eE][-\+]?[0-9]+)?\s+){2}(-|\+)?(\d+(\.\d*)?|\.\d+|\d+\.\d+)([eE][-\+]?[0-9]+)?\s*"/>
</xsd:restriction>
</xsd:simpleType>

Expand All @@ -26,12 +26,13 @@

<xsd:simpleType name="pose">
<xsd:restriction base="xsd:string">
<xsd:pattern value="(\s*(-|\+)?(\d+(\.\d*)?|\.\d+|\d+\.\d+[eE][-\+]?[0-9]+)\s+){5}((-|\+)?(\d+(\.\d*)?|\.\d+|\d+\.\d+[eE][-\+]?[0-9]+))\s*"/>
<xsd:pattern value="(\s*(-|\+)?(\d+(\.\d*)?|\.\d+|\d+\.\d+)([eE][-\+]?[0-9]+)?\s+){5}(-|\+)?(\d+(\.\d*)?|\.\d+|\d+\.\d+)([eE][-\+]?[0-9]+)?\s*"/>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to update this for 1.7 and up because <pose/> is now valid.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated 1.7 to accept <pose/>: 75b33b6

Also updated 1.5 & 1.6 regex for pose (does not accept <pose/>) and vector3d

</xsd:restriction>
</xsd:simpleType>

<xsd:simpleType name="time">
<xsd:restriction base="xsd:double">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\s*\d+\s+\d+\s*"/>
</xsd:restriction>
</xsd:simpleType>

Expand Down
99 changes: 68 additions & 31 deletions tools/xmlschema.rb
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require "rexml/document"
require "optparse"
require "set"

$path = nil

Expand Down Expand Up @@ -72,13 +73,22 @@ def printElem(_file, _spaces, _elem)
printDocumentation(_file, _spaces+2, _elem.elements["description"].text)
end

_file.printf("%*s<xsd:complexType>\n", _spaces+2, "")
if _elem.attributes['name'] == "pose"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't encounter pose here because it has type='pose'

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed 75b33b6

_file.printf("%*s<xsd:complexType mixed='true'>\n", _spaces+2, "")
else
_file.printf("%*s<xsd:complexType>\n", _spaces+2, "")
end

_file.printf("%*s<xsd:choice maxOccurs='unbounded'>\n", _spaces+4, "")

_elem.get_elements("element").each do |elem|
printElem(_file, _spaces+6, elem)
end

_elem.get_elements("include").each do |inc|
printInclude(_file, _spaces+6, inc)
end

_file.printf("%*s</xsd:choice>\n", _spaces+4, "")

# Print the attributes for the complex type
Expand All @@ -89,18 +99,43 @@ def printElem(_file, _spaces, _elem)

_file.printf("%*s</xsd:complexType>\n", _spaces+2, "")
else
_file.printf("%*s<xsd:element name='%s' type='%s'>\n",
_spaces, "", _elem.attributes["name"], type)

attributes = _elem.get_elements("attribute")
hasAttributes = attributes.size > 0

if hasAttributes
_file.printf("%*s<xsd:element name='%s'>\n",
_spaces, "", _elem.attributes["name"])
else
_file.printf("%*s<xsd:element name='%s' type='%s'>\n",
_spaces, "", _elem.attributes["name"], type)
end

if !_elem.elements["description"].nil? &&
!_elem.elements["description"].text.nil?
printDocumentation(_file, _spaces+2, _elem.elements["description"].text)
end

if hasAttributes
_file.printf("%*s<xsd:complexType>\n", _spaces+2, "")
_file.printf("%*s<xsd:simpleContent>\n", _spaces+4, "")
_file.printf("%*s<xsd:extension base='%s'>\n", _spaces+6, "", type)

# Print the attributes for the complex type
# Attributes must go at the end of the complex type.
attributes.each do |attr|
printAttribute(_file, _spaces+8, attr);
end

_file.printf("%*s</xsd:extension>\n", _spaces+6, "")
_file.printf("%*s</xsd:simpleContent>\n", _spaces+4, "")
_file.printf("%*s</xsd:complexType>\n", _spaces+2, "")
end

end

_file.printf("%*s</xsd:element>\n", _spaces, "")
_file.printf("%*s</xsd:choice>\n", _spaces, "")

end

#################################################
Expand All @@ -121,18 +156,14 @@ def printDocumentation(_file, _spaces, _doc)
end

#################################################
def printIncludeRef(_file, _spaces, _inc)
path = File.join($path, _inc.attributes["filename"])
doc = REXML::Document.new File.new(path)
incElemName = doc.root.attributes['name']
_file.printf("%*s<xsd:element ref='%s'/>\n", _spaces, "", incElemName)
end

#################################################
# Prints XSD contents of <include>
def printInclude(_file, _spaces, _attr)
loc = "http://sdformat.org/schemas/"
loc += _attr.attributes['filename'].sub("\.sdf","\.xsd")
_file.printf("%*s<xsd:include schemaLocation='%s'/>\n", _spaces, "", loc)
loc = $path + "/" + _attr.attributes['filename']
doc = REXML::Document.new File.new(loc)

doc.elements.each_with_index("element") do |elem, i|
printXSD(_file, _spaces+2, elem)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if we should use printElem instead of printXSD here so that the pose element gets the pose type. Right now this is what it generates

<xsd:element name='pose'>
  <xsd:annotation>
    <xsd:documentation xml:lang='en'>
      <![CDATA[A position(x,y,z) and orientation(roll, pitch yaw) with respect to the frame named in the relative_to attribute.]]>
    </xsd:documentation>
  </xsd:annotation>
  <xsd:complexType mixed='true'>
    <xsd:attribute name='relative_to' type='xsd:string'  >
      <xsd:annotation>
        <xsd:documentation xml:lang='en'>
          <![CDATA[
Name of frame relative to which the pose is applied.
]]>
        </xsd:documentation>
      </xsd:annotation>
    </xsd:attribute>
  </xsd:complexType>
</xsd:element>

(1) We have <xsd:complexType mixed='true'> which indicate that <pose> can have child elements, which is not currently true
(2). The xsd type pose is not used at all so it is not validating based on the regex. You can try this by trying to validate 1.0` in an sdf file. It passes currently.

When using printElem, it generates:

<xsd:element name='pose'>
  <xsd:annotation>
    <xsd:documentation xml:lang='en'>
      <![CDATA[A position(x,y,z) and orientation(roll, pitch yaw) with respect to the frame named in the relative_to attribute.]]>
    </xsd:documentation>
  </xsd:annotation>
  <xsd:complexType>
    <xsd:simpleContent>
      <xsd:extension base='pose'>
        <xsd:attribute name='relative_to' type='xsd:string'  >
          <xsd:annotation>
            <xsd:documentation xml:lang='en'>
              <![CDATA[
Name of frame relative to which the pose is applied.
]]>
            </xsd:documentation>
          </xsd:annotation>
        </xsd:attribute>
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>
</xsd:element>

This extends the pose type, so validation works properly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! 75b33b6

end
end

#################################################
Expand Down Expand Up @@ -176,27 +207,24 @@ def printAttribute(_file, _spaces, _attr)
# \param[in] _elem The SDF element to convert to an xml schema.
def printXSD(_file, _spaces, _elem)

if !_elem.elements["description"].nil? &&
!_elem.elements["description"].text.nil?
printDocumentation(_file, _spaces, _elem.elements["description"].text)
end

_file.printf("%*s<xsd:include schemaLocation='http://sdformat.org/schemas/types.xsd'/>\n", _spaces, "")

# Print the inclues for the complex type
# The includes must appear first
_elem.get_elements("include").each do |inc|
printInclude(_file, _spaces, inc);
end

if _elem.get_elements("element").size > 0 ||
_elem.get_elements("attribute").size > 0 ||
_elem.get_elements("include").size > 0

# Print the complex type with a name
_file.printf("%*s<xsd:element name='%s'>\n", _spaces, "",
_elem.attributes["name"])
_file.printf("%*s<xsd:complexType>\n", _spaces+2, "")

if !_elem.elements["description"].nil? &&
!_elem.elements["description"].text.nil?
printDocumentation(_file, _spaces+2, _elem.elements["description"].text)
end

if _elem.attributes['name'] == "pose"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use printElem as I suggested, I'm not sure if we need a special treatment of pose here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed 75b33b6

_file.printf("%*s<xsd:complexType mixed='true'>\n", _spaces+2, "")
else
_file.printf("%*s<xsd:complexType>\n", _spaces+2, "")
end

if _elem.attributes['name'] != "plugin" &&
(_elem.get_elements("element").size > 0 ||
Expand All @@ -209,10 +237,11 @@ def printXSD(_file, _spaces, _elem)
printElem(_file, _spaces+6, elem);
end

# Print all the included sdf's root elements
# print XSD of <include> element
_elem.get_elements("include").each do |inc|
printIncludeRef(_file, _spaces+6, inc);
printInclude(_file, _spaces+4, inc);
end

if _elem.attributes['name'] != "plugin" &&
(_elem.get_elements("element").size > 0 ||
_elem.get_elements("include").size > 0)
Expand Down Expand Up @@ -295,6 +324,14 @@ def printXSD(_file, _spaces, _elem)
file.print("<?xml version='1.0' encoding='UTF-8'?>\n")
file.print("<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>\n")

# drop xml header
File.readlines("#{$path}/schema/types.xsd").drop(1).each do |line|
# skip root <schema> element
if !line.include? "xsd:schema"
file.printf("%*s#{line}", spaces-2, "")
end
end

printXSD(file, spaces, elem)

file.print("</xsd:schema>\n")
Expand Down