rgen-xsd 0.1.0
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.
- data/CHANGELOG +4 -0
- data/MIT-LICENSE +21 -0
- data/README +16 -0
- data/Rakefile +45 -0
- data/lib/rgen/xsd/1.0/datatypes.xml +1117 -0
- data/lib/rgen/xsd/1.0/metamodel.rb +413 -0
- data/lib/rgen/xsd/1.0/rakefile +3 -0
- data/lib/rgen/xsd/1.0/readme.txt +6 -0
- data/lib/rgen/xsd/1.0/structures.xml +1235 -0
- data/lib/rgen/xsd/1.1/datatypes.xml +491 -0
- data/lib/rgen/xsd/1.1/metamodel.rb +488 -0
- data/lib/rgen/xsd/1.1/rakefile +3 -0
- data/lib/rgen/xsd/1.1/readme.txt +6 -0
- data/lib/rgen/xsd/1.1/structures.xml +1479 -0
- data/lib/rgen/xsd/metamodel_generator.rb +110 -0
- data/lib/rgen/xsd/metamodel_modification_helper.rb +41 -0
- data/lib/rgen/xsd/particle.rb +169 -0
- data/lib/rgen/xsd/simple_type.rb +87 -0
- data/lib/rgen/xsd/xml/readme.txt +6 -0
- data/lib/rgen/xsd/xml/xml.xsd +145 -0
- data/lib/rgen/xsd/xml_schema_metamodel_ext.rb +54 -0
- data/lib/rgen/xsd/xsd_instantiator.rb +83 -0
- data/lib/rgen/xsd/xsd_to_ecore.rb +325 -0
- data/lib/rgen/xsd/xsi_instantiator.rb +230 -0
- metadata +87 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)+"/../../")
|
2
|
+
|
3
|
+
require "rgen/environment"
|
4
|
+
require "rgen/util/name_helper"
|
5
|
+
require 'mmgen/metamodel_generator'
|
6
|
+
|
7
|
+
require "rgen/xsd/xsd_instantiator"
|
8
|
+
require "rgen/xsd/metamodel_modification_helper"
|
9
|
+
require 'optparse'
|
10
|
+
|
11
|
+
include RGen::Util::NameHelper
|
12
|
+
include RGen::XSD::MetamodelModificationHelper
|
13
|
+
|
14
|
+
options = {}
|
15
|
+
optparse = OptionParser.new do|opts|
|
16
|
+
opts.banner = "Usage: metamodel_generator.rb [options] <schema file>+"
|
17
|
+
|
18
|
+
opts.on( '--mm VERSION', 'XML schema version: 1.0 or 1.1' ) do |v|
|
19
|
+
options[:mm] = v
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on('-o FILE', "Output metamodel file") do |f|
|
23
|
+
options[:outfile] = f
|
24
|
+
end
|
25
|
+
end
|
26
|
+
optparse.parse!
|
27
|
+
if !options[:mm]
|
28
|
+
puts "Schema version not specified"
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
if !options[:outfile]
|
32
|
+
puts "Output file not specified"
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
|
36
|
+
case options[:mm]
|
37
|
+
when "1.0"
|
38
|
+
require "rgen/xsd/1.0/metamodel"
|
39
|
+
when "1.1"
|
40
|
+
require "rgen/xsd/1.1/metamodel"
|
41
|
+
else
|
42
|
+
puts "Unknown schema version: #{options[:mm]}"
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
XMLSchemaMetamodel = MM::W3Org2001XMLSchema
|
46
|
+
|
47
|
+
env = RGen::Environment.new
|
48
|
+
mm = XMLSchemaMetamodel
|
49
|
+
inst = RGen::XSD::XSDInstantiator.new(env, mm)
|
50
|
+
|
51
|
+
ARGV.each do |fn|
|
52
|
+
inst.instantiate(fn)
|
53
|
+
end
|
54
|
+
|
55
|
+
problems = []
|
56
|
+
inst.resolve(problems)
|
57
|
+
|
58
|
+
if problems.size > 0
|
59
|
+
problems.each do |p|
|
60
|
+
puts p
|
61
|
+
end
|
62
|
+
puts "#{problems.size} problems, stop."
|
63
|
+
exit
|
64
|
+
end
|
65
|
+
|
66
|
+
require "rgen/xsd/xml_schema_metamodel_ext"
|
67
|
+
require "rgen/xsd/xsd_to_ecore"
|
68
|
+
|
69
|
+
sch = env.find(:class => XMLSchemaMetamodel::Element, :name => "schema").first
|
70
|
+
|
71
|
+
env_ecore = RGen::Environment.new
|
72
|
+
trans = RGen::XSD::XSDToEcoreTransformer.new(env, env_ecore)
|
73
|
+
root = trans.transform
|
74
|
+
|
75
|
+
class_complexType = env_ecore.find(:class => RGen::ECore::EClass, :name => "ComplexType").first
|
76
|
+
class_simpleType = env_ecore.find(:class => RGen::ECore::EClass, :name => "SimpleType").first
|
77
|
+
class_element = env_ecore.find(:class => RGen::ECore::EClass, :name => "Element").first
|
78
|
+
class_group = env_ecore.find(:class => RGen::ECore::EClass, :name => "Group").first
|
79
|
+
class_attribute = env_ecore.find(:class => RGen::ECore::EClass, :name => "Attribute").first
|
80
|
+
class_attributeGroup = env_ecore.find(:class => RGen::ECore::EClass, :name => "AttributeGroup").first
|
81
|
+
|
82
|
+
# insert Type class as supertype of ComplexType and SimpleType
|
83
|
+
class_type = env_ecore.new(RGen::ECore::EClass, :name => "Type", :ePackage => class_complexType.ePackage,
|
84
|
+
:eSuperTypes => class_complexType.eSuperTypes)
|
85
|
+
class_complexType.eSuperTypes = [class_type]
|
86
|
+
class_simpleType.eSuperTypes = [class_type]
|
87
|
+
|
88
|
+
# explicit references
|
89
|
+
attribute_to_reference(env_ecore, "RestrictionType#base", class_type)
|
90
|
+
attribute_to_reference(env_ecore, "RestrictionTYPE#base", class_type)
|
91
|
+
attribute_to_reference(env_ecore, "ExtensionType#base", class_type)
|
92
|
+
attribute_to_reference(env_ecore, "Element#ref", class_element)
|
93
|
+
attribute_to_reference(env_ecore, "Element#type", class_type)
|
94
|
+
attribute_to_reference(env_ecore, "Group#ref", class_group)
|
95
|
+
attribute_to_reference(env_ecore, "AttributeGroup#ref", class_attributeGroup)
|
96
|
+
attribute_to_reference(env_ecore, "Attribute#ref", class_attribute)
|
97
|
+
attribute_to_reference(env_ecore, "Attribute#type", class_simpleType)
|
98
|
+
attribute_to_reference(env_ecore, "Element#substitutionGroup", class_element)
|
99
|
+
attribute_to_reference(env_ecore, "ListTYPE#itemType", class_simpleType)
|
100
|
+
attribute_to_reference(env_ecore, "UnionTYPE#memberTypes", class_simpleType)
|
101
|
+
|
102
|
+
# bidirectional references
|
103
|
+
create_opposite(env_ecore, "Element#substitutionGroup", "substitutes", -1)
|
104
|
+
create_opposite(env_ecore, "Element#complexType", "containingElement", 1)
|
105
|
+
create_opposite(env_ecore, "Element#simpleType", "containingElement", 1)
|
106
|
+
create_opposite(env_ecore, "Attribute#simpleType", "containingAttribute", 1)
|
107
|
+
|
108
|
+
include MMGen::MetamodelGenerator
|
109
|
+
generateMetamodel(root, options[:outfile])
|
110
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module RGen
|
2
|
+
|
3
|
+
module XSD
|
4
|
+
|
5
|
+
module MetamodelModificationHelper
|
6
|
+
|
7
|
+
def find_feature(env, desc)
|
8
|
+
env.find(:class => RGen::ECore::EStructuralFeature, :name => desc.split("#").last).
|
9
|
+
find{|f| f.eContainingClass.name == desc.split("#").first}
|
10
|
+
end
|
11
|
+
|
12
|
+
def attribute_to_reference(env, desc, target)
|
13
|
+
a = find_feature(env, desc)
|
14
|
+
r = env.new(RGen::ECore::EReference, Hash[
|
15
|
+
RGen::ECore::EStructuralFeature.ecore.eAllStructuralFeatures.collect do |f|
|
16
|
+
next if f.derived
|
17
|
+
p = [f.name, a.getGeneric(f.name)]
|
18
|
+
if f.many
|
19
|
+
a.setGeneric(f.name, [])
|
20
|
+
else
|
21
|
+
a.setGeneric(f.name, nil)
|
22
|
+
end
|
23
|
+
p
|
24
|
+
end])
|
25
|
+
r.eType = target
|
26
|
+
r
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_opposite(env, desc, name, upper_bound)
|
30
|
+
r = find_feature(env, desc)
|
31
|
+
r.eOpposite =
|
32
|
+
env.new(RGen::ECore::EReference, :name => name, :eType => r.eContainingClass,
|
33
|
+
:eContainingClass => r.eType, :upperBound => upper_bound, :eOpposite => r)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module RGen
|
2
|
+
module XSD
|
3
|
+
module Particle
|
4
|
+
|
5
|
+
# helper structure representing a particle or particle tree
|
6
|
+
# particles of kind :choice, :sequence or :all can have child particles
|
7
|
+
Particle = Struct.new(:kind, :children, :minOccurs, :maxOccurs, :node)
|
8
|
+
|
9
|
+
# builds a flat list of the element particles contained in +node+
|
10
|
+
# to be used for ComplexType and complex content extensions
|
11
|
+
def element_particles(node)
|
12
|
+
trees = build_particles_trees(node)
|
13
|
+
if trees.size == 1
|
14
|
+
flatten_particle_tree(trees.first)
|
15
|
+
elsif trees.size > 1
|
16
|
+
puts "WARN: only one particle expected as a content model"
|
17
|
+
[]
|
18
|
+
else
|
19
|
+
[]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_substitution_particles(particles)
|
24
|
+
result = []
|
25
|
+
particles.each do |p|
|
26
|
+
result << p
|
27
|
+
if p.kind == :element
|
28
|
+
p.node.substitutes.each do |s|
|
29
|
+
result << Particle.new(:element, [], p.minOccurs, p.maxOccurs, s)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
# flattens the particle tree with root +particle+ and calculates min/max occurrence
|
37
|
+
# returns a list of particles of kind "element" and "any"
|
38
|
+
# element names are unique throughout the list
|
39
|
+
# the order is the order of first occurrence
|
40
|
+
def flatten_particle_tree(particle)
|
41
|
+
if particle.kind == :element || particle.kind == :any
|
42
|
+
[particle]
|
43
|
+
else
|
44
|
+
eocc = {}
|
45
|
+
elist = []
|
46
|
+
particle.children.each do |c|
|
47
|
+
flatten_particle_tree(c).each do |e|
|
48
|
+
if e.kind == :element
|
49
|
+
name = e.node.name
|
50
|
+
else
|
51
|
+
name = "#any#"
|
52
|
+
end
|
53
|
+
if !eocc[name]
|
54
|
+
eocc[name] = []
|
55
|
+
elist << name
|
56
|
+
end
|
57
|
+
eocc[name] << e
|
58
|
+
end
|
59
|
+
end
|
60
|
+
is_unbounded = lambda do |particle, elements|
|
61
|
+
(particle.maxOccurs == "unbounded" &&
|
62
|
+
elements.any?{|e| e.maxOccurs == "unbounded" || e.maxOccurs.to_i > 0}) ||
|
63
|
+
(particle.maxOccurs.to_i > 0 &&
|
64
|
+
elements.any?{|e| e.maxOccurs == "unbounded"})
|
65
|
+
end
|
66
|
+
if particle.kind == :choice
|
67
|
+
elist.collect do |n|
|
68
|
+
if eocc[n].size < particle.children.size
|
69
|
+
# element is not in every choice
|
70
|
+
min = 0
|
71
|
+
else
|
72
|
+
min = eocc[n].collect{|e| e.minOccurs.to_i}.min * particle.minOccurs.to_i
|
73
|
+
end
|
74
|
+
if is_unbounded.call(particle, eocc[n])
|
75
|
+
max = "unbounded"
|
76
|
+
else
|
77
|
+
max = eocc[n].collect{|e| e.maxOccurs.to_i}.max * particle.maxOccurs.to_i
|
78
|
+
end
|
79
|
+
if n == "#any#"
|
80
|
+
Particle.new(:any, [], min, max, eocc[n].first.node)
|
81
|
+
else
|
82
|
+
Particle.new(:element, [], min, max, eocc[n].first.node)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
else # sequence or all
|
86
|
+
elist.collect do |n|
|
87
|
+
min = eocc[n].inject(0){|m, e| m + e.minOccurs.to_i} * particle.minOccurs.to_i
|
88
|
+
if is_unbounded.call(particle, eocc[n])
|
89
|
+
max = "unbounded"
|
90
|
+
else
|
91
|
+
max = eocc[n].inject(0){|m, e| m + e.maxOccurs.to_i} * particle.maxOccurs.to_i
|
92
|
+
end
|
93
|
+
if n == "#any#"
|
94
|
+
Particle.new(:any, [], min, max, eocc[n].first.node)
|
95
|
+
else
|
96
|
+
Particle.new(:element, [], min, max, eocc[n].first.node)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# builds the particle trees for the particles contained in node
|
104
|
+
def build_particles_trees(node)
|
105
|
+
trees = []
|
106
|
+
# ComplexType and extension type have only one choice, sequence, all, group
|
107
|
+
choices = node.choice
|
108
|
+
choices = [choices].compact unless choices.is_a?(Array)
|
109
|
+
choices.each do |c|
|
110
|
+
trees << Particle.new(:choice, build_particles_trees(c), c.minOccurs || "1", c.maxOccurs || "1", c)
|
111
|
+
end
|
112
|
+
sequences = node.sequence
|
113
|
+
sequences = [sequences].compact unless sequences.is_a?(Array)
|
114
|
+
sequences.each do |s|
|
115
|
+
trees << Particle.new(:sequence, build_particles_trees(s), s.minOccurs || "1", s.maxOccurs || "1", s)
|
116
|
+
end
|
117
|
+
alls = node.all
|
118
|
+
alls = [alls].compact unless alls.is_a?(Array)
|
119
|
+
alls.each do |a|
|
120
|
+
trees << Particle.new(:all, build_particles_trees(s), a.minOccurs || "1", a.maxOccurs || "1", a)
|
121
|
+
end
|
122
|
+
# Group definitions don't have group reference particles
|
123
|
+
if node.respond_to?(:group)
|
124
|
+
groups = node.group
|
125
|
+
groups = [groups].compact unless groups.is_a?(Array)
|
126
|
+
groups.each do |g|
|
127
|
+
if g.ref
|
128
|
+
# the referenced group is a Model Group Definition, i.e. a node wrapping a Model Group
|
129
|
+
# it must contain at most one of Choice, Sequence, All
|
130
|
+
# it must not contain another "group" tag because this would be a particle
|
131
|
+
group_childs = g.ref.all + g.ref.choice + g.ref.sequence
|
132
|
+
if group_childs.size == 1
|
133
|
+
gtc = build_particles_trees(g.ref).first
|
134
|
+
gtc.minOccurs = g.minOccurs || "1"
|
135
|
+
gtc.maxOccurs = g.maxOccurs || "1"
|
136
|
+
trees << gtc
|
137
|
+
elsif group_childs.size > 1
|
138
|
+
puts "WARN: ignoring model group definition containing more than one model group"
|
139
|
+
else
|
140
|
+
# empty, ignore
|
141
|
+
end
|
142
|
+
else
|
143
|
+
puts "WARN: ignoring non-toplevel group without a ref"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
# ComplexType and complex content extension don't have element particles
|
148
|
+
if node.respond_to?(:element)
|
149
|
+
node.element.each do |e|
|
150
|
+
if e.ref
|
151
|
+
trees << Particle.new(:element, [], e.minOccurs || "1", e.maxOccurs || "1", e.ref)
|
152
|
+
else
|
153
|
+
trees << Particle.new(:element, [], e.minOccurs || "1", e.maxOccurs || "1", e)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
# ComplexType and complex content extension don't have 'any' particles
|
158
|
+
if node.respond_to?(:any)
|
159
|
+
node.any.each do |a|
|
160
|
+
trees << Particle.new(:any, [], a.minOccurs || "1", a.maxOccurs || "1", a)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
trees
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module RGen
|
2
|
+
module XSD
|
3
|
+
module SimpleType
|
4
|
+
|
5
|
+
SimpleType = Struct.new(:type, :isList, :minOccurs, :maxOccurs)
|
6
|
+
|
7
|
+
def build_type_desc(type)
|
8
|
+
builtin = builtin_type(type)
|
9
|
+
if builtin
|
10
|
+
builtin
|
11
|
+
elsif type.respond_to?(:list) && type.list
|
12
|
+
if type.list.itemType || type.list.simpleType
|
13
|
+
td = build_type_desc(type.list.itemType || type.list.simpleType)
|
14
|
+
td.isList = true
|
15
|
+
td.minOccurs = 0
|
16
|
+
td.maxOccurs = -1
|
17
|
+
td
|
18
|
+
else
|
19
|
+
puts "WARN: list type without an item type"
|
20
|
+
SimpleType.new(:string, false, 0, 1)
|
21
|
+
end
|
22
|
+
elsif type.respond_to?(:union) && type.union
|
23
|
+
# TODO
|
24
|
+
# (type.union.memberTypes + type.union.simpleType).each do |t|
|
25
|
+
# build_type_desc(t)
|
26
|
+
# end
|
27
|
+
# TODO: make this a string instead? otherwise there is a problem serializing with RText (could also be fixed in RText: o.to_s)
|
28
|
+
SimpleType.new(:object, false, 0, 1)
|
29
|
+
elsif type.respond_to?(:restriction) && type.restriction
|
30
|
+
if type.restriction.base
|
31
|
+
td = build_type_desc(type.restriction.base)
|
32
|
+
if td.type == :string && type.restriction.enumeration.size > 0
|
33
|
+
SimpleType.new(
|
34
|
+
type.restriction.enumeration.collect { |e| e.value },
|
35
|
+
false, 0, 1)
|
36
|
+
elsif td.isList
|
37
|
+
# assumption: restrictions are properly nested
|
38
|
+
# note: this doesn't work correctly in case of lists of lists
|
39
|
+
td.minOccurs = type.restriction.minLength.first.value.to_i if type.restriction.minLength.first
|
40
|
+
td.maxOccurs = type.restriction.maxLength.first.value.to_i if type.restriction.maxLength.first
|
41
|
+
td
|
42
|
+
else
|
43
|
+
# unhandled restriction, pass the original
|
44
|
+
td
|
45
|
+
end
|
46
|
+
else
|
47
|
+
puts "WARN: restriction type without a base type"
|
48
|
+
SimpleType.new(:string, false, 0, 1)
|
49
|
+
end
|
50
|
+
else
|
51
|
+
puts "WARN: unknown node type: #{type.class}"
|
52
|
+
SimpleType.new(:string, false, 0, 1)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def builtin_type(type)
|
57
|
+
if type.nil?
|
58
|
+
# assumen anySimpleType
|
59
|
+
return SimpleType.new(:string, false, 0, 1)
|
60
|
+
end
|
61
|
+
case type.name
|
62
|
+
when "anyType"
|
63
|
+
SimpleType.new(:object, false, 0, 1)
|
64
|
+
when "anySimpleType", "string", "normalizedString", "token", "language", "Name", "NCName",
|
65
|
+
"ID", "IDREF", "ENTITY", "NMTOKEN", "base64Binary", "hexBinary", "anyURI", "QName",
|
66
|
+
"NOTATION", "duration", "dateTime", "time", "date", "gYearMonth", "gYear", "gMonthDay",
|
67
|
+
"gDay", "gMonth"
|
68
|
+
SimpleType.new(:string, false, 0, 1)
|
69
|
+
when "IDREFS", "ENTITIES", "NMTOKENS"
|
70
|
+
SimpleType.new(:string, true, 0, -1)
|
71
|
+
when "float", "double"
|
72
|
+
SimpleType.new(:float, false, 0, 1)
|
73
|
+
when "decimal", "integer", "nonPositiveInteger", "negativeInteger", "long", "int", "short",
|
74
|
+
"byte", "nonNegativeInteger", "unsignedLong", "unsignedInt", "unsignedShort",
|
75
|
+
"unsignedByte", "positiveInteger"
|
76
|
+
SimpleType.new(:int, false, 0, 1)
|
77
|
+
when "boolean"
|
78
|
+
SimpleType.new(:boolean, false, 0, 1)
|
79
|
+
else
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
@@ -0,0 +1,6 @@
|
|
1
|
+
This folder contains the following schema parts as published by the W3C
|
2
|
+
|
3
|
+
* xml.xsd (http://www.w3.org/2007/08/xml.xsd)
|
4
|
+
|
5
|
+
Copyright � 2007 World Wide Web Consortium, (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231
|
6
|
+
|
@@ -0,0 +1,145 @@
|
|
1
|
+
<?xml version='1.0'?>
|
2
|
+
<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" xml:lang="en">
|
3
|
+
|
4
|
+
<xs:annotation>
|
5
|
+
<xs:documentation>
|
6
|
+
See http://www.w3.org/XML/1998/namespace.html and
|
7
|
+
http://www.w3.org/TR/REC-xml for information about this namespace.
|
8
|
+
|
9
|
+
This schema document describes the XML namespace, in a form
|
10
|
+
suitable for import by other schema documents.
|
11
|
+
|
12
|
+
Note that local names in this namespace are intended to be defined
|
13
|
+
only by the World Wide Web Consortium or its subgroups. The
|
14
|
+
following names are currently defined in this namespace and should
|
15
|
+
not be used with conflicting semantics by any Working Group,
|
16
|
+
specification, or document instance:
|
17
|
+
|
18
|
+
base (as an attribute name): denotes an attribute whose value
|
19
|
+
provides a URI to be used as the base for interpreting any
|
20
|
+
relative URIs in the scope of the element on which it
|
21
|
+
appears; its value is inherited. This name is reserved
|
22
|
+
by virtue of its definition in the XML Base specification.
|
23
|
+
|
24
|
+
id (as an attribute name): denotes an attribute whose value
|
25
|
+
should be interpreted as if declared to be of type ID.
|
26
|
+
This name is reserved by virtue of its definition in the
|
27
|
+
xml:id specification.
|
28
|
+
|
29
|
+
lang (as an attribute name): denotes an attribute whose value
|
30
|
+
is a language code for the natural language of the content of
|
31
|
+
any element; its value is inherited. This name is reserved
|
32
|
+
by virtue of its definition in the XML specification.
|
33
|
+
|
34
|
+
space (as an attribute name): denotes an attribute whose
|
35
|
+
value is a keyword indicating what whitespace processing
|
36
|
+
discipline is intended for the content of the element; its
|
37
|
+
value is inherited. This name is reserved by virtue of its
|
38
|
+
definition in the XML specification.
|
39
|
+
|
40
|
+
Father (in any context at all): denotes Jon Bosak, the chair of
|
41
|
+
the original XML Working Group. This name is reserved by
|
42
|
+
the following decision of the W3C XML Plenary and
|
43
|
+
XML Coordination groups:
|
44
|
+
|
45
|
+
In appreciation for his vision, leadership and dedication
|
46
|
+
the W3C XML Plenary on this 10th day of February, 2000
|
47
|
+
reserves for Jon Bosak in perpetuity the XML name
|
48
|
+
xml:Father
|
49
|
+
</xs:documentation>
|
50
|
+
</xs:annotation>
|
51
|
+
|
52
|
+
<xs:annotation>
|
53
|
+
<xs:documentation>This schema defines attributes and an attribute group
|
54
|
+
suitable for use by
|
55
|
+
schemas wishing to allow xml:base, xml:lang, xml:space or xml:id
|
56
|
+
attributes on elements they define.
|
57
|
+
|
58
|
+
To enable this, such a schema must import this schema
|
59
|
+
for the XML namespace, e.g. as follows:
|
60
|
+
<schema . . .>
|
61
|
+
. . .
|
62
|
+
<import namespace="http://www.w3.org/XML/1998/namespace"
|
63
|
+
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
|
64
|
+
|
65
|
+
Subsequently, qualified reference to any of the attributes
|
66
|
+
or the group defined below will have the desired effect, e.g.
|
67
|
+
|
68
|
+
<type . . .>
|
69
|
+
. . .
|
70
|
+
<attributeGroup ref="xml:specialAttrs"/>
|
71
|
+
|
72
|
+
will define a type which will schema-validate an instance
|
73
|
+
element with any of those attributes</xs:documentation>
|
74
|
+
</xs:annotation>
|
75
|
+
|
76
|
+
<xs:annotation>
|
77
|
+
<xs:documentation>In keeping with the XML Schema WG's standard versioning
|
78
|
+
policy, this schema document will persist at
|
79
|
+
http://www.w3.org/2007/08/xml.xsd.
|
80
|
+
At the date of issue it can also be found at
|
81
|
+
http://www.w3.org/2001/xml.xsd.
|
82
|
+
The schema document at that URI may however change in the future,
|
83
|
+
in order to remain compatible with the latest version of XML Schema
|
84
|
+
itself, or with the XML namespace itself. In other words, if the XML
|
85
|
+
Schema or XML namespaces change, the version of this document at
|
86
|
+
http://www.w3.org/2001/xml.xsd will change
|
87
|
+
accordingly; the version at
|
88
|
+
http://www.w3.org/2007/08/xml.xsd will not change.
|
89
|
+
</xs:documentation>
|
90
|
+
</xs:annotation>
|
91
|
+
|
92
|
+
<xs:attribute name="lang">
|
93
|
+
<xs:annotation>
|
94
|
+
<xs:documentation>Attempting to install the relevant ISO 2- and 3-letter
|
95
|
+
codes as the enumerated possible values is probably never
|
96
|
+
going to be a realistic possibility. See
|
97
|
+
RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry
|
98
|
+
at http://www.iana.org/assignments/lang-tag-apps.htm for
|
99
|
+
further information.
|
100
|
+
|
101
|
+
The union allows for the 'un-declaration' of xml:lang with
|
102
|
+
the empty string.</xs:documentation>
|
103
|
+
</xs:annotation>
|
104
|
+
<xs:simpleType>
|
105
|
+
<xs:union memberTypes="xs:language">
|
106
|
+
<xs:simpleType>
|
107
|
+
<xs:restriction base="xs:string">
|
108
|
+
<xs:enumeration value=""/>
|
109
|
+
</xs:restriction>
|
110
|
+
</xs:simpleType>
|
111
|
+
</xs:union>
|
112
|
+
</xs:simpleType>
|
113
|
+
</xs:attribute>
|
114
|
+
|
115
|
+
<xs:attribute name="space">
|
116
|
+
<xs:simpleType>
|
117
|
+
<xs:restriction base="xs:NCName">
|
118
|
+
<xs:enumeration value="default"/>
|
119
|
+
<xs:enumeration value="preserve"/>
|
120
|
+
</xs:restriction>
|
121
|
+
</xs:simpleType>
|
122
|
+
</xs:attribute>
|
123
|
+
|
124
|
+
<xs:attribute name="base" type="xs:anyURI">
|
125
|
+
<xs:annotation>
|
126
|
+
<xs:documentation>See http://www.w3.org/TR/xmlbase/ for
|
127
|
+
information about this attribute.</xs:documentation>
|
128
|
+
</xs:annotation>
|
129
|
+
</xs:attribute>
|
130
|
+
|
131
|
+
<xs:attribute name="id" type="xs:ID">
|
132
|
+
<xs:annotation>
|
133
|
+
<xs:documentation>See http://www.w3.org/TR/xml-id/ for
|
134
|
+
information about this attribute.</xs:documentation>
|
135
|
+
</xs:annotation>
|
136
|
+
</xs:attribute>
|
137
|
+
|
138
|
+
<xs:attributeGroup name="specialAttrs">
|
139
|
+
<xs:attribute ref="xml:base"/>
|
140
|
+
<xs:attribute ref="xml:lang"/>
|
141
|
+
<xs:attribute ref="xml:space"/>
|
142
|
+
<xs:attribute ref="xml:id"/>
|
143
|
+
</xs:attributeGroup>
|
144
|
+
|
145
|
+
</xs:schema>
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module XMLSchemaMetamodel
|
2
|
+
|
3
|
+
module Element::ClassModule
|
4
|
+
def effectiveElement
|
5
|
+
ref || self
|
6
|
+
end
|
7
|
+
def effectiveType
|
8
|
+
e = effectiveElement
|
9
|
+
if e.getType && e.complexType
|
10
|
+
puts "WARN: element has both, a type reference and a contained type"
|
11
|
+
end
|
12
|
+
e.getType || e.complexType || e.simpleType
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module Attribute::ClassModule
|
17
|
+
def effectiveAttribute
|
18
|
+
ref || self
|
19
|
+
end
|
20
|
+
def effectiveType
|
21
|
+
e = effectiveAttribute
|
22
|
+
if e.getType && e.simpleType
|
23
|
+
puts "WARN: attribute has both, a type reference and a contained type"
|
24
|
+
end
|
25
|
+
e.getType || e.simpleType
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module ComplexType::ClassModule
|
30
|
+
def allAttributes
|
31
|
+
attribute + attributeGroup.allAttributes +
|
32
|
+
(complexContent.andand.extension.andand.allAttributes || []) +
|
33
|
+
(simpleContent.andand.extension.andand.allAttributes || [])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module ExtensionType::ClassModule
|
38
|
+
def allAttributes
|
39
|
+
attribute + attributeGroup.allAttributes
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module AttributeGroup::ClassModule
|
44
|
+
def effectiveAttributeGroup
|
45
|
+
ref || self
|
46
|
+
end
|
47
|
+
def allAttributes
|
48
|
+
effectiveAttributeGroup.attribute
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
|