ruby3mf 0.2.1 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|