moxml 0.1.1 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fd59e7a59b29416c792cd5d84cedceaede12d661e96c1da3b78af9711bcdb95
4
- data.tar.gz: bb90166adcfa1e8c5440b6f991c842358df348e62a3a04e11a228ff7c96590c9
3
+ metadata.gz: 7aeebdab58434af19ecef2aef1d8be83f44aa4cafef5386cc01f90df9c0d74b0
4
+ data.tar.gz: 365ea23544a86eb5fbe13d6c87a903c844db321ba7884521ba76c4f169558bd2
5
5
  SHA512:
6
- metadata.gz: 9e23367b7e18bc71b64527f1e8e7481279132366d169551b665e11d474c473e779bb6424158f64a6171f0e6122d12268cd573c2d12abaa20a80666f538224d1b
7
- data.tar.gz: 3760403535f405b1153aeb02a7b9ff0c1896b961eed403a017ab32522202b7aa9fe1adb1d455c59ae903e5903ab6d2ddea57ec64cb4570e538420efc63d9014a
6
+ metadata.gz: 924f7a2e7e6a68d9e78f4f65244bd5f8cdaefa58c00dc7a3a926d2cb41d1d6ac39cc98c46cdd83f13dbdec450ad5b8abbe400c6b89a595aadf2e1c21f074ab01
7
+ data.tar.gz: f125a15ea901391a648a3545b5afa79d9e3794c4e5f4009c6cca623501ad53071f27fbc3046da7fe0a964a240c8d9ae7f75410283f59daa0b6a34ac561540c68
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2025-01-13 02:38:07 UTC using RuboCop version 1.70.0.
3
+ # on 2025-02-07 04:56:30 UTC using RuboCop version 1.71.2.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -28,7 +28,7 @@ Lint/MissingSuper:
28
28
  Metrics/AbcSize:
29
29
  Max: 30
30
30
 
31
- # Offense count: 46
31
+ # Offense count: 49
32
32
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
33
33
  # AllowedMethods: refine
34
34
  Metrics/BlockLength:
@@ -63,3 +63,11 @@ Naming/MethodParameterName:
63
63
  # Configuration parameters: AllowedConstants.
64
64
  Style/Documentation:
65
65
  Enabled: false
66
+
67
+ # Offense count: 20
68
+ # This cop supports safe autocorrection (--autocorrect).
69
+ # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
70
+ # SupportedStyles: single_quotes, double_quotes
71
+ Style/StringLiterals:
72
+ Exclude:
73
+ - 'spec/support/shared_examples/examples/readme_examples.rb'
data/README.adoc CHANGED
@@ -32,7 +32,7 @@ Install the gem and at least one supported XML library:
32
32
  ----
33
33
  # In your Gemfile
34
34
  gem 'moxml'
35
- gem 'nokogiri' # Or 'ox' or 'oga'
35
+ gem 'nokogiri' # Or 'oga', or 'ox' when it is integrated
36
36
  ----
37
37
 
38
38
  === Basic document creation
@@ -45,7 +45,7 @@ require 'moxml'
45
45
  doc = Moxml.new.create_document
46
46
 
47
47
  # Add XML declaration
48
- doc.add_declaration(version: "1.0", encoding: "UTF-8")
48
+ doc.add_child(doc.create_declaration("1.0", "UTF-8"))
49
49
 
50
50
  # Create root element with namespace
51
51
  root = doc.create_element('book')
@@ -69,7 +69,7 @@ The builder pattern provides a clean DSL for creating XML documents:
69
69
 
70
70
  [source,ruby]
71
71
  ----
72
- doc = Moxml.new.build do
72
+ doc = Moxml::Builder.new(Moxml.new).build do
73
73
  declaration version: "1.0", encoding: "UTF-8"
74
74
 
75
75
  element 'library', xmlns: 'http://example.org/library' do
