ruby3mf 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/batch.rb +22 -21
- data/bin/cli.rb +3 -0
- data/bin/suite_test.sh +39 -0
- data/lib/ruby3mf.rb +1 -0
- data/lib/ruby3mf/{3MFcoreSpec_1.1.xsd → 3MFcoreSpec_1.1.xsd.template} +1 -1
- data/lib/ruby3mf/content_types.rb +11 -3
- data/lib/ruby3mf/document.rb +29 -4
- data/lib/ruby3mf/errors.yml +20 -1
- data/lib/ruby3mf/log3mf.rb +5 -2
- data/lib/ruby3mf/model3mf.rb +1 -4
- data/lib/ruby3mf/relationships.rb +1 -0
- data/lib/ruby3mf/schema_files.rb +12 -0
- data/lib/ruby3mf/version.rb +1 -1
- data/lib/ruby3mf/xml.xsd +286 -0
- data/lib/ruby3mf/xml_val.rb +12 -5
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d2f6346320579794b80cb51d43cc89d2bfe62c5
|
4
|
+
data.tar.gz: 69c77fd6fe56952bc7e66b7bb0d8c113dbc35fc8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56d2dbe4baa8689c8eaa1f227a407c960204f820d27c5f907d3b0201baa8c3b5a96c05f25abb4f8f6d4df88fc6b8975ec74d774c2972c8b4d0d8de7a8c556945
|
7
|
+
data.tar.gz: 7c934b3b61c37585696697e644fb63d4ffe516d07e5f10c7fde335baac6e2b879db3de0c6d91c6a1574432bb053de3d69289986f4ad63952b742a63172178d2c
|
data/bin/batch.rb
CHANGED
@@ -1,21 +1,22 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require_relative '../lib/ruby3mf'
|
4
|
-
|
5
|
-
files = Dir["spec/ruby3mf-testfiles/#{ARGV[0] || "failing_cases"}/*.#{ARGV[1] || '3mf'}"]
|
6
|
-
|
7
|
-
files.each do |file|
|
8
|
-
begin
|
9
|
-
Log3mf.reset_log
|
10
|
-
doc = Document.read(file)
|
11
|
-
errors = Log3mf.entries(:error, :fatal_error)
|
12
|
-
|
13
|
-
puts "=" * 100
|
14
|
-
puts "Validating file: #{file}"
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/ruby3mf'
|
4
|
+
|
5
|
+
files = Dir["spec/ruby3mf-testfiles/#{ARGV[0] || "failing_cases"}/*.#{ARGV[1] || '3mf'}"]
|
6
|
+
|
7
|
+
files.each do |file|
|
8
|
+
begin
|
9
|
+
Log3mf.reset_log
|
10
|
+
doc = Document.read(file)
|
11
|
+
errors = Log3mf.entries(:error, :fatal_error)
|
12
|
+
|
13
|
+
puts "=" * 100
|
14
|
+
puts "Validating file: #{file}"
|
15
|
+
|
16
|
+
errors.each do |ent|
|
17
|
+
h = { context: ent[0], severity: ent[1], message: ent[2] }
|
18
|
+
puts h
|
19
|
+
end
|
20
|
+
rescue
|
21
|
+
end
|
22
|
+
end
|
data/bin/cli.rb
CHANGED
data/bin/suite_test.sh
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
MATCH=$1
|
4
|
+
OUTFILE=suite_test.txt
|
5
|
+
GOOD_FILES=../3mf-test-suite/Positive/${MATCH}*.3mf
|
6
|
+
BAD_FILES=../3mf-test-suite/Negative/${MATCH}*.3mf
|
7
|
+
|
8
|
+
echo "Test Suite: filter: ${MATCH}"
|
9
|
+
printf "\n\nTest Suite: filter: ${MATCH} - $(date)\n" >> ${OUTFILE}
|
10
|
+
|
11
|
+
echo "Positive Files -------------"
|
12
|
+
printf "\nPositive Files -------------\n" >> ${OUTFILE}
|
13
|
+
for filename in ${GOOD_FILES}; do
|
14
|
+
if [ -f ${filename} ]; then
|
15
|
+
echo " Validating ${filename}"
|
16
|
+
result=$(( ~/src/ruby3mf/bin/cli.rb ${filename} ) 2>&1)
|
17
|
+
if [ $? -ne 0 ]; then
|
18
|
+
echo " Failed!"
|
19
|
+
printf " ${filename}\n $result\n" >> ${OUTFILE}
|
20
|
+
fi
|
21
|
+
fi
|
22
|
+
done
|
23
|
+
|
24
|
+
echo "Negative Files -------------"
|
25
|
+
printf "\nNegative Files -------------\n" >> suite_test.txt
|
26
|
+
for filename in ${BAD_FILES}; do
|
27
|
+
if [ -f ${filename} ]; then
|
28
|
+
echo " Validating ${filename}"
|
29
|
+
result=$(( ~/src/ruby3mf/bin/cli.rb ${filename} ) 2>&1)
|
30
|
+
if [ $? -eq 0 ]; then
|
31
|
+
echo " Passed!"
|
32
|
+
printf " ${filename} - No Errors found!\n" >> ${OUTFILE}
|
33
|
+
fi
|
34
|
+
fi
|
35
|
+
done
|
36
|
+
|
37
|
+
echo "All Done."
|
38
|
+
printf "Completed -- $(date)\n\n" >> ${OUTFILE}
|
39
|
+
|
data/lib/ruby3mf.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
targetNamespace="http://schemas.microsoft.com/3dmanufacturing/core/2015/02" elementFormDefault="unqualified"
|
4
4
|
attributeFormDefault="unqualified" blockDefault="#all">
|
5
5
|
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
|
6
|
-
schemaLocation="
|
6
|
+
schemaLocation= "<%= SchemaFiles::SchemaLocation %>" />
|
7
7
|
<xs:annotation>
|
8
8
|
<xs:documentation><![CDATA[
|
9
9
|
Schema notes:
|
@@ -2,6 +2,7 @@ class ContentTypes
|
|
2
2
|
|
3
3
|
def self.parse(zip_entry)
|
4
4
|
found_types={}
|
5
|
+
found_overrides={}
|
5
6
|
|
6
7
|
Log3mf.context "parse" do |l|
|
7
8
|
begin
|
@@ -18,13 +19,20 @@ class ContentTypes
|
|
18
19
|
types_node = doc.children.first
|
19
20
|
types_node.children.each do |node|
|
20
21
|
l.context node.name do |l|
|
21
|
-
|
22
|
-
l.warning "[Content_Types].xml:#{node.line} contains unexpected element #{node.name}", page: 10
|
23
|
-
else
|
22
|
+
if node.name == 'Default'
|
24
23
|
# l.error "[Content_Types].xml:#{node.line} contains Default node without defined Extension attribute" unless node['Extension'].is_a? String
|
25
24
|
# l.error "[Content_Types].xml:#{node.line} contains Default node with unexpected ContentType \"#{node['ContentType']}\"", page: 10 unless all_types.include? node['ContentType']
|
26
25
|
l.info "Setting type hash #{node['Extension']}=#{node['ContentType']}"
|
26
|
+
|
27
|
+
l.error :duplicate_content_extension_types if !found_types[node['Extension']].nil?
|
27
28
|
found_types[node['Extension']] = node['ContentType']
|
29
|
+
elsif node.name == 'Override'
|
30
|
+
l.error :empty_override_part_name if node['PartName'].empty?
|
31
|
+
|
32
|
+
l.error :duplicate_content_override_types if !found_overrides[node['PartName']].nil?
|
33
|
+
found_overrides[node['PartName']] = node['ContentType']
|
34
|
+
else
|
35
|
+
l.warning "[Content_Types].xml:#{node.line} contains unexpected element #{node.name}", page: 10
|
28
36
|
end
|
29
37
|
end
|
30
38
|
end
|
data/lib/ruby3mf/document.rb
CHANGED
@@ -15,6 +15,18 @@ class Document
|
|
15
15
|
TEXTURE_TYPE = 'http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture'
|
16
16
|
PRINT_TICKET_TYPE = 'http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket'
|
17
17
|
|
18
|
+
# Image Content Types
|
19
|
+
THUMBNAIL_TYPES = %w[image/jpeg image/png].freeze
|
20
|
+
TEXTURE_TYPES = %w[image/jpeg image/png application/vnd.ms-package.3dmanufacturing-3dmodeltexture].freeze
|
21
|
+
|
22
|
+
# Relationship to valid Content types
|
23
|
+
REL_TO_CONTENT_TYPES = {
|
24
|
+
MODEL_TYPE => 'application/vnd.ms-package.3dmanufacturing-3dmodel+xml',
|
25
|
+
PRINT_TICKET_TYPE => 'application/vnd.ms-printing.printticket+xml',
|
26
|
+
TEXTURE_TYPE => TEXTURE_TYPES,
|
27
|
+
THUMBNAIL_TYPE => THUMBNAIL_TYPES
|
28
|
+
}
|
29
|
+
|
18
30
|
# Relationship Type => Class validating relationship type
|
19
31
|
RELATIONSHIP_TYPES = {
|
20
32
|
MODEL_TYPE => {klass: 'Model3mf', collection: :models},
|
@@ -23,15 +35,13 @@ class Document
|
|
23
35
|
PRINT_TICKET_TYPE => {}
|
24
36
|
}
|
25
37
|
|
26
|
-
TEXTURE_TYPES = %w[image/jpeg image/png application/vnd.ms-package.3dmanufacturing-3dmodeltexture]
|
27
|
-
|
28
38
|
def initialize(zip_filename)
|
29
39
|
self.models=[]
|
30
40
|
self.thumbnails=[]
|
31
41
|
self.textures=[]
|
32
42
|
self.objects={}
|
33
43
|
self.relationships={}
|
34
|
-
self.types=
|
44
|
+
self.types={}
|
35
45
|
self.parts=[]
|
36
46
|
@zip_filename = zip_filename
|
37
47
|
end
|
@@ -96,10 +106,11 @@ class Document
|
|
96
106
|
if content_type_match
|
97
107
|
m.types = ContentTypes.parse(content_type_match)
|
98
108
|
model_extension = m.types.key('application/vnd.ms-package.3dmanufacturing-3dmodel+xml')
|
109
|
+
model_extension = model_extension.downcase unless model_extension.nil?
|
99
110
|
model_file = zip_file.glob("**/*.#{model_extension}").first
|
100
111
|
l.error :no_3d_model, extension: model_extension if model_file.nil?
|
101
112
|
else
|
102
|
-
l.
|
113
|
+
l.fatal_error 'Missing required file: [Content_Types].xml', page: 4
|
103
114
|
end
|
104
115
|
end
|
105
116
|
|
@@ -136,6 +147,20 @@ class Document
|
|
136
147
|
l.error :err_uri_relative_path if target.include? '/../'
|
137
148
|
relationship_file = zip_file.glob(target).first
|
138
149
|
|
150
|
+
# check that relationships are valid; extensions and relationship types must jive
|
151
|
+
extension = File.extname(target).strip.downcase[1..-1]
|
152
|
+
|
153
|
+
content_type = m.types[extension]
|
154
|
+
rel_type = rel[:type]
|
155
|
+
expected_content_type = REL_TO_CONTENT_TYPES[rel_type]
|
156
|
+
|
157
|
+
if (expected_content_type)
|
158
|
+
l.error :missing_extension_in_content_types, ext: extension unless content_type
|
159
|
+
l.error :resource_contentype_invalid, bt: content_type, rt: rel[:target] unless (!content_type.nil? && expected_content_type.include?(content_type))
|
160
|
+
else
|
161
|
+
l.info "found unrecognized relationship type: #{rel_type}"
|
162
|
+
end
|
163
|
+
|
139
164
|
if relationship_file
|
140
165
|
relationship_type = RELATIONSHIP_TYPES[rel[:type]]
|
141
166
|
if relationship_type.nil?
|
data/lib/ruby3mf/errors.yml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
resource_contentype_invalid:
|
2
|
-
msg: "
|
2
|
+
msg: "Relationship target %{rt} resource has invalid contenttype %{bt}"
|
3
3
|
page: 10
|
4
4
|
err_uri_empty_segment:
|
5
5
|
msg: 'No segment of a 3MF part name path may be empty'
|
@@ -70,12 +70,19 @@ invalid_texture_file_type:
|
|
70
70
|
missing_content_types:
|
71
71
|
msg: "Missing required file: [Content_Types].xml"
|
72
72
|
page: 4
|
73
|
+
missing_extension_in_content_types:
|
74
|
+
msg: "Missing extension '%{ext}' in [Content_Types].xml"
|
75
|
+
page: 10
|
73
76
|
missing_dot_rels_file:
|
74
77
|
msg: "Missing required file _rels/.rels"
|
75
78
|
page: 4
|
76
79
|
missing_rels_folder:
|
77
80
|
msg: "Missing required file _rels/.rels"
|
78
81
|
page: 4
|
82
|
+
non_unique_rel_id:
|
83
|
+
msg: "The ID value '%{id}' appears more than once in '%{file}'. Within a rels file, all ID's must be unique"
|
84
|
+
page: 8 #TODO:change this to page 23 of the OPC spec once logging supports linking to that spec
|
85
|
+
spec: opc
|
79
86
|
multiple_relationships:
|
80
87
|
msg: "There MUST NOT be more than one relationship of a given relationship type from one part to a second part"
|
81
88
|
page: 10
|
@@ -148,3 +155,15 @@ non_distinct_indices:
|
|
148
155
|
has_improper_base_color:
|
149
156
|
msg: "An sRGB color MUST be specified with a value of a 6 or 8 digit hexadecimal number"
|
150
157
|
page: 35
|
158
|
+
duplicate_content_extension_types:
|
159
|
+
msg: "Only one ContentType definition is allowed per extension"
|
160
|
+
page: 8
|
161
|
+
invalid_image_content_type:
|
162
|
+
msg: "Invalid content type for %{extension}"
|
163
|
+
page: 22
|
164
|
+
duplicate_content_override_types:
|
165
|
+
msg: "Only one override is allowed per part"
|
166
|
+
page: 8
|
167
|
+
empty_override_part_name:
|
168
|
+
msg: "Overrides can't have empty partname"
|
169
|
+
page: 8
|
data/lib/ruby3mf/log3mf.rb
CHANGED
@@ -65,7 +65,7 @@ class Log3mf
|
|
65
65
|
def method_missing(name, *args, &block)
|
66
66
|
if LOG_LEVELS.include? name.to_sym
|
67
67
|
log(name.to_sym, *args)
|
68
|
-
else
|
68
|
+
else+
|
69
69
|
super
|
70
70
|
end
|
71
71
|
end
|
@@ -73,6 +73,7 @@ class Log3mf
|
|
73
73
|
def log(severity, message, options = {})
|
74
74
|
error = @errormap.fetch(message.to_s) { {"msg" => message.to_s, "page" => nil } }
|
75
75
|
options[:page] = error["page"] unless options[:page]
|
76
|
+
options[:spec] = error["spec"] unless options[:spec]
|
76
77
|
message = interpolate(error["msg"], options)
|
77
78
|
@log_list << ["#{@context_stack.join("/")}", severity, message, options] unless severity==:debug && ENV['LOGDEBUG'].nil?
|
78
79
|
raise FatalError if severity == :fatal_error
|
@@ -100,7 +101,9 @@ class Log3mf
|
|
100
101
|
core: 'http://3mf.io/wp-content/uploads/2016/03/3MFcoreSpec_1.1.pdf',
|
101
102
|
material: 'http://3mf.io/wp-content/uploads/2015/04/3MFmaterialsSpec_1.0.1.pdf',
|
102
103
|
production: 'http://3mf.io/wp-content/uploads/2016/07/3MFproductionSpec.pdf',
|
103
|
-
slice: 'http://3mf.io/wp-content/uploads/2016/07/3MFsliceSpec.pdf'
|
104
|
+
slice: 'http://3mf.io/wp-content/uploads/2016/07/3MFsliceSpec.pdf',
|
105
|
+
#opc: 'http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-376,%20Fourth%20Edition,%20Part%202%20-%20Open%20Packaging%20Conventions.zip'
|
106
|
+
opc: 'http://3mf.io/wp-content/uploads/2016/03/3MFcoreSpec_1.1.pdf'
|
104
107
|
}
|
105
108
|
"#{doc_urls[spec]}#page=#{page}"
|
106
109
|
end
|
data/lib/ruby3mf/model3mf.rb
CHANGED
@@ -1,14 +1,11 @@
|
|
1
1
|
class Model3mf
|
2
2
|
|
3
|
-
VALID_UNITS = ['micron', 'millimeter', 'centimeter', 'meter', 'inch', 'foot'].freeze
|
4
3
|
VALID_EXTENSIONS = {
|
5
4
|
'http://schemas.microsoft.com/3dmanufacturing/slice/2015/07' => {},
|
6
5
|
'http://schemas.microsoft.com/3dmanufacturing/material/2015/02' => {},
|
7
6
|
'http://schemas.microsoft.com/3dmanufacturing/production/2015/06' => {},
|
8
7
|
}.freeze
|
9
8
|
|
10
|
-
SCHEMA = '3MFcoreSpec_1.1.xsd'
|
11
|
-
|
12
9
|
VALID_CORE_METADATA_NAMES = ['Title', 'Designer', 'Description', 'Copyright', 'LicenseTerms', 'Rating', 'CreationDate', 'ModificationDate'].freeze
|
13
10
|
|
14
11
|
def self.parse(document, zip_entry)
|
@@ -16,7 +13,7 @@ class Model3mf
|
|
16
13
|
|
17
14
|
Log3mf.context "parsing model" do |l|
|
18
15
|
begin
|
19
|
-
model_doc = XmlVal.validate_parse(zip_entry,
|
16
|
+
model_doc = XmlVal.validate_parse(zip_entry, SchemaFiles::SchemaTemplate)
|
20
17
|
rescue Nokogiri::XML::SyntaxError => e
|
21
18
|
l.fatal_error "Model file invalid XML. Exception #{e}"
|
22
19
|
end
|
@@ -15,6 +15,7 @@ class Relationships
|
|
15
15
|
relationship_elements.each do |node|
|
16
16
|
if node.is_a?(Nokogiri::XML::Element) && node.name == "Relationship"
|
17
17
|
l.error :multiple_relationships if (relationships.select { |r| r[:target] == node['Target'] && r[:type] == node['Type'] }.size > 0)
|
18
|
+
l.error :non_unique_rel_id, :file => zip_entry.name, :id => node['Id'] if (relationships.select { |r| r[:id] == node['Id'] }.size > 0)
|
18
19
|
relationships << {target: node['Target'], type: node['Type'], id: node['Id']}
|
19
20
|
l.info "adding relationship: #{relationships.last.inspect}"
|
20
21
|
else
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
class SchemaFiles
|
4
|
+
|
5
|
+
SchemaTemplate = File.join(File.dirname(__FILE__), "3MFcoreSpec_1.1.xsd.template")
|
6
|
+
SchemaLocation = File.join(File.dirname(__FILE__), "xml.xsd")
|
7
|
+
|
8
|
+
def self.render(template)
|
9
|
+
ERB.new(template).result( binding )
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
data/lib/ruby3mf/version.rb
CHANGED
data/lib/ruby3mf/xml.xsd
ADDED
@@ -0,0 +1,286 @@
|
|
1
|
+
<?xml version='1.0'?>
|
2
|
+
<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?>
|
3
|
+
<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace"
|
4
|
+
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
5
|
+
xmlns ="http://www.w3.org/1999/xhtml"
|
6
|
+
xml:lang="en">
|
7
|
+
|
8
|
+
<xs:annotation>
|
9
|
+
<xs:documentation>
|
10
|
+
<div>
|
11
|
+
<h1>About the XML namespace</h1>
|
12
|
+
|
13
|
+
<div class="bodytext">
|
14
|
+
<p>
|
15
|
+
This schema document describes the XML namespace, in a form
|
16
|
+
suitable for import by other schema documents.
|
17
|
+
</p>
|
18
|
+
<p>
|
19
|
+
See <a href="http://www.w3.org/XML/1998/namespace.html">
|
20
|
+
http://www.w3.org/XML/1998/namespace.html</a> and
|
21
|
+
<a href="http://www.w3.org/TR/REC-xml">
|
22
|
+
http://www.w3.org/TR/REC-xml</a> for information
|
23
|
+
about this namespace.
|
24
|
+
</p>
|
25
|
+
<p>
|
26
|
+
Note that local names in this namespace are intended to be
|
27
|
+
defined only by the World Wide Web Consortium or its subgroups.
|
28
|
+
The names currently defined in this namespace are listed below.
|
29
|
+
They should not be used with conflicting semantics by any Working
|
30
|
+
Group, specification, or document instance.
|
31
|
+
</p>
|
32
|
+
<p>
|
33
|
+
See further below in this document for more information about <a
|
34
|
+
href="#usage">how to refer to this schema document from your own
|
35
|
+
XSD schema documents</a> and about <a href="#nsversioning">the
|
36
|
+
namespace-versioning policy governing this schema document</a>.
|
37
|
+
</p>
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
</xs:documentation>
|
41
|
+
</xs:annotation>
|
42
|
+
|
43
|
+
<xs:attribute name="lang">
|
44
|
+
<xs:annotation>
|
45
|
+
<xs:documentation>
|
46
|
+
<div>
|
47
|
+
|
48
|
+
<h3>lang (as an attribute name)</h3>
|
49
|
+
<p>
|
50
|
+
denotes an attribute whose value
|
51
|
+
is a language code for the natural language of the content of
|
52
|
+
any element; its value is inherited. This name is reserved
|
53
|
+
by virtue of its definition in the XML specification.</p>
|
54
|
+
|
55
|
+
</div>
|
56
|
+
<div>
|
57
|
+
<h4>Notes</h4>
|
58
|
+
<p>
|
59
|
+
Attempting to install the relevant ISO 2- and 3-letter
|
60
|
+
codes as the enumerated possible values is probably never
|
61
|
+
going to be a realistic possibility.
|
62
|
+
</p>
|
63
|
+
<p>
|
64
|
+
See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
|
65
|
+
http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a>
|
66
|
+
and the IANA language subtag registry at
|
67
|
+
<a href="http://www.iana.org/assignments/language-subtag-registry">
|
68
|
+
http://www.iana.org/assignments/language-subtag-registry</a>
|
69
|
+
for further information.
|
70
|
+
</p>
|
71
|
+
<p>
|
72
|
+
The union allows for the 'un-declaration' of xml:lang with
|
73
|
+
the empty string.
|
74
|
+
</p>
|
75
|
+
</div>
|
76
|
+
</xs:documentation>
|
77
|
+
</xs:annotation>
|
78
|
+
<xs:simpleType>
|
79
|
+
<xs:union memberTypes="xs:language">
|
80
|
+
<xs:simpleType>
|
81
|
+
<xs:restriction base="xs:string">
|
82
|
+
<xs:enumeration value=""/>
|
83
|
+
</xs:restriction>
|
84
|
+
</xs:simpleType>
|
85
|
+
</xs:union>
|
86
|
+
</xs:simpleType>
|
87
|
+
</xs:attribute>
|
88
|
+
|
89
|
+
<xs:attribute name="space">
|
90
|
+
<xs:annotation>
|
91
|
+
<xs:documentation>
|
92
|
+
<div>
|
93
|
+
|
94
|
+
<h3>space (as an attribute name)</h3>
|
95
|
+
<p>
|
96
|
+
denotes an attribute whose
|
97
|
+
value is a keyword indicating what whitespace processing
|
98
|
+
discipline is intended for the content of the element; its
|
99
|
+
value is inherited. This name is reserved by virtue of its
|
100
|
+
definition in the XML specification.</p>
|
101
|
+
|
102
|
+
</div>
|
103
|
+
</xs:documentation>
|
104
|
+
</xs:annotation>
|
105
|
+
<xs:simpleType>
|
106
|
+
<xs:restriction base="xs:NCName">
|
107
|
+
<xs:enumeration value="default"/>
|
108
|
+
<xs:enumeration value="preserve"/>
|
109
|
+
</xs:restriction>
|
110
|
+
</xs:simpleType>
|
111
|
+
</xs:attribute>
|
112
|
+
|
113
|
+
<xs:attribute name="base" type="xs:anyURI"> <xs:annotation>
|
114
|
+
<xs:documentation>
|
115
|
+
<div>
|
116
|
+
|
117
|
+
<h3>base (as an attribute name)</h3>
|
118
|
+
<p>
|
119
|
+
denotes an attribute whose value
|
120
|
+
provides a URI to be used as the base for interpreting any
|
121
|
+
relative URIs in the scope of the element on which it
|
122
|
+
appears; its value is inherited. This name is reserved
|
123
|
+
by virtue of its definition in the XML Base specification.</p>
|
124
|
+
|
125
|
+
<p>
|
126
|
+
See <a
|
127
|
+
href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a>
|
128
|
+
for information about this attribute.
|
129
|
+
</p>
|
130
|
+
</div>
|
131
|
+
</xs:documentation>
|
132
|
+
</xs:annotation>
|
133
|
+
</xs:attribute>
|
134
|
+
|
135
|
+
<xs:attribute name="id" type="xs:ID">
|
136
|
+
<xs:annotation>
|
137
|
+
<xs:documentation>
|
138
|
+
<div>
|
139
|
+
|
140
|
+
<h3>id (as an attribute name)</h3>
|
141
|
+
<p>
|
142
|
+
denotes an attribute whose value
|
143
|
+
should be interpreted as if declared to be of type ID.
|
144
|
+
This name is reserved by virtue of its definition in the
|
145
|
+
xml:id specification.</p>
|
146
|
+
|
147
|
+
<p>
|
148
|
+
See <a
|
149
|
+
href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a>
|
150
|
+
for information about this attribute.
|
151
|
+
</p>
|
152
|
+
</div>
|
153
|
+
</xs:documentation>
|
154
|
+
</xs:annotation>
|
155
|
+
</xs:attribute>
|
156
|
+
|
157
|
+
<xs:attributeGroup name="specialAttrs">
|
158
|
+
<xs:attribute ref="xml:base"/>
|
159
|
+
<xs:attribute ref="xml:lang"/>
|
160
|
+
<xs:attribute ref="xml:space"/>
|
161
|
+
<xs:attribute ref="xml:id"/>
|
162
|
+
</xs:attributeGroup>
|
163
|
+
|
164
|
+
<xs:annotation>
|
165
|
+
<xs:documentation>
|
166
|
+
<div>
|
167
|
+
|
168
|
+
<h3>Father (in any context at all)</h3>
|
169
|
+
|
170
|
+
<div class="bodytext">
|
171
|
+
<p>
|
172
|
+
denotes Jon Bosak, the chair of
|
173
|
+
the original XML Working Group. This name is reserved by
|
174
|
+
the following decision of the W3C XML Plenary and
|
175
|
+
XML Coordination groups:
|
176
|
+
</p>
|
177
|
+
<blockquote>
|
178
|
+
<p>
|
179
|
+
In appreciation for his vision, leadership and
|
180
|
+
dedication the W3C XML Plenary on this 10th day of
|
181
|
+
February, 2000, reserves for Jon Bosak in perpetuity
|
182
|
+
the XML name "xml:Father".
|
183
|
+
</p>
|
184
|
+
</blockquote>
|
185
|
+
</div>
|
186
|
+
</div>
|
187
|
+
</xs:documentation>
|
188
|
+
</xs:annotation>
|
189
|
+
|
190
|
+
<xs:annotation>
|
191
|
+
<xs:documentation>
|
192
|
+
<div xml:id="usage" id="usage">
|
193
|
+
<h2><a name="usage">About this schema document</a></h2>
|
194
|
+
|
195
|
+
<div class="bodytext">
|
196
|
+
<p>
|
197
|
+
This schema defines attributes and an attribute group suitable
|
198
|
+
for use by schemas wishing to allow <code>xml:base</code>,
|
199
|
+
<code>xml:lang</code>, <code>xml:space</code> or
|
200
|
+
<code>xml:id</code> attributes on elements they define.
|
201
|
+
</p>
|
202
|
+
<p>
|
203
|
+
To enable this, such a schema must import this schema for
|
204
|
+
the XML namespace, e.g. as follows:
|
205
|
+
</p>
|
206
|
+
<pre>
|
207
|
+
<schema . . .>
|
208
|
+
. . .
|
209
|
+
<import namespace="http://www.w3.org/XML/1998/namespace"
|
210
|
+
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
|
211
|
+
</pre>
|
212
|
+
<p>
|
213
|
+
or
|
214
|
+
</p>
|
215
|
+
<pre>
|
216
|
+
<import namespace="http://www.w3.org/XML/1998/namespace"
|
217
|
+
schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
|
218
|
+
</pre>
|
219
|
+
<p>
|
220
|
+
Subsequently, qualified reference to any of the attributes or the
|
221
|
+
group defined below will have the desired effect, e.g.
|
222
|
+
</p>
|
223
|
+
<pre>
|
224
|
+
<type . . .>
|
225
|
+
. . .
|
226
|
+
<attributeGroup ref="xml:specialAttrs"/>
|
227
|
+
</pre>
|
228
|
+
<p>
|
229
|
+
will define a type which will schema-validate an instance element
|
230
|
+
with any of those attributes.
|
231
|
+
</p>
|
232
|
+
</div>
|
233
|
+
</div>
|
234
|
+
</xs:documentation>
|
235
|
+
</xs:annotation>
|
236
|
+
|
237
|
+
<xs:annotation>
|
238
|
+
<xs:documentation>
|
239
|
+
<div id="nsversioning" xml:id="nsversioning">
|
240
|
+
<h2><a name="nsversioning">Versioning policy for this schema document</a></h2>
|
241
|
+
<div class="bodytext">
|
242
|
+
<p>
|
243
|
+
In keeping with the XML Schema WG's standard versioning
|
244
|
+
policy, this schema document will persist at
|
245
|
+
<a href="http://www.w3.org/2009/01/xml.xsd">
|
246
|
+
http://www.w3.org/2009/01/xml.xsd</a>.
|
247
|
+
</p>
|
248
|
+
<p>
|
249
|
+
At the date of issue it can also be found at
|
250
|
+
<a href="http://www.w3.org/2001/xml.xsd">
|
251
|
+
http://www.w3.org/2001/xml.xsd</a>.
|
252
|
+
</p>
|
253
|
+
<p>
|
254
|
+
The schema document at that URI may however change in the future,
|
255
|
+
in order to remain compatible with the latest version of XML
|
256
|
+
Schema itself, or with the XML namespace itself. In other words,
|
257
|
+
if the XML Schema or XML namespaces change, the version of this
|
258
|
+
document at <a href="http://www.w3.org/2001/xml.xsd">
|
259
|
+
http://www.w3.org/2001/xml.xsd
|
260
|
+
</a>
|
261
|
+
will change accordingly; the version at
|
262
|
+
<a href="http://www.w3.org/2009/01/xml.xsd">
|
263
|
+
http://www.w3.org/2009/01/xml.xsd
|
264
|
+
</a>
|
265
|
+
will not change.
|
266
|
+
</p>
|
267
|
+
<p>
|
268
|
+
Previous dated (and unchanging) versions of this schema
|
269
|
+
document are at:
|
270
|
+
</p>
|
271
|
+
<ul>
|
272
|
+
<li><a href="http://www.w3.org/2009/01/xml.xsd">
|
273
|
+
http://www.w3.org/2009/01/xml.xsd</a></li>
|
274
|
+
<li><a href="http://www.w3.org/2007/08/xml.xsd">
|
275
|
+
http://www.w3.org/2007/08/xml.xsd</a></li>
|
276
|
+
<li><a href="http://www.w3.org/2004/10/xml.xsd">
|
277
|
+
http://www.w3.org/2004/10/xml.xsd</a></li>
|
278
|
+
<li><a href="http://www.w3.org/2001/03/xml.xsd">
|
279
|
+
http://www.w3.org/2001/03/xml.xsd</a></li>
|
280
|
+
</ul>
|
281
|
+
</div>
|
282
|
+
</div>
|
283
|
+
</xs:documentation>
|
284
|
+
</xs:annotation>
|
285
|
+
|
286
|
+
</xs:schema>
|
data/lib/ruby3mf/xml_val.rb
CHANGED
@@ -2,7 +2,7 @@ require 'nokogiri'
|
|
2
2
|
|
3
3
|
class XmlVal
|
4
4
|
|
5
|
-
def self.validate_parse(xml_file, schema_name=nil)
|
5
|
+
def self.validate_parse(xml_file, schema_name = nil)
|
6
6
|
doc = Nokogiri::XML(xml_file.get_input_stream) do |config|
|
7
7
|
config.strict.nonet.noblanks
|
8
8
|
end
|
@@ -10,7 +10,14 @@ class XmlVal
|
|
10
10
|
doc
|
11
11
|
end
|
12
12
|
|
13
|
-
def self.
|
13
|
+
def self.open_schema_file(file)
|
14
|
+
File.open(file, "r") do |file|
|
15
|
+
template = file.read
|
16
|
+
yield(SchemaFiles.render(template))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.validate(file, document, schema_filename = nil)
|
14
21
|
Log3mf.context "validations" do |l|
|
15
22
|
l.error :has_xml_space_attribute if space_attribute_exists?(document)
|
16
23
|
l.error :wrong_encoding if xml_not_utf8_encoded?(document)
|
@@ -20,8 +27,8 @@ class XmlVal
|
|
20
27
|
|
21
28
|
if schema_filename
|
22
29
|
Log3mf.context "validating core schema" do |l|
|
23
|
-
|
24
|
-
xsd = Nokogiri::XML::Schema(
|
30
|
+
open_schema_file(schema_filename) do |content|
|
31
|
+
xsd = Nokogiri::XML::Schema(content)
|
25
32
|
puts "the schema is NIL!" if xsd.nil?
|
26
33
|
core_schema_errors = xsd.validate(document)
|
27
34
|
l.error :invalid_xml_core if core_schema_errors.size > 0
|
@@ -39,7 +46,7 @@ class XmlVal
|
|
39
46
|
end
|
40
47
|
|
41
48
|
def self.objects_not_referenced?(document)
|
42
|
-
document.css('object').map { |x| x.attributes["id"].value } != document.css('item').map { |x| x.attributes["objectid"].value }
|
49
|
+
document.css('object').map { |x| x.attributes["id"].value } != document.css('build/item').map { |x| x.attributes["objectid"].value }
|
43
50
|
end
|
44
51
|
|
45
52
|
def self.bad_floating_numbers?(document)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby3mf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Whitmarsh, Jeff Porter, and William Hertling
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -147,8 +147,9 @@ files:
|
|
147
147
|
- bin/folder_test.sh
|
148
148
|
- bin/setup
|
149
149
|
- bin/suite.rb
|
150
|
+
- bin/suite_test.sh
|
150
151
|
- lib/ruby3mf.rb
|
151
|
-
- lib/ruby3mf/3MFcoreSpec_1.1.xsd
|
152
|
+
- lib/ruby3mf/3MFcoreSpec_1.1.xsd.template
|
152
153
|
- lib/ruby3mf/content_types.rb
|
153
154
|
- lib/ruby3mf/document.rb
|
154
155
|
- lib/ruby3mf/edge_list.rb
|
@@ -158,9 +159,11 @@ files:
|
|
158
159
|
- lib/ruby3mf/mesh_analyzer.rb
|
159
160
|
- lib/ruby3mf/model3mf.rb
|
160
161
|
- lib/ruby3mf/relationships.rb
|
162
|
+
- lib/ruby3mf/schema_files.rb
|
161
163
|
- lib/ruby3mf/texture3mf.rb
|
162
164
|
- lib/ruby3mf/thumbnail3mf.rb
|
163
165
|
- lib/ruby3mf/version.rb
|
166
|
+
- lib/ruby3mf/xml.xsd
|
164
167
|
- lib/ruby3mf/xml_val.rb
|
165
168
|
- ruby3mf.gemspec
|
166
169
|
homepage: https://github.com/IPGPTP/ruby3mf
|