Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support encoding in parsing #189

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/lutaml/model/json_adapter/json_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Model
module JsonAdapter
# Base class for JSON documents
class JsonDocument < JsonObject
def self.parse(json)
def self.parse(json, _options = {})
raise NotImplementedError, "Subclasses must implement `parse`."
end

Expand Down
2 changes: 1 addition & 1 deletion lib/lutaml/model/json_adapter/multi_json_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Lutaml
module Model
module JsonAdapter
class MultiJsonAdapter < JsonDocument
def self.parse(json)
def self.parse(json, _options = {})
data = MultiJson.load(json)
new(data)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/lutaml/model/json_adapter/standard_json_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Lutaml
module Model
module JsonAdapter
class StandardJsonAdapter < JsonDocument
def self.parse(json)
def self.parse(json, _options = {})
JSON.parse(json, create_additions: false)
end

Expand Down
20 changes: 11 additions & 9 deletions lib/lutaml/model/serialize.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def add_custom_handling_methods_to_model(klass)
Utils.add_boolean_accessor_if_not_defined(klass, :ordered)
Utils.add_boolean_accessor_if_not_defined(klass, :mixed)
Utils.add_accessor_if_not_defined(klass, :element_order)
Utils.add_accessor_if_not_defined(klass, :encoding)

Utils.add_method_if_not_defined(klass,
:using_default_for) do |attribute_name|
Expand Down Expand Up @@ -101,23 +102,22 @@ def attribute(name, type, options = {})
end
end

define_method(:"from_#{format}") do |data|
define_method(:"from_#{format}") do |data, options = {}|
adapter = Lutaml::Model::Config.send(:"#{format}_adapter")

doc = adapter.parse(data)
public_send(:"of_#{format}", doc)
doc = adapter.parse(data, options)
public_send(:"of_#{format}", doc, options)
end

define_method(:"of_#{format}") do |doc|
define_method(:"of_#{format}") do |doc, options = {}|
if doc.is_a?(Array)
return doc.map do |item|
send(:"of_#{format}", item)
end
return doc.map { |item| send(:"of_#{format}", item) }
end

if format == :xml
doc_hash = doc.parse_element(doc.root, self, :xml)
apply_mappings(doc_hash, format)
options[:encoding] = doc.encoding
apply_mappings(doc_hash, format, options)
else
apply_mappings(doc.to_h, format)
end
Expand Down Expand Up @@ -315,6 +315,7 @@ def apply_mappings(doc, format, options = {})
end

def apply_xml_mapping(doc, instance, options = {})
instance.encoding = options[:encoding]
return instance unless doc

if options[:default_namespace].nil?
Expand Down Expand Up @@ -459,7 +460,7 @@ def ensure_utf8(value)
end
end

attr_accessor :element_order, :schema_location
attr_accessor :element_order, :schema_location, :encoding
attr_writer :ordered, :mixed

def initialize(attrs = {})
Expand Down Expand Up @@ -548,6 +549,7 @@ def key_value(hash, key)
options)
end

options[:parse_encoding] = encoding if encoding
adapter.new(representation).public_send(:"to_#{format}", options)
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/lutaml/model/toml_adapter/toml_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Model
module TomlAdapter
# Base class for TOML documents
class TomlDocument < TomlObject
def self.parse(toml)
def self.parse(toml, _options = {})
raise NotImplementedError, "Subclasses must implement `parse`."
end

Expand Down
2 changes: 1 addition & 1 deletion lib/lutaml/model/toml_adapter/toml_rb_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Lutaml
module Model
module TomlAdapter
class TomlRbAdapter < TomlDocument
def self.parse(toml)
def self.parse(toml, _options = {})
data = TomlRB.parse(toml)
new(data)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/lutaml/model/toml_adapter/tomlib_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Lutaml
module Model
module TomlAdapter
class TomlibAdapter < TomlDocument
def self.parse(toml)
def self.parse(toml, _options = {})
data = Tomlib.load(toml)
new(data)
end
Expand Down
8 changes: 5 additions & 3 deletions lib/lutaml/model/xml_adapter/nokogiri_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ module Lutaml
module Model
module XmlAdapter
class NokogiriAdapter < XmlDocument
def self.parse(xml)
parsed = Nokogiri::XML(xml)
def self.parse(xml, options = {})
parsed = Nokogiri::XML(xml, nil, options[:encoding])
root = NokogiriElement.new(parsed.root)
new(root)
new(root, parsed.encoding)
end