@@ -98,11 +98,12 @@ end
98
98
  doc = Moxml.new.create_document
99
99
 
100
100
  # Add declaration
101
- doc.add_declaration(version: "1.0", encoding: "UTF-8")
101
+ doc.add_child(doc.create_declaration("1.0", "UTF-8"))
102
102
 
103
103
  # Create root with namespace
104
104
  root = doc.create_element('library')
105
105
  root.add_namespace(nil, 'http://example.org/library')
106
+ root.add_namespace("dc", "http://purl.org/dc/elements/1.1/")
106
107
  doc.add_child(root)
107
108
 
108
109
  # Add elements with attributes
@@ -131,23 +132,23 @@ doc = Moxml.new.create_document
131
132
  doc = Moxml.new.parse(xml_string)
132
133
 
133
134
  # Document properties and methods
134
- doc.encoding # Get document encoding
135
- doc.encoding = "UTF-8" # Set document encoding
135
+ doc.encoding # Get document encoding
136
+ doc.encoding = "UTF-8" # Set document encoding
136
137
  doc.version # Get XML version
137
138
  doc.version = "1.1" # Set XML version
138
139
  doc.standalone # Get standalone declaration
139
140
  doc.standalone = "yes" # Set standalone declaration
140
141
 
141
142
  # Document structure
142
- doc.root # Get root element
143
+ doc.root # Get root element
143
144
  doc.children # Get all top-level nodes
144
145
  doc.add_child(node) # Add a child node
145
146
  doc.remove_child(node) # Remove a child node
146
147
 
147
148
  # Node creation methods
148
- doc.create_element(name) # Create new element
149
- doc.create_text(content) # Create text node
150
- doc.create_cdata(content) # Create CDATA section
149
+ doc.create_element(name) # Create new element
150
+ doc.create_text(content) # Create text node
151
+ doc.create_cdata(content) # Create CDATA section
151
152
  doc.create_comment(content) # Create comment
152
153
  doc.create_processing_instruction(target, content) # Create PI
153
154
 
@@ -171,8 +172,9 @@ element.name # Get element name
171
172
  element.name = "new_name" # Set element name
172
173
  element.text # Get text content
173
174
  element.text = "content" # Set text content
174
- element.inner_html # Get inner XML content
175
- element.inner_html = xml # Set inner XML content
175
+ element.inner_text # Get text content for current node only
176
+ element.inner_xml # Get inner XML content
177
+ element.inner_xml = xml # Set inner XML content
176
178
 
177
179
  # Attributes
178
180
  element[name] # Get attribute value
@@ -443,6 +445,9 @@ rescue Moxml::ValidationError => e
443
445
  rescue Moxml::XPathError => e
444
446
  # Handles XPath expression errors
445
447
  puts "XPath error: #{e.message}"
448
+ rescue Moxml::NamespaceError => e
449
+ # Handles namespace errors
450
+ puts "Namespace error: #{e.message}"
446
451
  rescue Moxml::Error => e
447
452
  # Handles other Moxml-specific errors
448
453
  puts "Error: #{e.message}"
@@ -451,7 +456,9 @@ end
451
456
 
452
457
  == Configuration
453
458
 
454
- Moxml can be configured globally or per instance:
459
+ === General
460
+
461
+ Moxml can be configured globally or per instance.
455
462
 
456
463
  [source,ruby]
457
464
  ----
@@ -464,11 +471,31 @@ end
464
471
 
465
472
  # Instance configuration
466
473
  moxml = Moxml.new do |config|
467
- config.adapter = :ox
474
+ config.adapter = :oga
468
475
  config.strict = false
469
476
  end
470
477
  ----
471
478
 
