moxml 0.1.0 → 0.1.1

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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +15 -0
  3. data/.github/workflows/release.yml +23 -0
  4. data/.gitignore +3 -0
  5. data/.rubocop.yml +2 -0
  6. data/.rubocop_todo.yml +65 -0
  7. data/.ruby-version +1 -0
  8. data/Gemfile +10 -3
  9. data/README.adoc +400 -594
  10. data/lib/moxml/adapter/base.rb +102 -0
  11. data/lib/moxml/adapter/customized_oga/xml_declaration.rb +18 -0
  12. data/lib/moxml/adapter/customized_oga/xml_generator.rb +104 -0
  13. data/lib/moxml/adapter/nokogiri.rb +314 -0
  14. data/lib/moxml/adapter/oga.rb +309 -0
  15. data/lib/moxml/adapter/ox.rb +325 -0
  16. data/lib/moxml/adapter.rb +26 -170
  17. data/lib/moxml/attribute.rb +47 -14
  18. data/lib/moxml/builder.rb +64 -0
  19. data/lib/moxml/cdata.rb +4 -26
  20. data/lib/moxml/comment.rb +6 -22
  21. data/lib/moxml/config.rb +39 -15
  22. data/lib/moxml/context.rb +29 -0
  23. data/lib/moxml/declaration.rb +16 -26
  24. data/lib/moxml/doctype.rb +9 -0
  25. data/lib/moxml/document.rb +51 -63
  26. data/lib/moxml/document_builder.rb +87 -0
  27. data/lib/moxml/element.rb +61 -99
  28. data/lib/moxml/error.rb +20 -0
  29. data/lib/moxml/namespace.rb +12 -37
  30. data/lib/moxml/node.rb +78 -58
  31. data/lib/moxml/node_set.rb +19 -222
  32. data/lib/moxml/processing_instruction.rb +6 -25
  33. data/lib/moxml/text.rb +4 -26
  34. data/lib/moxml/version.rb +1 -1
  35. data/lib/moxml/xml_utils/encoder.rb +55 -0
  36. data/lib/moxml/xml_utils.rb +80 -0
  37. data/lib/moxml.rb +33 -33
  38. data/moxml.gemspec +1 -1
  39. data/spec/moxml/adapter/nokogiri_spec.rb +14 -0
  40. data/spec/moxml/adapter/oga_spec.rb +14 -0
  41. data/spec/moxml/adapter/ox_spec.rb +49 -0
  42. data/spec/moxml/all_with_adapters_spec.rb +46 -0
  43. data/spec/moxml/config_spec.rb +55 -0
  44. data/spec/moxml/error_spec.rb +71 -0
  45. data/spec/moxml/examples/adapter_spec.rb +27 -0
  46. data/spec/moxml_spec.rb +50 -0
  47. data/spec/spec_helper.rb +32 -0
  48. data/spec/support/shared_examples/attribute.rb +165 -0
  49. data/spec/support/shared_examples/builder.rb +25 -0
  50. data/spec/support/shared_examples/cdata.rb +70 -0
  51. data/spec/support/shared_examples/comment.rb +65 -0
  52. data/spec/support/shared_examples/context.rb +35 -0
  53. data/spec/support/shared_examples/declaration.rb +93 -0
  54. data/spec/support/shared_examples/doctype.rb +25 -0
  55. data/spec/support/shared_examples/document.rb +110 -0
  56. data/spec/support/shared_examples/document_builder.rb +43 -0
  57. data/spec/support/shared_examples/edge_cases.rb +185 -0
  58. data/spec/support/shared_examples/element.rb +110 -0
  59. data/spec/support/shared_examples/examples/attribute.rb +42 -0
  60. data/spec/support/shared_examples/examples/basic_usage.rb +67 -0
  61. data/spec/support/shared_examples/examples/memory.rb +54 -0
  62. data/spec/support/shared_examples/examples/namespace.rb +65 -0
  63. data/spec/support/shared_examples/examples/readme_examples.rb +100 -0
  64. data/spec/support/shared_examples/examples/thread_safety.rb +43 -0
  65. data/spec/support/shared_examples/examples/xpath.rb +39 -0
  66. data/spec/support/shared_examples/integration.rb +135 -0
  67. data/spec/support/shared_examples/namespace.rb +96 -0
  68. data/spec/support/shared_examples/node.rb +110 -0
  69. data/spec/support/shared_examples/node_set.rb +90 -0
  70. data/spec/support/shared_examples/processing_instruction.rb +88 -0
  71. data/spec/support/shared_examples/text.rb +66 -0
  72. data/spec/support/shared_examples/xml_adapter.rb +191 -0
  73. data/spec/support/xml_matchers.rb +27 -0
  74. metadata +55 -6
  75. data/.github/workflows/main.yml +0 -27
  76. data/lib/moxml/error_handler.rb +0 -77
  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(/&lt; &gt; &amp; (&quot;|") ('|&apos;)/)
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.0
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: 2024-10-30 00:00:00.000000000 Z
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/main.yml"
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/error_handler.rb
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.5.22
119
+ rubygems_version: 3.3.27
71
120
  signing_key:
72
121
  specification_version: 4
73
122
  summary: Unified XML manipulation library
@@ -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
@@ -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