-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathruby_xml2json_binding.rb.erb
156 lines (151 loc) · 7.57 KB
/
ruby_xml2json_binding.rb.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns="http://www.w3.org/2005/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cdf="<%= @locals[:target_schema] %>" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:err="http://www.w3.org/2005/xqt-errors" exclude-result-prefixes="array cdf fn map math xhtml err xs xsi" version="3.0">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:import-schema namespace="<%= @locals[:target_schema] %>" schema-location="<%= @locals[:target_schema] %>" />
<xsl:template match="*|/" priority="-9">
<!-- do nothing -->
</xsl:template>
<xsl:template match="/" name="xsl:initial-template">
<xsl:variable name="json">
<map>
<xsl:apply-templates />
</map>
</xsl:variable>
<xsl:value-of select="xml-to-json($json, map{'number-formatter':function($n){$n}})" />
</xsl:template>
<% require 'active_support/inflector'
%>
<% xml_schema_stereotype = @all_packages.collect{|p| p.applied_stereotypes}.flatten.find{|s| s.name == 'XML Schema'}
@outer_module = @locals[:outer_module] || 'OuterModule'
#object_id_attr = xml_schema_stereotype.applied_tags.find{|t| t.name == 'id_attribute_name'}.value
id_suffix = xml_schema_stereotype.applied_tags.find{|t| t.name == 'id_suffix_for_references'}.value rescue 'Id'
plural_id_suffix = xml_schema_stereotype.applied_tags.find{|t| t.name == 'id_suffix_for_plural_references'}.value rescue 'Ids'
version = @locals[:version]
version ||= 'v' + @all_packages.collect{|p| p.applied_stereotypes}.flatten.find{|s| s.name == 'XML Schema'}.applied_tags.find{|t| t.name == 'major_version'}.value rescue nil
raise "You must specify a version for the domain model" unless version
def get_property_name(property, singular_id_suffix, plural_id_suffix, pluralize_roles = false, underscore = false)
name = property.name
name ||= property.type.name
name = name.underscore if underscore
if property.association? && !(property.attribute? || property.composite?)
id_suffix = property.multiple? ? plural_id_suffix : singular_id_suffix
name = name + id_suffix
else
name = name.pluralize if property.multiple? && pluralize_roles
end
name
end
def get_default_value(property)
if property.multiple?
", :default => []"
end
end
def get_property_type(property)
if !(property.type.primitive? || property.type.enumeration? || (property.association? && !(property.attribute?) && !(property.composite?))) # This may not cover all necessary cases
"map"
elsif property.type.primitive? && [UmlMetamodel::PRIMITIVES[:integer],UmlMetamodel::PRIMITIVES[:float], UmlMetamodel::PRIMITIVES[:double]].include?(property.type.base_primitive)
"number"
elsif property.type.primitive? && [UmlMetamodel::PRIMITIVES[:boolean]].include?(property.type.base_primitive)
"boolean"
else
"string"
end
end
%>
<% @all_packages.each do |package| %>
<% fully_qualified_package_name = @outer_module + '.' + package.qualified_name%>
<% package.classes.sort_by{|c|c.name}.each do |klass| %>
<%# the not ensures we don't match any parent types, we will call them explicitly %>
<%# abstracts should have no match!%>
<%# determines class hierarchy depth %>
<% getDepth = -> (klasses, highest) {
curHigh = highest;
klasses.each {
|x|
lastHigh = 0
if x.children.any?
lastHigh = getDepth.call(x.children, highest + 1)
end
if (lastHigh > curHigh )
curHigh = lastHigh
end
}
return curHigh
}
%>
<xsl:template name="cdf:<%= klass.name %>" match="element(*, cdf:<%= klass.name %>)"<%if klass.children.any?%> priority="<%=getDepth.call(klass.children,1)*-1 %>"<%end%>>
<xsl:param name="set_type" select="false()" />
<% if klass.parents.empty? && klass.properties.any?{|property| property.association? && property.opposite.is_navigable && !property.opposite.composite? }%>
<% end %>
<% if klass.parents.empty? && klass.properties.any?{|property| property.association? && property.opposite.is_navigable && !property.opposite.composite? } %>
<string key="@id"><xsl:value-of select="@ObjectId" /></string>
<% end %>
<% klass.properties.sort_by{|p|(p.name || p.type.name).underscore}.each do |property| %>
<% next unless property.is_navigable %>
<% property_name = get_property_name(property, id_suffix, plural_id_suffix) %>
<% klass_has_simple_content = klass.properties.any?{|p| p.applied_stereotypes.any?{|s| s.name == 'simpleContent'}} %>
<% is_xml_attribute = (klass_has_simple_content && !property.applied_stereotypes.any?{|s| s.name == 'simpleContent' }) || property.applied_stereotypes.any?{|s| s.name == 'xmlAttribute'} %>
<%# determine if we need to output the property %>
<% if is_xml_attribute %>
<xsl:where-populated>
<% elsif property.applied_stereotypes.any?{|s| s.name == 'simpleContent' } %>
<string key="<%= property_name %>"><xsl:value-of select="." /></string>
<% next %>
<% else %>
<xsl:where-populated>
<% end %>
<%# if it is an array, then we need to apply special logic %>
<% calculated_data_type = property.multiple? ? 'array' : get_property_type(property) %>
<% is_idrefs = !property.composite? && property.association? %>
<%# output calculated data type, could be a array %>
<<%= calculated_data_type %> key="<%= property_name %>">
<% if property.multiple? %>
<% if is_idrefs %>
<%# handle the use of IDREFS, which must map to arrays %>
<%# fn:data is a schema aware function, but we must use it as
fn:tokenize throws an error with multiple IDs
https://stackoverflow.com/questions/39881920/xquery-multivalued-fields-idrefs %>
<xsl:for-each select="data(cdf:<%=property_name%>)">
<% else %>
<xsl:for-each select="cdf:<%=property_name%>">
<% end %>
<% if get_property_type(property) == 'map' %>
<%# use anonynomous map %>
<map>
<xsl:apply-templates select="." />
</map>
<% elsif is_xml_attribute %>
<<%= get_property_type(property) %>>
<xsl:value-of select="." />
</<%= get_property_type(property) %>>
<% else %>
<<%= get_property_type(property) %>>
<xsl:value-of select="." />
</<%= get_property_type(property) %>>
<% end %>
</xsl:for-each>
<%else%>
<% if get_property_type(property) == 'map' %>
<xsl:apply-templates select="cdf:<%= property_name %>" />
<% elsif is_xml_attribute %>
<xsl:value-of select="@<%= property_name %>" />
<% else %>
<xsl:value-of select="cdf:<%= property_name %>" />
<% end %>
<% end %>
</<%= calculated_data_type%>>
</xsl:where-populated>
<% end %>
<xsl:if test="not($set_type)">
<string key="@type"><%= package.qualified_name %>.<%= klass.name %></string>
</xsl:if>
<%# Call parent class' template %>
<%if klass.parents.any?%>
<xsl:call-template name="cdf:<%=klass.parents.first.name%>">
<xsl:with-param name="set_type" select="true()" />
</xsl:call-template>
<% end %>
</xsl:template>
<% end %>
<% end %>
</xsl:stylesheet>