moxml 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +15 -0
- data/.github/workflows/release.yml +23 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +2 -0
- data/.rubocop_todo.yml +65 -0
- data/.ruby-version +1 -0
- data/Gemfile +10 -3
- data/README.adoc +400 -594
- data/lib/moxml/adapter/base.rb +102 -0
- data/lib/moxml/adapter/customized_oga/xml_declaration.rb +18 -0
- data/lib/moxml/adapter/customized_oga/xml_generator.rb +104 -0
- data/lib/moxml/adapter/nokogiri.rb +314 -0
- data/lib/moxml/adapter/oga.rb +309 -0
- data/lib/moxml/adapter/ox.rb +325 -0
- data/lib/moxml/adapter.rb +26 -170
- data/lib/moxml/attribute.rb +47 -14
- data/lib/moxml/builder.rb +64 -0
- data/lib/moxml/cdata.rb +4 -26
- data/lib/moxml/comment.rb +6 -22
- data/lib/moxml/config.rb +39 -15
- data/lib/moxml/context.rb +29 -0
- data/lib/moxml/declaration.rb +16 -26
- data/lib/moxml/doctype.rb +9 -0
- data/lib/moxml/document.rb +51 -63
- data/lib/moxml/document_builder.rb +87 -0
- data/lib/moxml/element.rb +61 -99
- data/lib/moxml/error.rb +20 -0
- data/lib/moxml/namespace.rb +12 -37
- data/lib/moxml/node.rb +78 -58
- data/lib/moxml/node_set.rb +19 -222
- data/lib/moxml/processing_instruction.rb +6 -25
- data/lib/moxml/text.rb +4 -26
- data/lib/moxml/version.rb +1 -1
- data/lib/moxml/xml_utils/encoder.rb +55 -0
- data/lib/moxml/xml_utils.rb +80 -0
- data/lib/moxml.rb +33 -33
- data/moxml.gemspec +1 -1
- data/spec/moxml/adapter/nokogiri_spec.rb +14 -0
- data/spec/moxml/adapter/oga_spec.rb +14 -0
- data/spec/moxml/adapter/ox_spec.rb +49 -0
- data/spec/moxml/all_with_adapters_spec.rb +46 -0
- data/spec/moxml/config_spec.rb +55 -0
- data/spec/moxml/error_spec.rb +71 -0
- data/spec/moxml/examples/adapter_spec.rb +27 -0
- data/spec/moxml_spec.rb +50 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/shared_examples/attribute.rb +165 -0
- data/spec/support/shared_examples/builder.rb +25 -0
- data/spec/support/shared_examples/cdata.rb +70 -0
- data/spec/support/shared_examples/comment.rb +65 -0
- data/spec/support/shared_examples/context.rb +35 -0
- data/spec/support/shared_examples/declaration.rb +93 -0
- data/spec/support/shared_examples/doctype.rb +25 -0
- data/spec/support/shared_examples/document.rb +110 -0
- data/spec/support/shared_examples/document_builder.rb +43 -0
- data/spec/support/shared_examples/edge_cases.rb +185 -0
- data/spec/support/shared_examples/element.rb +110 -0
- data/spec/support/shared_examples/examples/attribute.rb +42 -0
- data/spec/support/shared_examples/examples/basic_usage.rb +67 -0
- data/spec/support/shared_examples/examples/memory.rb +54 -0
- data/spec/support/shared_examples/examples/namespace.rb +65 -0
- data/spec/support/shared_examples/examples/readme_examples.rb +100 -0
- data/spec/support/shared_examples/examples/thread_safety.rb +43 -0
- data/spec/support/shared_examples/examples/xpath.rb +39 -0
- data/spec/support/shared_examples/integration.rb +135 -0
- data/spec/support/shared_examples/namespace.rb +96 -0
- data/spec/support/shared_examples/node.rb +110 -0
- data/spec/support/shared_examples/node_set.rb +90 -0
- data/spec/support/shared_examples/processing_instruction.rb +88 -0
- data/spec/support/shared_examples/text.rb +66 -0
- data/spec/support/shared_examples/xml_adapter.rb +191 -0
- data/spec/support/xml_matchers.rb +27 -0
- metadata +55 -6
- data/.github/workflows/main.yml +0 -27
- data/lib/moxml/error_handler.rb +0 -77
- data/lib/moxml/errors.rb +0 -169
@@ -0,0 +1,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_examples "xml adapter" do
|
4
|
+
let(:xml) do
|
5
|
+
<<~XML
|
6
|
+
<?xml version="1.0"?>
|
7
|
+
<root xmlns="http://example.org" xmlns:x="http://example.org/x">
|
8
|
+
<child id="1">Text</child>
|
9
|
+
<child id="2"/>
|
10
|
+
<x:special>
|
11
|
+
<![CDATA[Some <special> text]]>
|
12
|
+
<!-- A comment -->
|
13
|
+
<?pi target?>
|
14
|
+
</x:special>
|
15
|
+
</root>
|
16
|
+
XML
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ".parse" do
|
20
|
+
it "parses XML string" do
|
21
|
+
doc = described_class.parse(xml).native
|
22
|
+
expect(described_class.node_type(doc)).to eq(:document)
|
23
|
+
expect(described_class.node_name(described_class.root(doc))).to eq("root")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "handles malformed XML according to strict setting" do
|
27
|
+
malformed = "<root><unclosed>"
|
28
|
+
|
29
|
+
expect do
|
30
|
+
described_class.parse(malformed, strict: true)
|
31
|
+
end.to raise_error(Moxml::ParseError)
|
32
|
+
|
33
|
+
expect do
|
34
|
+
described_class.parse(malformed, strict: false)
|
35
|
+
end.not_to raise_error
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "node creation" do
|
40
|
+
let(:doc) { described_class.create_document }
|
41
|
+
|
42
|
+
it "creates element" do
|
43
|
+
element = described_class.create_element("test")
|
44
|
+
expect(described_class.node_type(element)).to eq(:element)
|
45
|
+
expect(described_class.node_name(element)).to eq("test")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "creates text" do
|
49
|
+
text = described_class.create_text("content")
|
50
|
+
expect(described_class.node_type(text)).to eq(:text)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "creates CDATA" do
|
54
|
+
cdata = described_class.create_cdata("<content>")
|
55
|
+
expect(described_class.node_type(cdata)).to eq(:cdata)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "creates comment" do
|
59
|
+
comment = described_class.create_comment("comment")
|
60
|
+
expect(described_class.node_type(comment)).to eq(:comment)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "creates processing instruction" do
|
64
|
+
pi = described_class.create_processing_instruction("target", "content")
|
65
|
+
expect(described_class.node_type(pi)).to eq(:processing_instruction)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "node manipulation" do
|
70
|
+
let(:doc) { described_class.parse(xml).native }
|
71
|
+
let(:root) { described_class.root(doc) }
|
72
|
+
|
73
|
+
it "gets parent" do
|
74
|
+
child = described_class.children(root).first
|
75
|
+
expect(described_class.parent(child)).to eq(root)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "gets children" do
|
79
|
+
children = described_class.children(root)
|
80
|
+
expect(children.length).to eq(3)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "gets siblings", skip: "Oga includes text nodes into siblings" do
|
84
|
+
children = described_class.children(root)
|
85
|
+
first = children[0]
|
86
|
+
second = children[1]
|
87
|
+
|
88
|
+
expect(described_class.next_sibling(first)).to eq(second)
|
89
|
+
expect(described_class.previous_sibling(second)).to eq(first)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "adds child" do
|
93
|
+
element = described_class.create_element("new")
|
94
|
+
described_class.add_child(root, element)
|
95
|
+
expect(described_class.children(root).last).to eq(element)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "adds text child" do
|
99
|
+
described_class.add_child(root, "text")
|
100
|
+
expect(described_class.children(root).last.text).to eq("text")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "attributes" do
|
105
|
+
let(:doc) { described_class.parse(xml) }
|
106
|
+
let(:element) { described_class.children(described_class.root(doc.native)).first }
|
107
|
+
|
108
|
+
it "gets attributes" do
|
109
|
+
attrs = described_class.attributes(element)
|
110
|
+
expect(attrs.count).to eq(1)
|
111
|
+
expect(attrs.first.value).to eq("1")
|
112
|
+
end
|
113
|
+
|
114
|
+
it "sets attribute" do
|
115
|
+
described_class.set_attribute(element, "new", "value")
|
116
|
+
expect(described_class.get_attribute(element, "new").value).to eq("value")
|
117
|
+
end
|
118
|
+
|
119
|
+
it "removes attribute" do
|
120
|
+
described_class.remove_attribute(element, "id")
|
121
|
+
expect(described_class.get_attribute(element, "id")&.value).to be_nil
|
122
|
+
end
|
123
|
+
|
124
|
+
it "handles special characters in attributes" do
|
125
|
+
described_class.set_attribute(element, "special", '< > & " \'')
|
126
|
+
value = described_class.get_attribute(element, "special")&.to_xml
|
127
|
+
expect(value).to match(/< > & ("|") ('|')/)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "namespaces" do
|
132
|
+
let(:doc) { described_class.parse(xml).native }
|
133
|
+
let(:root) { described_class.root(doc) }
|
134
|
+
let(:special) { described_class.children(root).last }
|
135
|
+
|
136
|
+
it "creates namespace" do
|
137
|
+
ns = described_class.create_namespace(root, "test", "http://test.org")
|
138
|
+
expect(ns).not_to be_nil
|
139
|
+
end
|
140
|
+
|
141
|
+
it "handles namespaced elements" do
|
142
|
+
expect(described_class.node_name(special)).to eq("special")
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "serialization" do
|
147
|
+
let(:doc) { described_class.parse(xml).native }
|
148
|
+
|
149
|
+
it "serializes to XML" do
|
150
|
+
result = described_class.serialize(doc)
|
151
|
+
|
152
|
+
expect(result).to include("<?xml")
|
153
|
+
expect(result).to include("<root")
|
154
|
+
expect(result).to include('xmlns="http://example.org"').once
|
155
|
+
expect(result).to include('xmlns:x="http://example.org/x"').once
|
156
|
+
expect(result).to include("</root>")
|
157
|
+
end
|
158
|
+
|
159
|
+
it "respects indentation settings", skip: "Indent cannot be negative, and zero indent doesn't remove newlines" do
|
160
|
+
unindented = described_class.serialize(doc, indent: 0)
|
161
|
+
indented = described_class.serialize(doc, indent: 2)
|
162
|
+
|
163
|
+
expect(unindented).not_to include("\n ")
|
164
|
+
expect(indented).to include("\n ")
|
165
|
+
end
|
166
|
+
|
167
|
+
it "preserves XML declaration" do
|
168
|
+
result = described_class.serialize(doc)
|
169
|
+
expect(result).to match(/^<\?xml/)
|
170
|
+
end
|
171
|
+
|
172
|
+
it "handles encoding specification" do
|
173
|
+
result = described_class.serialize(doc, encoding: "UTF-8")
|
174
|
+
expect(result).to include('encoding="UTF-8"')
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "xpath" do
|
179
|
+
let(:doc) { described_class.parse(xml) }
|
180
|
+
|
181
|
+
it "finds nodes by xpath" do
|
182
|
+
nodes = described_class.xpath(doc, "//xmlns:child")
|
183
|
+
expect(nodes.length).to eq(2)
|
184
|
+
end
|
185
|
+
|
186
|
+
it "finds first node by xpath" do
|
187
|
+
node = described_class.at_xpath(doc, "//xmlns:child")
|
188
|
+
expect(described_class.get_attribute_value(node, "id")).to eq("1")
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# spec/support/xml_matchers.rb
|
4
|
+
# RSpec::Matchers.define :be_equivalent_to do |expected|
|
5
|
+
# match do |actual|
|
6
|
+
# normalize_xml(actual) == normalize_xml(expected)
|
7
|
+
# end
|
8
|
+
|
9
|
+
# failure_message do |actual|
|
10
|
+
# "expected XML to be equivalent to:\n#{normalize_xml(expected)}\n\nbut was:\n#{normalize_xml(actual)}"
|
11
|
+
# end
|
12
|
+
|
13
|
+
# def normalize_xml(xml)
|
14
|
+
# xml.to_s.gsub(/>\s+</, '><').strip
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
|
18
|
+
RSpec::Matchers.define :have_xpath do |xpath, text|
|
19
|
+
match do |xml_node|
|
20
|
+
nodes = xml_node.xpath(xpath)
|
21
|
+
text.nil? ? !nodes.empty? : nodes.any? { |node| node.text == text }
|
22
|
+
end
|
23
|
+
|
24
|
+
failure_message do |_xml_node|
|
25
|
+
"expected to find xpath #{xpath} #{text ? "with text '#{text}'" : ""}"
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moxml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 'Moxml is a unified XML manipulation library that provides a common API.
|
14
14
|
|
@@ -19,10 +19,13 @@ executables: []
|
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
-
- ".github/workflows/
|
22
|
+
- ".github/workflows/rake.yml"
|
23
|
+
- ".github/workflows/release.yml"
|
23
24
|
- ".gitignore"
|
24
25
|
- ".rspec"
|
25
26
|
- ".rubocop.yml"
|
27
|
+
- ".rubocop_todo.yml"
|
28
|
+
- ".ruby-version"
|
26
29
|
- Gemfile
|
27
30
|
- README.adoc
|
28
31
|
- Rakefile
|
@@ -30,23 +33,69 @@ files:
|
|
30
33
|
- bin/setup
|
31
34
|
- lib/moxml.rb
|
32
35
|
- lib/moxml/adapter.rb
|
36
|
+
- lib/moxml/adapter/base.rb
|
37
|
+
- lib/moxml/adapter/customized_oga/xml_declaration.rb
|
38
|
+
- lib/moxml/adapter/customized_oga/xml_generator.rb
|
39
|
+
- lib/moxml/adapter/nokogiri.rb
|
40
|
+
- lib/moxml/adapter/oga.rb
|
41
|
+
- lib/moxml/adapter/ox.rb
|
33
42
|
- lib/moxml/attribute.rb
|
43
|
+
- lib/moxml/builder.rb
|
34
44
|
- lib/moxml/cdata.rb
|
35
45
|
- lib/moxml/comment.rb
|
36
46
|
- lib/moxml/config.rb
|
47
|
+
- lib/moxml/context.rb
|
37
48
|
- lib/moxml/declaration.rb
|
49
|
+
- lib/moxml/doctype.rb
|
38
50
|
- lib/moxml/document.rb
|
51
|
+
- lib/moxml/document_builder.rb
|
39
52
|
- lib/moxml/element.rb
|
40
|
-
- lib/moxml/
|
41
|
-
- lib/moxml/errors.rb
|
53
|
+
- lib/moxml/error.rb
|
42
54
|
- lib/moxml/namespace.rb
|
43
55
|
- lib/moxml/node.rb
|
44
56
|
- lib/moxml/node_set.rb
|
45
57
|
- lib/moxml/processing_instruction.rb
|
46
58
|
- lib/moxml/text.rb
|
47
59
|
- lib/moxml/version.rb
|
60
|
+
- lib/moxml/xml_utils.rb
|
61
|
+
- lib/moxml/xml_utils/encoder.rb
|
48
62
|
- moxml.gemspec
|
49
63
|
- sig/moxml.rbs
|
64
|
+
- spec/moxml/adapter/nokogiri_spec.rb
|
65
|
+
- spec/moxml/adapter/oga_spec.rb
|
66
|
+
- spec/moxml/adapter/ox_spec.rb
|
67
|
+
- spec/moxml/all_with_adapters_spec.rb
|
68
|
+
- spec/moxml/config_spec.rb
|
69
|
+
- spec/moxml/error_spec.rb
|
70
|
+
- spec/moxml/examples/adapter_spec.rb
|
71
|
+
- spec/moxml_spec.rb
|
72
|
+
- spec/spec_helper.rb
|
73
|
+
- spec/support/shared_examples/attribute.rb
|
74
|
+
- spec/support/shared_examples/builder.rb
|
75
|
+
- spec/support/shared_examples/cdata.rb
|
76
|
+
- spec/support/shared_examples/comment.rb
|
77
|
+
- spec/support/shared_examples/context.rb
|
78
|
+
- spec/support/shared_examples/declaration.rb
|
79
|
+
- spec/support/shared_examples/doctype.rb
|
80
|
+
- spec/support/shared_examples/document.rb
|
81
|
+
- spec/support/shared_examples/document_builder.rb
|
82
|
+
- spec/support/shared_examples/edge_cases.rb
|
83
|
+
- spec/support/shared_examples/element.rb
|
84
|
+
- spec/support/shared_examples/examples/attribute.rb
|
85
|
+
- spec/support/shared_examples/examples/basic_usage.rb
|
86
|
+
- spec/support/shared_examples/examples/memory.rb
|
87
|
+
- spec/support/shared_examples/examples/namespace.rb
|
88
|
+
- spec/support/shared_examples/examples/readme_examples.rb
|
89
|
+
- spec/support/shared_examples/examples/thread_safety.rb
|
90
|
+
- spec/support/shared_examples/examples/xpath.rb
|
91
|
+
- spec/support/shared_examples/integration.rb
|
92
|
+
- spec/support/shared_examples/namespace.rb
|
93
|
+
- spec/support/shared_examples/node.rb
|
94
|
+
- spec/support/shared_examples/node_set.rb
|
95
|
+
- spec/support/shared_examples/processing_instruction.rb
|
96
|
+
- spec/support/shared_examples/text.rb
|
97
|
+
- spec/support/shared_examples/xml_adapter.rb
|
98
|
+
- spec/support/xml_matchers.rb
|
50
99
|
homepage: https://github.com/lutaml/moxml
|
51
100
|
licenses:
|
52
101
|
- BSD-2-Clause
|
@@ -67,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
116
|
- !ruby/object:Gem::Version
|
68
117
|
version: '0'
|
69
118
|
requirements: []
|
70
|
-
rubygems_version: 3.
|
119
|
+
rubygems_version: 3.3.27
|
71
120
|
signing_key:
|
72
121
|
specification_version: 4
|
73
122
|
summary: Unified XML manipulation library
|
data/.github/workflows/main.yml
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
name: Ruby
|
2
|
-
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
branches:
|
6
|
-
- main
|
7
|
-
|
8
|
-
pull_request:
|
9
|
-
|
10
|
-
jobs:
|
11
|
-
build:
|
12
|
-
runs-on: ubuntu-latest
|
13
|
-
name: Ruby ${{ matrix.ruby }}
|
14
|
-
strategy:
|
15
|
-
matrix:
|
16
|
-
ruby:
|
17
|
-
- '3.3.2'
|
18
|
-
|
19
|
-
steps:
|
20
|
-
- uses: actions/checkout@v4
|
21
|
-
- name: Set up Ruby
|
22
|
-
uses: ruby/setup-ruby@v1
|
23
|
-
with:
|
24
|
-
ruby-version: ${{ matrix.ruby }}
|
25
|
-
bundler-cache: true
|
26
|
-
- name: Run the default task
|
27
|
-
run: bundle exec rake
|
data/lib/moxml/error_handler.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
# lib/moxml/error_handler.rb
|
2
|
-
module Moxml
|
3
|
-
class ErrorHandler
|
4
|
-
class << self
|
5
|
-
def handle_parse_error(error, backend)
|
6
|
-
case backend
|
7
|
-
when :nokogiri
|
8
|
-
handle_nokogiri_error(error)
|
9
|
-
when :ox
|
10
|
-
handle_ox_error(error)
|
11
|
-
when :oga
|
12
|
-
handle_oga_error(error)
|
13
|
-
else
|
14
|
-
handle_generic_error(error)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def handle_nokogiri_error(error)
|
21
|
-
case error
|
22
|
-
when ::Nokogiri::XML::SyntaxError
|
23
|
-
raise ParseError.new(
|
24
|
-
error.message,
|
25
|
-
line: error.line,
|
26
|
-
column: error.column,
|
27
|
-
source: error.source,
|
28
|
-
)
|
29
|
-
when ::Nokogiri::XML::XPath::SyntaxError
|
30
|
-
raise XPathError.new(error.message)
|
31
|
-
else
|
32
|
-
handle_generic_error(error)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def handle_ox_error(error)
|
37
|
-
case error
|
38
|
-
when ::Ox::ParseError
|
39
|
-
raise ParseError.new(
|
40
|
-
error.message,
|
41
|
-
line: error.line,
|
42
|
-
column: error.column,
|
43
|
-
)
|
44
|
-
else
|
45
|
-
handle_generic_error(error)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def handle_oga_error(error)
|
50
|
-
case error
|
51
|
-
when ::Oga::XML::ParseError
|
52
|
-
raise ParseError.new(
|
53
|
-
error.message,
|
54
|
-
line: error.line,
|
55
|
-
column: error.column,
|
56
|
-
)
|
57
|
-
when ::Oga::XML::XPath::Error
|
58
|
-
raise XPathError.new(error.message)
|
59
|
-
else
|
60
|
-
handle_generic_error(error)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def handle_generic_error(error)
|
65
|
-
case error
|
66
|
-
when NameError, NoMethodError
|
67
|
-
raise BackendError.new(
|
68
|
-
"Backend operation failed: #{error.message}",
|
69
|
-
Moxml.config.backend
|
70
|
-
)
|
71
|
-
else
|
72
|
-
raise Error, "XML operation failed: #{error.message}"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
data/lib/moxml/errors.rb
DELETED
@@ -1,169 +0,0 @@
|
|
1
|
-
# lib/moxml/errors.rb
|
2
|
-
module Moxml
|
3
|
-
# Base error class for all Moxml errors
|
4
|
-
class Error < StandardError; end
|
5
|
-
|
6
|
-
# Parsing related errors
|
7
|
-
class ParseError < Error
|
8
|
-
attr_reader :line, :column, :source
|
9
|
-
|
10
|
-
def initialize(message, line: nil, column: nil, source: nil)
|
11
|
-
@line = line
|
12
|
-
@column = column
|
13
|
-
@source = source
|
14
|
-
super(build_message(message))
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def build_message(message)
|
20
|
-
parts = [message]
|
21
|
-
parts << "Line: #{line}" if line
|
22
|
-
parts << "Column: #{column}" if column
|
23
|
-
parts << "\nSource: #{source}" if source
|
24
|
-
parts.join(" | ")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Validation errors
|
29
|
-
class ValidationError < Error; end
|
30
|
-
class DTDValidationError < ValidationError; end
|
31
|
-
class SchemaValidationError < ValidationError; end
|
32
|
-
class NamespaceError < ValidationError; end
|
33
|
-
|
34
|
-
# Structure errors
|
35
|
-
class MalformedXMLError < ParseError; end
|
36
|
-
class UnbalancedTagError < ParseError; end
|
37
|
-
class UndefinedEntityError < ParseError; end
|
38
|
-
class DuplicateAttributeError < ParseError; end
|
39
|
-
|
40
|
-
# Encoding errors
|
41
|
-
class EncodingError < Error
|
42
|
-
attr_reader :encoding
|
43
|
-
|
44
|
-
def initialize(message, encoding)
|
45
|
-
@encoding = encoding
|
46
|
-
super("#{message} (Encoding: #{encoding})")
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Security related errors
|
51
|
-
class SecurityError < Error; end
|
52
|
-
class MaxDepthExceededError < SecurityError; end
|
53
|
-
class MaxAttributesExceededError < SecurityError; end
|
54
|
-
class MaxNameLengthExceededError < SecurityError; end
|
55
|
-
class EntityExpansionError < SecurityError; end
|
56
|
-
|
57
|
-
# Backend errors
|
58
|
-
class BackendError < Error
|
59
|
-
attr_reader :backend
|
60
|
-
|
61
|
-
def initialize(message, backend)
|
62
|
-
@backend = backend
|
63
|
-
super("#{message} (Backend: #{backend})")
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
class BackendNotFoundError < BackendError; end
|
68
|
-
class BackendConfigurationError < BackendError; end
|
69
|
-
|
70
|
-
# Node manipulation errors
|
71
|
-
class NodeError < Error
|
72
|
-
attr_reader :node
|
73
|
-
|
74
|
-
def initialize(message, node)
|
75
|
-
@node = node
|
76
|
-
super("#{message} (Node: #{node.class})")
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
class InvalidNodeTypeError < NodeError; end
|
81
|
-
class InvalidOperationError < NodeError; end
|
82
|
-
class NodeNotFoundError < NodeError; end
|
83
|
-
|
84
|
-
# Visitor pattern errors
|
85
|
-
class VisitorError < Error; end
|
86
|
-
|
87
|
-
class InvalidSelectorError < VisitorError
|
88
|
-
attr_reader :selector
|
89
|
-
|
90
|
-
def initialize(message, selector)
|
91
|
-
@selector = selector
|
92
|
-
super("#{message} (Selector: #{selector})")
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
class VisitorMethodError < VisitorError
|
97
|
-
attr_reader :method_name
|
98
|
-
|
99
|
-
def initialize(message, method_name)
|
100
|
-
@method_name = method_name
|
101
|
-
super("#{message} (Method: #{method_name})")
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# Serialization errors
|
106
|
-
class SerializationError < Error; end
|
107
|
-
|
108
|
-
class InvalidOptionsError < SerializationError
|
109
|
-
attr_reader :options
|
110
|
-
|
111
|
-
def initialize(message, options)
|
112
|
-
@options = options
|
113
|
-
super("#{message} (Options: #{options})")
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# IO errors
|
118
|
-
class IOError < Error
|
119
|
-
attr_reader :path
|
120
|
-
|
121
|
-
def initialize(message, path)
|
122
|
-
@path = path
|
123
|
-
super("#{message} (Path: #{path})")
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
class FileNotFoundError < IOError; end
|
128
|
-
class WriteError < IOError; end
|
129
|
-
|
130
|
-
# Memory errors
|
131
|
-
class MemoryError < Error
|
132
|
-
attr_reader :size
|
133
|
-
|
134
|
-
def initialize(message, size)
|
135
|
-
@size = size
|
136
|
-
super("#{message} (Size: #{size} bytes)")
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
class DocumentTooLargeError < MemoryError; end
|
141
|
-
|
142
|
-
# CDATA related errors
|
143
|
-
class CDATAError < Error; end
|
144
|
-
class NestedCDATAError < CDATAError; end
|
145
|
-
class InvalidCDATAContentError < CDATAError; end
|
146
|
-
|
147
|
-
# Namespace related errors
|
148
|
-
class NamespaceDeclarationError < Error
|
149
|
-
attr_reader :prefix, :uri
|
150
|
-
|
151
|
-
def initialize(message, prefix, uri)
|
152
|
-
@prefix = prefix
|
153
|
-
@uri = uri
|
154
|
-
super("#{message} (Prefix: #{prefix}, URI: #{uri})")
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
# XPath related errors
|
159
|
-
class XPathError < Error
|
160
|
-
attr_reader :expression
|
161
|
-
|
162
|
-
def initialize(message, expression)
|
163
|
-
@expression = expression
|
164
|
-
super("#{message} (Expression: #{expression})")
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
class InvalidXPathError < XPathError; end
|
169
|
-
end
|