479
+ === Default adapter selection
480
+
481
+ To use an adapter other than `:nokogiri` as the global default, set it before
482
+ processing any input using the following option.
483
+
484
+ [source,ruby]
485
+ ----
486
+ Moxml::Config.default_adapter = <adapter-symbol>
487
+ ----
488
+
489
+ Moxml supports the following adapters:
490
+
491
+ `:nokogiri`:: (default) https://github.com/sparklemotion/nokogiri[Nokogiri], a
492
+ wrapper around the https://github.com/GNOME/libxml2[libxml2] C library
493
+
494
+ `:oga`:: https://github.com/yorickpeterse/oga[Oga], a pure Ruby XML parser
495
+
496
+ `:ox`:: https://github.com/ohler55/ox[Ox], a fast XML parser (not yet supported)
497
+
498
+
472
499
  == Thread safety
473
500
 
474
501
  Moxml is thread-safe when used properly. Each instance maintains its own state
@@ -562,11 +589,11 @@ end
562
589
 
563
590
  == Contributing
564
591
 
565
- 1. Fork the repository
566
- 2. Create your feature branch (`git checkout -b feature/my-new-feature`)
567
- 3. Commit your changes (`git commit -am 'Add some feature'`)
568
- 4. Push to the branch (`git push origin feature/my-new-feature`)
569
- 5. Create a new Pull Request
592
+ . Fork the repository
593
+ . Create your feature branch (`git checkout -b feature/my-new-feature`)
594
+ . Commit your changes (`git commit -am 'Add some feature'`)
595
+ . Push to the branch (`git push origin feature/my-new-feature`)
596
+ . Create a new Pull Request
570
597
 
571
598
  == License
572
599
 
@@ -224,6 +224,11 @@ module Moxml
224
224
  node.content
225
225
  end
226
226
 
227
+ def inner_text(node)
228
+ text_children = node.children - node.element_children
229
+ text_children.map(&:content).join
230
+ end
231
+
227
232
  def set_text_content(node, content)
228
233
  node.native_content = content
229
234
  end
@@ -237,6 +237,15 @@ module Moxml
237
237
  node.text
238
238
  end
239
239
 
240
+ def inner_text(node)
241
+ if node.respond_to?(:inner_text)
242
+ node.inner_text
243
+ else
244
+ # Oga::XML::Text node for example
245
+ node.text
246
+ end
247
+ end
248
+
240
249
  def set_text_content(node, content)
241
250
  if node.respond_to?(:inner_text)
242
251
  node.inner_text = content
data/lib/moxml/config.rb CHANGED
@@ -6,8 +6,14 @@ module Moxml
6
6
  DEFAULT_ADAPTER = VALID_ADAPTERS.first
7
7
 
8
8
  class << self
9
+ attr_writer :default_adapter
10
+
9
11
  def default
10
- @default ||= new(DEFAULT_ADAPTER, true, "UTF-8")
12
+ @default ||= new(default_adapter, true, "UTF-8")
13
+ end
14
+
15
+ def default_adapter
16
+ @default_adapter ||= DEFAULT_ADAPTER
11
17
  end
12
18
  end
13
19
 
@@ -38,7 +44,10 @@ module Moxml
38
44
  adapter
39
45
  end
40
46
 
41
- alias default_adapter= adapter=
47
+ def default_adapter=(name)
48
+ self.adapter = name
49
+ self.class.default_adapter = name
50
+ end
42
51
 
43
52
  def adapter
44
53
  @adapter ||= Adapter.load(@adapter_name)
data/lib/moxml/element.rb CHANGED
@@ -79,11 +79,15 @@ module Moxml
79
79
  adapter.set_text_content(@native, normalize_xml_value(content))
80
80
  end
81
81
 
82
- def inner_html
83
- adapter.inner_html(@native)
82
+ def inner_text
83
+ adapter.inner_text(@native)
84
84
  end
85
85
 
86
- def inner_html=(html)
86
+ def inner_xml
87
+ adapter.inner_xml(@native)
88
+ end
89
+
90
+ def inner_xml=(html)
87
91
  doc = context.parse("<root>#{html}</root>")