def to_xml(options = {})
builder_options = {}

if options.key?(:encoding)
builder_options[:encoding] = options[:encoding] unless options[:encoding].nil?
elsif options.key?(:parse_encoding)
builder_options[:encoding] = options[:parse_encoding]
else
builder_options[:encoding] = "UTF-8"
end
Expand Down
2 changes: 1 addition & 1 deletion lib/lutaml/model/xml_adapter/oga_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Lutaml
module Model
module XmlAdapter
class OgaAdapter < XmlDocument
def self.parse(xml)
def self.parse(xml, _options = {})
parsed = Oga.parse_xml(xml)
root = OgaElement.new(parsed)
new(root)
Expand Down
30 changes: 20 additions & 10 deletions lib/lutaml/model/xml_adapter/ox_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,28 @@ module Lutaml
module Model
module XmlAdapter
class OxAdapter < XmlDocument
def self.parse(xml)
def self.parse(xml, options = {})
Ox.default_options = Ox.default_options.merge(encoding: options[:encoding] || "UTF-8")

parsed = Ox.parse(xml)
root = OxElement.new(parsed)
new(root)
new(root, Ox.default_options[:encoding])
end

def to_xml(options = {})
builder = Builder::Ox.build
builder_options = { version: options[:version] }

if options.key?(:encoding)
builder_options[:encoding] = options[:encoding] unless options[:encoding].nil?
else
builder_options[:encoding] = "UTF-8"
end
builder_options[:encoding] = if options.key?(:encoding)
options[:encoding]
elsif options.key?(:parse_encoding)
options[:parse_encoding]
else
"UTF-8"
end

builder = Builder::Ox.build
builder.xml.instruct(:xml, encoding: options[:parse_encoding])

builder.xml.instruct(:xml, builder_options)
if @root.is_a?(Lutaml::Model::XmlAdapter::OxElement)
@root.build_xml(builder)
elsif ordered?(@root, options)
Expand All @@ -34,7 +39,12 @@ def to_xml(options = {})
end

xml_data = builder.xml.to_s
options[:declaration] ? xml_data : xml_data.sub(/\A<\?xml[^>]*\?>\n?/, "")
if builder_options[:encoding] && xml_data.valid_encoding?
xml_data = xml_data.encode(builder_options[:encoding])
end

stripped_data = xml_data.lines.drop(1).join
options[:declaration] ? declaration(options) + stripped_data : stripped_data
end

private
Expand Down
7 changes: 4 additions & 3 deletions lib/lutaml/model/xml_adapter/xml_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ module Lutaml
module Model
module XmlAdapter
class XmlDocument
attr_reader :root
attr_reader :root, :encoding

def initialize(root)
def initialize(root, encoding = nil)
@root = root
@encoding = encoding
end

def self.parse(xml)
def self.parse(xml, _options = {})
raise NotImplementedError, "Subclasses must implement `parse`."
end

Expand Down
2 changes: 1 addition & 1 deletion lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class StandardYamlAdapter < YamlDocument
PERMITTED_CLASSES_BASE
end.freeze

def self.parse(yaml)
def self.parse(yaml, _options = {})
YAML.safe_load(yaml, permitted_classes: PERMITTED_CLASSES)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/lutaml/model/yaml_adapter/yaml_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Model
module YamlAdapter
# Base class for YAML documents
class YamlDocument < YamlObject
def self.parse(yaml)
def self.parse(yaml, _options = {})
raise NotImplementedError, "Subclasses must implement `parse`."
end

Expand Down
5 changes: 5 additions & 0 deletions spec/fixtures/xml/latin_encoding.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<note>
<to>José</to>
<from>Müller</from>
<heading>Reminder</heading>
</note>
4 changes: 4 additions & 0 deletions spec/fixtures/xml/shift_jis.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<root>
<FieldName>Žè‘‚«‰pŽš‚P</FieldName>
<FieldName>123456</FieldName>
</root>
Loading
Loading