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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e69399223f22bf72d431f634a3dae81966252da
4
- data.tar.gz: f8a87375c839cb3e42e00496104ee0c0a6a1c93f
3
+ metadata.gz: 2d2f6346320579794b80cb51d43cc89d2bfe62c5
4
+ data.tar.gz: 69c77fd6fe56952bc7e66b7bb0d8c113dbc35fc8
5
5
  SHA512:
6
- metadata.gz: 8ad2102f909a1df3f614010c4738b81e5b0ece6415d6f3f6cc47951151ed57f282b3150e4c2c581b41cd2685f46253df48c40117fbf0a323968a41502f594412
7
- data.tar.gz: 7c0182a9da87926ad9a76eb604a72dfc68926720b14e7174a4672d8c8f18773bdfb835b6fff4c428983bdb9dbdf169b7980b55fec53aea070d697a98c8e36322
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
- errors.each do |ent|
16
- h = { context: ent[0], severity: ent[1], message: ent[2] }
17
- puts h
18
- end
19
- rescue
20
- end
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
@@ -10,3 +10,6 @@ errors.each do |ent|
10
10
  h = { file: filename, context: ent[0], severity: ent[1], message: ent[2] }
11
11
  puts h
12
12
  end
13
+
14
+ # set exit code for suite test usage
15
+ exit errors.size == 0
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
@@ -1,5 +1,6 @@
1
1
  require_relative "ruby3mf/version"
2
2
  require_relative "ruby3mf/interpolation"
3
+ require_relative "ruby3mf/schema_files"
3
4
  require_relative "ruby3mf/log3mf"
4
5
  require_relative "ruby3mf/document"
5
6
  require_relative "ruby3mf/content_types"
@@ -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="http://www.w3.org/2001/xml.xsd"/>
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
- unless node.name == 'Default'
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
@@ -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.error 'Missing required file: [Content_Types].xml', page: 4
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?
@@ -1,5 +1,5 @@
1
1
  resource_contentype_invalid:
2
- msg: "Resource in model has invalid contenttype %{bt}"
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
@@ -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
@@ -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, SCHEMA)
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
@@ -1,3 +1,3 @@
1
1
  module Ruby3mf
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.3"
3
3
  end
@@ -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
+ &lt;schema . . .>
208
+ . . .
209
+ &lt;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
+ &lt;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
+ &lt;type . . .>
225
+ . . .
226
+ &lt;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>
@@ -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.validate(file, document, schema_filename=nil)
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
- File.open(File.join(File.dirname(__FILE__), schema_filename), "r") do |file|
24
- xsd = Nokogiri::XML::Schema(file.read)
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.1
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-19 00:00:00.000000000 Z
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