88
92
  adapter.replace_children(@native, doc.root.children.map(&:native))
89
93
  end
data/lib/moxml/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Moxml
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.3"
5
5
  end
data/spec/moxml_spec.rb CHANGED
@@ -36,7 +36,7 @@ RSpec.describe Moxml do
36
36
 
37
37
  it "uses configured options from the block" do
38
38
  Moxml.configure do |config|
39
- config.adapter = :oga
39
+ config.default_adapter = :oga
40
40
  config.strict_parsing = false
41
41
  config.default_encoding = "US-ASCII"
42
42
  end
@@ -79,8 +79,8 @@ RSpec.shared_examples "Moxml::Element" do
79
79
  expect(element.text).to eq("firstsecond")
80
80
  end
81
81
 
82
- it "sets inner HTML" do
83
- element.inner_html = "<child>text</child>"
82
+ it "sets inner XML" do
83
+ element.inner_xml = "<child>text</child>"
84
84
  expect(element.children.size).to eq(1)
85
85
  expect(element.children.first.name).to eq("child")
86
86
  expect(element.children.first.text).to eq("text")
@@ -106,5 +106,25 @@ RSpec.shared_examples "Moxml::Element" do
106
106
  expect(element.to_xml).to include("text<child></child>more")
107
107
  end
108
108
  end
109
+
110
+ describe "complex element structures" do
111
+ it "creates nested paragraphs without namespaces" do
112
+ outer_p = doc.create_element("p")
113
+ inner_p = doc.create_element("p")
114
+ inner_p.add_child("Some text inside paragraph")
115
+ outer_p.add_child(inner_p)
116
+
117
+ expect(outer_p.to_xml).to include("<p>Some text inside paragraph</p>")
118
+ end
119
+
120
+ it "does not return text of child elements in root text" do
121
+ outer_p = doc.create_element("p")
122
+ inner_p = doc.create_element("p")
123
+ inner_p.add_child("Some text inside paragraph")
124
+ outer_p.add_child(inner_p)
125
+ expect(outer_p.inner_text).to eq("")
126
+ expect(inner_p.text).to include("Some text inside paragraph")
127
+ end
128
+ end
109
129
  end
110
130
  end
@@ -1,20 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.shared_examples "README Examples" do
4
- describe "Quick Start example" do
4
+ describe "Basic document creation" do
5
5
  it "builds document as shown in README" do
6
- context = Moxml.new
7
- doc = context.create_document
6
+ doc = Moxml.new.create_document
7
+
8
+ # Add XML declaration
9
+ doc.add_child(doc.create_declaration("1.0", "UTF-8"))
8
10
 
11
+ # Create root element with namespace
9
12
  root = doc.create_element("book")
13
+ root.add_namespace("dc", "http://purl.org/dc/elements/1.1/")
10
14
  doc.add_child(root)
11
15
 
12
- root.add_namespace("dc", "http://purl.org/dc/elements/1.1/")
16
+ # Add content
13
17
  title = doc.create_element("dc:title")
14
- title.add_child(doc.create_text("XML Processing with Ruby"))
18
+ title.text = "XML Processing with Ruby"
15
19
  root.add_child(title)
16
20
 
