xsd_struct 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1c1c5f92fb6a7e7b8b6200de5ab3af4b28b6c53deac97d3d7afe1320fe6eb33b
4
+ data.tar.gz: f9463188c81bb62633693623c552ecbf96dddca1f6cd8257a12276da4a8b0b69
5
+ SHA512:
6
+ metadata.gz: 9ec4efce2cb37f56222a6f3ae26fd0615447506b16e768877aa1dec95be1d078fe1c885101e0fb228a31082f508bff4f3ec4dde11076f1ead56bd643c15e7a9f
7
+ data.tar.gz: 68568be909b88169c0006ce36bfd900f5538319c144e0a456287cf72abc6cb5d26528221e3818c1a24442547a886f7ce32301351fbb8fa8665000f9ea60eba87
data/AI_POLICY.md ADDED
@@ -0,0 +1,5 @@
1
+ # AI / LLMs Policy
2
+
3
+ An interactions - whether they be code, issues or documentation - must be entirely written by humans.
4
+
5
+ For reasons as to why LLM tools are not welcome here, a good starting point is https://whynoai.info.
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2026-10-31
4
+
5
+ - Initial release
@@ -0,0 +1,89 @@
1
+ # Contributor Covenant 3.0 Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We pledge to make our community welcoming, safe, and equitable for all.
6
+
7
+ We are committed to fostering an environment that respects and promotes the dignity, rights, and contributions of all individuals, regardless of characteristics including race, ethnicity, caste, colour, age, physical characteristics, neurodiversity, disability, sex or gender, gender identity or expression, sexual orientation, language, philosophy or religion, national or social origin, socio-economic position, level of education, or other status. The same privileges of participation are extended to everyone who participates in good faith and in accordance with this Covenant.
8
+
9
+
10
+ ## Encouraged Behaviours
11
+
12
+ While acknowledging differences in social norms, we all strive to meet our community's expectations for positive behaviour. We also understand that our words and actions may be interpreted differently than we intend based on culture, background, or native language.
13
+
14
+ With these considerations in mind, we agree to behave mindfully toward each other and act in ways that centre our shared values, including:
15
+
16
+ 1. Respecting the **purpose of our community**, our activities, and our ways of gathering.
17
+ 2. Engaging **kindly and honestly** with others.
18
+ 3. Respecting **different viewpoints** and experiences.
19
+ 4. **Taking responsibility** for our actions and contributions.
20
+ 5. Gracefully giving and accepting **constructive feedback**.
21
+ 6. Committing to **repairing harm** when it occurs.
22
+ 7. Behaving in other ways that promote and sustain the **well-being of our community**.
23
+
24
+
25
+ ## Restricted Behaviours
26
+
27
+ We agree to restrict the following behaviours in our community. Instances, threats, and promotion of these behaviours are violations of this Code of Conduct.
28
+
29
+ 1. **Harassment.** Violating explicitly expressed boundaries or engaging in unnecessary personal attention after any clear request to stop.
30
+ 2. **Character attacks.** Making insulting, demeaning, or pejorative comments directed at a community member or group of people.
31
+ 3. **Stereotyping or discrimination.** Characterising anyone’s personality or behaviour on the basis of immutable identities or traits.
32
+ 4. **Sexualization.** Behaving in a way that would generally be considered inappropriately intimate in the context or purpose of the community.
33
+ 5. **Violating confidentiality**. Sharing or acting on someone's personal or private information without their permission.
34
+ 6. **Endangerment.** Causing, encouraging, or threatening violence or other harm toward any person or group.
35
+ 7. Behaving in other ways that **threaten the well-being** of our community.
36
+
37
+ ### Other Restrictions
38
+
39
+ 1. **Misleading identity.** Impersonating someone else for any reason, or pretending to be someone else to evade enforcement actions.
40
+ 2. **Failing to credit sources.** Not properly crediting the sources of content you contribute.
41
+ 3. **Promotional materials**. Sharing marketing or other commercial content in a way that is outside the norms of the community.
42
+ 4. **Irresponsible communication.** Failing to responsibly present content which includes, links or describes any other restricted behaviours.
43
+
44
+
45
+ ## Reporting an Issue
46
+
47
+ Tensions can occur between community members even when they are trying their best to collaborate. Not every conflict represents a code of conduct violation, and this Code of Conduct reinforces encouraged behaviours and norms that can help avoid conflicts and minimise harm.
48
+
49
+ When an incident does occur, it is important to report it promptly. To report a possible violation, please email pat@freelancing-gods.com.
50
+
51
+ Community Moderators take reports of violations seriously and will make every effort to respond in a timely manner. They will investigate all reports of code of conduct violations, reviewing messages, logs, and recordings, or interviewing witnesses and other participants. Community Moderators will keep investigation and enforcement actions as transparent as possible while prioritising safety and confidentiality. In order to honour these values, enforcement actions are carried out in private with the involved parties, but communicating to the whole community may be part of a mutually agreed upon resolution.
52
+
53
+
54
+ ## Addressing and Repairing Harm
55
+
56
+ If an investigation by the Community Moderators finds that this Code of Conduct has been violated, the following enforcement ladder may be used to determine how best to repair harm, based on the incident's impact on the individuals involved and the community as a whole. Depending on the severity of a violation, lower rungs on the ladder may be skipped.
57
+
58
+ 1) Warning
59
+ 1) Event: A violation involving a single incident or series of incidents.
60
+ 2) Consequence: A private, written warning from the Community Moderators.
61
+ 3) Repair: Examples of repair include a private written apology, acknowledgement of responsibility, and seeking clarification on expectations.
62
+ 2) Temporarily Limited Activities
63
+ 1) Event: A repeated incidence of a violation that previously resulted in a warning, or the first incidence of a more serious violation.
64
+ 2) Consequence: A private, written warning with a time-limited cooldown period designed to underscore the seriousness of the situation and give the community members involved time to process the incident. The cooldown period may be limited to particular communication channels or interactions with particular community members.
65
+ 3) Repair: Examples of repair may include making an apology, using the cooldown period to reflect on actions and impact, and being thoughtful about re-entering community spaces after the period is over.
66
+ 3) Temporary Suspension
67
+ 1) Event: A pattern of repeated violation which the Community Moderators have tried to address with warnings, or a single serious violation.
68
+ 2) Consequence: A private written warning with conditions for return from suspension. In general, temporary suspensions give the person being suspended time to reflect upon their behaviour and possible corrective actions.
69
+ 3) Repair: Examples of repair include respecting the spirit of the suspension, meeting the specified conditions for return, and being thoughtful about how to reintegrate with the community when the suspension is lifted.
70
+ 4) Permanent Ban
71
+ 1) Event: A pattern of repeated code of conduct violations that other steps on the ladder have failed to resolve, or a violation so serious that the Community Moderators determine there is no way to keep the community safe with this person as a member.
72
+ 2) Consequence: Access to all community spaces, tools, and communication channels is removed. In general, permanent bans should be rarely used, should have strong reasoning behind them, and should only be resorted to if working through other remedies has failed to change the behaviour.
73
+ 3) Repair: There is no possible repair in cases of this severity.
74
+
75
+ This enforcement ladder is intended as a guideline. It does not limit the ability of Community Managers to use their discretion and judgment, in keeping with the best interests of our community.
76
+
77
+
78
+ ## Scope
79
+
80
+ This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public or other spaces. Examples of representing our community include using an official email address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
81
+
82
+
83
+ ## Attribution
84
+
85
+ This Code of Conduct is adapted from the Contributor Covenant, version 3.0, permanently available at [https://www.contributor-covenant.org/version/3/0/](https://www.contributor-covenant.org/version/3/0/).
86
+
87
+ Contributor Covenant is stewarded by the Organization for Ethical Source and licensed under CC BY-SA 4.0. To view a copy of this license, visit [https://creativecommons.org/licenses/by-sa/4.0/](https://creativecommons.org/licenses/by-sa/4.0/)
88
+
89
+ For answers to common questions about Contributor Covenant, see the FAQ at [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq). Translations are provided at [https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations). Additional enforcement and community guideline resources can be found at [https://www.contributor-covenant.org/resources](https://www.contributor-covenant.org/resources). The enforcement ladder was inspired by the work of [Mozilla’s code of conduct team](https://github.com/mozilla/inclusion).
data/LICENSE.txt ADDED
@@ -0,0 +1,17 @@
1
+ MIT NON-AI License
2
+
3
+ Copyright (c) 2026, Pat Allan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of the software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions.
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ In addition, the following restrictions apply:
10
+
11
+ 1. The Software and any modifications made to it may not be used for the purpose of training or improving machine learning algorithms, including but not limited to artificial intelligence, natural language processing, or data mining. This condition applies to any derivatives, modifications, or updates based on the Software code. Any usage of the Software in an AI-training dataset is considered a breach of this License.
12
+
13
+ 2. The Software may not be included in any dataset used for training or improving machine learning algorithms, including but not limited to artificial intelligence, natural language processing, or data mining.
14
+
15
+ 3. Any person or organisation found to be in violation of these restrictions will be subject to legal action and may be held liable for any damages resulting from such use.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # XSD Struct
2
+
3
+ Take an XSD schema and turn XML documents following that schema into Ruby object trees.
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ ```bash
10
+ bundle add xsd_struct
11
+ ```
12
+
13
+ If bundler is not being used to manage dependencies, install the gem by executing:
14
+
15
+ ```bash
16
+ gem install xsd_struct
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ To load a new schema in, you can either refer to the raw string XSD (which is itself an XML document):
22
+
23
+ ```ruby
24
+ schema = XSDStruct::Schema.new(
25
+ "<?xml version="1.0" encoding="UTF-8" ?> ..."
26
+ )
27
+ ```
28
+
29
+ Or, you can load the schema from a file. This has the additional benefit that the schema can refer to other files to build out its full understanding.
30
+
31
+ ```ruby
32
+ schema = XSDStruct::Schema.from_path("./path/to/schema.xsd")
33
+ ```
34
+
35
+ It's also possible to refer to a gzipped schema, which is useful when the schema files are extremely large:
36
+
37
+ ```ruby
38
+ schema = XSDStruct::Schema.from_path(
39
+ "./path/to/schema.gz", gzip: true
40
+ )
41
+ ```
42
+
43
+ Once a schema is loaded, then you can pass in the raw string of an XML document which conforms to that schema, to retrieve an object tree representing the document. It responds to methods matching any root element names, downcased and underscored to match usual Ruby naming styles. So, as a contrived example:
44
+
45
+ ```ruby
46
+ document = schema.build("<Page><Item id="7" /></Page>")
47
+ # presuming a page may have many items:
48
+ document.page.items.first.id #=> 7
49
+ ```
50
+
51
+ ## Development
52
+
53
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
54
+
55
+ ## Contributing
56
+
57
+ Bug reports and pull requests are welcome on Codeberg at https://codeberg.org/patallan/xsd_struct. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://codeberg.org/patallan/xsd_struct/src/branch/main/CODE_OF_CONDUCT.md) and [AI/LLMs policy](https://codeberg.org/patallan/xsd_struct/src/branch/main/AI_POLICY.md).
58
+
59
+ ## License
60
+
61
+ The gem is available as open source under the terms of a [modified MIT License](https://codeberg.org/patallan/xsd_struct/src/branch/main/LICENSE.txt) - mostly the same, but cannot be used for training/improving machine learning algorithms (AI/LLMs) directly or indirectly.
62
+
63
+ ## Code of Conduct
64
+
65
+ Everyone interacting in the xsd_struct project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://codeberg.org/patallan/xsd_struct/src/branch/main/CODE_OF_CONDUCT.md).
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "attribute_valuer"
4
+
5
+ module XSDStruct
6
+ # Appends a method to an element subclass for a given attribute. The method
7
+ # name will be the attribute's name, but translated to idiomatic Ruby - so,
8
+ # downcased and underscored.
9
+ #
10
+ class AttributeMethod
11
+ def self.call(...)
12
+ new(...).call
13
+ end
14
+
15
+ def initialize(klass, attribute)
16
+ @klass = klass
17
+ @attribute = attribute
18
+ end
19
+
20
+ def call
21
+ valuer = AttributeValuer.new(attribute)
22
+ name = valuer.accessor_name
23
+
24
+ klass.define_method(name) do
25
+ attributes[name] ||= valuer.call(node)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :klass, :attribute
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module XSDStruct
4
+ # Generates a attribute's value for a given element.
5
+ #
6
+ class AttributeValuer
7
+ def initialize(attribute)
8
+ @attribute = attribute
9
+ end
10
+
11
+ def call(parent)
12
+ parent.attributes[attribute.name].value
13
+ end
14
+
15
+ def accessor_name
16
+ XSDStruct.inflector.underscore(attribute.name)
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :attribute
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ require_relative "element"
6
+
7
+ module XSDStruct
8
+ # XSDStruct::Cache maintains a known list of Element classes, representing
9
+ # each element in the given XSD document reader.
10
+ #
11
+ # The cache is lazily loaded, meaning that only elements that are traversed
12
+ # are generated.
13
+ class Cache
14
+ def initialize(reader)
15
+ @reader = reader
16
+ @cache = {}
17
+ end
18
+
19
+ def [](tree)
20
+ cache.fetch(tree) do
21
+ Element.generate(definition(tree), self, tree)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :reader, :cache
28
+
29
+ def definition(tree)
30
+ tree.inject(reader) { |parent, name| parent[name] } || reader[tree.last]
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "element_method"
4
+
5
+ module XSDStruct
6
+ # XSDStruct::Document represents the root of an XML document that has been
7
+ # parsed according to a given XSD schema.
8
+ #
9
+ # It responds to methods matching any root element names, downcased and
10
+ # underscored to match usual Ruby naming styles. So, for example:
11
+ #
12
+ # document = schema.build("<Page><Item id="7" /></Page>")
13
+ # # presuming a page may have many items:
14
+ # document.page.items.first.id #=> 7
15
+ #
16
+ class Document
17
+ def self.generate(xsd, cache)
18
+ klass = Class.new(Document)
19
+
20
+ xsd.elements.each do |element|
21
+ ElementMethod.call(klass, element, cache, [])
22
+ end
23
+
24
+ klass
25
+ end
26
+
27
+ def initialize(node)
28
+ @node = node
29
+ @elements = {}
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :node, :elements
35
+ end
36
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/inflector"
4
+
5
+ require_relative "attribute_method"
6
+ require_relative "element_method"
7
+
8
+ module XSDStruct
9
+ # Represents an element/node in an XML object tree. Attributes and inner
10
+ # elements can be accessed via methods (downcased, underscored, and pluralised
11
+ # where appropriate).
12
+ #
13
+ # If this element does not have any attributes or inner/sub-elements, then
14
+ # the value can be returned directly - and will be typed beyond raw strings if
15
+ # possible.
16
+ #
17
+ class Element
18
+ def self.generate(xsd, cache, tree)
19
+ klass = Class.new(Element)
20
+
21
+ xsd.collect_attributes.each do |attribute|
22
+ AttributeMethod.call(klass, attribute)
23
+ end
24
+
25
+ xsd.collect_elements.each do |element|
26
+ ElementMethod.call(klass, element, cache, tree)
27
+ end
28
+
29
+ klass
30
+ end
31
+
32
+ def initialize(node, schema)
33
+ @node = node
34
+ @schema = schema
35
+ @attributes = {}
36
+ @elements = {}
37
+ end
38
+
39
+ def value
40
+ case schema.data_type
41
+ when "positiveInteger"
42
+ node.text.to_i
43
+ when "decimal"
44
+ node.text.to_f
45
+ else
46
+ node.text
47
+ end
48
+ end
49
+
50
+ def value_or_self
51
+ direct? ? value : self
52
+ end
53
+
54
+ private
55
+
56
+ attr_reader :node, :schema, :attributes, :elements
57
+
58
+ def direct?
59
+ schema.collect_elements.empty? && schema.collect_attributes.empty?
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "element_valuer"
4
+
5
+ module XSDStruct
6
+ # Appends a method to an element subclass for a given sub-element. The method
7
+ # name will be the sub-element's name, but translated to idiomatic Ruby - so,
8
+ # downcased and underscored - and will also be plural if multiple instances of
9
+ # the sub-element are allowed.
10
+ #
11
+ class ElementMethod
12
+ def self.call(...)
13
+ new(...).call
14
+ end
15
+
16
+ def initialize(klass, element, cache, tree)
17
+ @klass = klass
18
+ @element = element
19
+ @cache = cache
20
+ @tree = tree
21
+ end
22
+
23
+ def call
24
+ valuer = ElementValuer.new(element, cache, tree)
25
+ name = valuer.accessor_name
26
+
27
+ klass.define_method(name) do
28
+ elements[name] ||= valuer.call(node)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :klass, :element, :cache, :tree
35
+ end
36
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module XSDStruct
4
+ # Generates a sub-element's value for a given parent. In the situation where
5
+ # the parent can have multiple sub-elements of the same type, this will return
6
+ # an array, but otherwise a single value.
7
+ #
8
+ # If the element has no possible children or attributes, then the raw text of
9
+ # that element is instead returned, typed accordingly where possible.
10
+ #
11
+ class ElementValuer
12
+ def initialize(element, cache, parent_tree)
13
+ @element = element
14
+ @cache = cache
15
+ @tree = parent_tree + [element.name]
16
+ end
17
+
18
+ def call(parent)
19
+ values = parent
20
+ .children
21
+ .select { |child| child.name == element.name }
22
+ .collect { |child| cache[tree].new(child, element).value_or_self }
23
+
24
+ element.multiple_allowed? ? values : values.first
25
+ end
26
+
27
+ def accessor_name
28
+ if element.multiple_allowed?
29
+ XSDStruct.inflector.pluralize(XSDStruct.inflector.underscore(element.name))
30
+ else
31
+ XSDStruct.inflector.underscore(element.name)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ attr_reader :element, :cache, :tree
38
+ end
39
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "nokogiri"
4
+ require "xsd"
5
+ require "zlib"
6
+
7
+ require_relative "cache"
8
+ require_relative "document"
9
+
10
+ module XSDStruct
11
+ # XSDStruct::Schema performs the initial parsing of a raw XSD string, which
12
+ # can then in turn be used to generate object trees from an XML document that
13
+ # conforms to the schema.
14
+ #
15
+ # To load a new schema in, you can either refer to the raw string XSD (which
16
+ # is itself an XML document):
17
+ #
18
+ # schema = XSDStruct::Schema.new(
19
+ # "<<?xml version="1.0" encoding="UTF-8" ?> ..."
20
+ # )
21
+ #
22
+ # Or, you can load the schema from a file. This has the additional benefit
23
+ # that the schema can refer to other files to build out its full
24
+ # understanding.
25
+ #
26
+ # schema = XSDStruct::Schema.from_path("./path/to/schema.xsd")
27
+ #
28
+ # It's also possible to refer to a gzipped schema, which is useful when the
29
+ # schema files are extremely large:
30
+ #
31
+ # schema = XSDStruct::Schema.from_path(
32
+ # "./path/to/schema.gz", gzip: true
33
+ # )
34
+ #
35
+ # Once a schema is loaded, then you can pass in the raw string of an XML
36
+ # document which conforms to that schema, to retrieve an object tree
37
+ # representing the document:
38
+ #
39
+ # document = schema.build("<?xml version="1.0" encoding="UTF-8" ?> ...")
40
+ #
41
+ # This document is an instance of XSDStruct::Document.
42
+ #
43
+ class Schema
44
+ def self.from_path(path, gzip: false)
45
+ raw = gzip ? Zlib::Inflate.inflate(File.binread(path)) : File.read(path)
46
+
47
+ new(raw, location: path)
48
+ end
49
+
50
+ def initialize(raw, location: nil)
51
+ @raw = raw
52
+ @location = location
53
+ end
54
+
55
+ def build(raw)
56
+ XSDStruct::Document
57
+ .generate(reader, cache)
58
+ .new(Nokogiri::XML(raw))
59
+ end
60
+
61
+ private
62
+
63
+ attr_reader :raw, :location
64
+
65
+ def cache
66
+ @cache ||= XSDStruct::Cache.new(reader)
67
+ end
68
+
69
+ def reader
70
+ @reader ||= XSD::XML.new.tap do |xml_reader|
71
+ xml_reader.add_schema_xml(raw, location:)
72
+ end
73
+ end
74
+ end
75
+ end
data/lib/xsd_struct.rb ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/inflector"
4
+ require "nokogiri"
5
+
6
+ # XSDStruct transforms XML documents into object trees, based on a schema
7
+ # defined by an XSD document.
8
+ #
9
+ # See XSDStruct::Schema for usage.
10
+ #
11
+ module XSDStruct
12
+ def self.inflector
13
+ @inflector ||= Dry::Inflector.new
14
+ end
15
+ end
16
+
17
+ require_relative "xsd_struct/schema"
@@ -0,0 +1,52 @@
1
+ module XSDStruct
2
+ type elementValue = (XSDStruct::Element | String | Integer | Float)
3
+
4
+ def self.inflector: () -> Dry::Inflector
5
+
6
+ class AttributeMethod
7
+ def self.call: (::Class klass, XSD::Attribute attribute) -> ::Symbol
8
+ def initialize: (::Class klass, XSD::Attribute attribute) -> void
9
+ def call: () -> ::Symbol
10
+ end
11
+
12
+ class AttributeValuer
13
+ def initialize: (XSD::Attribute attribute) -> void
14
+ def call: (untyped parent) -> String
15
+ def accessor_name: () -> String
16
+ end
17
+
18
+ class Cache
19
+ def initialize: (XSD::XML reader) -> void
20
+ def []: (Array[String] tree) -> Class
21
+ end
22
+
23
+ class Document
24
+ def self.generate: (XSD::XML xsd, XSDStruct::Cache cache) -> Class
25
+ def initialize: (Nokogiri::XML::Document node) -> void
26
+ end
27
+
28
+ class ElementMethod
29
+ def self.call: (Class klass, XSD::Element element, XSDStruct::Cache cache, Array[String] tree) -> Symbol
30
+ def initialize: (Class klass, XSD::Element element, XSDStruct::Cache cache, Array[String] tree) -> void
31
+ def call: () -> Symbol
32
+ end
33
+
34
+ class ElementValuer
35
+ def initialize: (XSD::Element element, XSDStruct::Cache cache, Array[String] parent_tree) -> void
36
+ def call: (untyped parent) -> (elementValue | Array[elementValue] | nil)
37
+ def accessor_name: () -> String
38
+ end
39
+
40
+ class Element
41
+ def self.generate: (XSD::Element xsd, XSDStruct::Cache cache, Array[String] tree) -> Class
42
+ def initialize: (Nokogiri::XML::Node node, XSD::Element schema) -> void
43
+ def value: () -> (String | Integer | Float)
44
+ def value_or_self: () -> elementValue
45
+ end
46
+
47
+ class Schema
48
+ def self.from_path: (String path, ?gzip: bool) -> XSDStruct::Schema
49
+ def initialize: (String raw, ?location: (nil | String)) -> void
50
+ def build: (String raw) -> XSDStruct::Document
51
+ end
52
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xsd_struct
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Pat Allan
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: dry-inflector
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '1.2'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '1.2'
26
+ - !ruby/object:Gem::Dependency
27
+ name: nokogiri
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '1.19'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '1.19'
40
+ - !ruby/object:Gem::Dependency
41
+ name: xsd
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '2.9'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '2.9'
54
+ - !ruby/object:Gem::Dependency
55
+ name: zlib
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '3.2'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '3.2'
68
+ description: Uses XSD schemas to turn an XML document into a collection of Ruby objects
69
+ email:
70
+ - pat@freelancing-gods.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - AI_POLICY.md
76
+ - CHANGELOG.md
77
+ - CODE_OF_CONDUCT.md
78
+ - LICENSE.txt
79
+ - README.md
80
+ - lib/xsd_struct.rb
81
+ - lib/xsd_struct/attribute_method.rb
82
+ - lib/xsd_struct/attribute_valuer.rb
83
+ - lib/xsd_struct/cache.rb
84
+ - lib/xsd_struct/document.rb
85
+ - lib/xsd_struct/element.rb
86
+ - lib/xsd_struct/element_method.rb
87
+ - lib/xsd_struct/element_valuer.rb
88
+ - lib/xsd_struct/schema.rb
89
+ - sig/xsd_struct.rbs
90
+ homepage: https://codeberg.org/patallan/xsd_struct
91
+ licenses:
92
+ - MIT NON-AI
93
+ metadata:
94
+ homepage_uri: https://codeberg.org/patallan/xsd_struct
95
+ source_code_uri: https://codeberg.org/patallan/xsd_struct
96
+ changelog_uri: https://codeberg.org/patallan/xsd_struct/src/branch/main/CHANGELOG.md
97
+ rubygems_mfa_required: 'true'
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: 3.3.0
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubygems_version: 4.0.20
113
+ specification_version: 4
114
+ summary: Combine XSD and XML documents to build Ruby object trees
115
+ test_files: []