17
21
  expect(doc.to_xml).to include(
22
+ '<?xml version="1.0" encoding="UTF-8"?>',
18
23
  '<book xmlns:dc="http://purl.org/dc/elements/1.1/">',
19
24
  "<dc:title>XML Processing with Ruby</dc:title>",
20
25
  "</book>"
@@ -22,7 +27,42 @@ RSpec.shared_examples "README Examples" do
22
27
  end
23
28
  end
24
29
 
25
- describe "Complex document example" do
30
+ describe "Using the builder pattern" do
31
+ it "builds a correct document" do
32
+ doc = Moxml::Builder.new(Moxml.new).build do
33
+ declaration version: "1.0", encoding: "UTF-8"
34
+
35
+ element "library", xmlns: "http://example.org/library" do
36
+ element "book" do
37
+ element "title" do
38
+ text "Ruby Programming"
39
+ end
40
+
41
+ element "author" do
42
+ text "Jane Smith"
43
+ end
44
+
45
+ comment "Publication details"
46
+ element "published", year: "2024"
47
+
48
+ cdata "<custom>metadata</custom>"
49
+ end
50
+ end
51
+ end
52
+
53
+ expect(doc.to_xml).to include(
54
+ '<?xml version="1.0" encoding="UTF-8"?>',
55
+ '<library xmlns="http://example.org/library">',
56
+ "<title>Ruby Programming</title>",
57
+ "<!--Publication details-->",
58
+ '<published year="2024"></published>',
59
+ "<![CDATA[<custom>metadata</custom>]]>",
60
+ "</book>"
61
+ )
62
+ end
63
+ end
64
+
65
+ describe "Direct document manipulation" do
26
66
  it "builds document with all features" do
27
67
  doc = Moxml.new.create_document
28
68
 
@@ -38,10 +78,12 @@ RSpec.shared_examples "README Examples" do
38
78
  # Add books
39
79
  %w[Ruby XML].each do |title|
40
80
  book = doc.create_element("book")
81
+ book["id"] = "b1-#{title}"
41
82
 
42
- # Add metadata
83
+ # Add mixed content
84
+ book.add_child(doc.create_comment("Book details"))
43
85
  dc_title = doc.create_element("dc:title")
44
- dc_title.add_child(doc.create_text(title))
86
+ dc_title.text = title
45
87
  book.add_child(dc_title)
46
88
 
47
89
  # Add description
@@ -52,13 +94,16 @@ RSpec.shared_examples "README Examples" do
52
94
  root.add_child(book)
53
95
  end
54
96
 
55
- xml = doc.to_xml
56
- expect(xml).to include('<?xml version="1.0" encoding="UTF-8"?>')
57
- expect(xml).to include('<library xmlns="http://example.org/library" xmlns:dc="http://purl.org/dc/elements/1.1/">')
58
- expect(xml).to include("<dc:title>Ruby</dc:title>")
59
- expect(xml).to include("<![CDATA[About Ruby...]]>")
60
- expect(xml).to include("<dc:title>XML</dc:title>")
61
- expect(xml).to include("<![CDATA[About XML...]]>")
97
+ expect(doc.to_xml).to include(
98
+ '<?xml version="1.0" encoding="UTF-8"?>',
99
+ '<library xmlns="http://example.org/library" xmlns:dc="http://purl.org/dc/elements/1.1/">',
100
+ '<book id="b1-Ruby">',
101
+ "<!--Book details-->",
102
+ "<dc:title>Ruby</dc:title>",
103
+ "<![CDATA[About Ruby...]]>",
104
+ "<dc:title>XML</dc:title>",
105
+ "<![CDATA[About XML...]]>"
106
+ )
62
107
  end
63
108
  end
64
109
 
@@ -70,6 +115,18 @@ RSpec.shared_examples "README Examples" do
70
115
  context.parse("<invalid>")
71
116
  end.to raise_error(Moxml::ParseError)
72
117
 
118
+ expect do
119
+ doc = context.parse("<root/>")
120
+ root = doc.root
121
+ root.add_namespace("n", "wrong.url")
122
+ end.to raise_error(Moxml::NamespaceError)
123
+
124
+ expect do
125
+ doc = context.parse("<root/>")
126
+ element = doc.create_element("wrong,name")
127
+ doc.add_child(element)
128
+ end.to raise_error(Moxml::ValidationError)
129
+
73
130
  doc = context.parse("<root/>")
74
131
  expect do
75
132
  doc.xpath("///")
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.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-01-13 00:00:00.000000000 Z
11
+ date: 2025-02-26 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