rxerces 0.1.0 → 0.3.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.
@@ -0,0 +1,167 @@
1
+ require 'spec_helper'
2
+ require 'rxerces/nokogiri'
3
+
4
+ RSpec.describe "Nokogiri compatibility" do
5
+ let(:simple_xml) { '<root><child>Hello</child></root>' }
6
+
7
+ describe "Nokogiri module" do
8
+ it "exists" do
9
+ expect(defined?(Nokogiri)).to eq('constant')
10
+ end
11
+
12
+ describe ".XML" do
13
+ it "parses XML" do
14
+ doc = Nokogiri.XML(simple_xml)
15
+ expect(doc).to be_a(RXerces::XML::Document)
16
+ end
17
+ end
18
+
19
+ describe ".parse" do
20
+ it "is an alias for .XML" do
21
+ doc = Nokogiri.parse(simple_xml)
22
+ expect(doc).to be_a(RXerces::XML::Document)
23
+ end
24
+ end
25
+ end
26
+
27
+ describe "Nokogiri::XML" do
28
+ it "exists" do
29
+ expect(defined?(Nokogiri::XML)).to eq('constant')
30
+ end
31
+
32
+ describe ".parse" do
33
+ it "parses XML" do
34
+ doc = Nokogiri::XML.parse(simple_xml)
35
+ expect(doc).to be_a(RXerces::XML::Document)
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "Nokogiri::XML::Document" do
41
+ it "is an alias for RXerces::XML::Document" do
42
+ expect(Nokogiri::XML::Document).to eq(RXerces::XML::Document)
43
+ end
44
+ end
45
+
46
+ describe "Nokogiri::XML::Node" do
47
+ it "is an alias for RXerces::XML::Node" do
48
+ expect(Nokogiri::XML::Node).to eq(RXerces::XML::Node)
49
+ end
50
+ end
51
+
52
+ describe "Nokogiri::XML::Element" do
53
+ it "is an alias for RXerces::XML::Element" do
54
+ expect(Nokogiri::XML::Element).to eq(RXerces::XML::Element)
55
+ end
56
+ end
57
+
58
+ describe "Nokogiri::XML::NodeSet" do
59
+ it "is an alias for RXerces::XML::NodeSet" do
60
+ expect(Nokogiri::XML::NodeSet).to eq(RXerces::XML::NodeSet)
61
+ end
62
+ end
63
+
64
+ describe "Nokogiri::XML::Schema" do
65
+ it "is an alias for RXerces::XML::Schema" do
66
+ expect(Nokogiri::XML::Schema).to eq(RXerces::XML::Schema)
67
+ end
68
+ end
69
+
70
+ describe "API compatibility" do
71
+ let(:doc) { Nokogiri.XML(simple_xml) }
72
+
73
+ it "provides root method" do
74
+ expect(doc.root).to be_a(Nokogiri::XML::Element)
75
+ expect(doc.root.name).to eq('root')
76
+ end
77
+
78
+ it "provides to_s method" do
79
+ xml_string = doc.to_s
80
+ expect(xml_string).to be_a(String)
81
+ expect(xml_string).to include('<root>')
82
+ end
83
+
84
+ it "provides to_xml method" do
85
+ xml_string = doc.to_xml
86
+ expect(xml_string).to be_a(String)
87
+ expect(xml_string).to include('<root>')
88
+ end
89
+
90
+ it "provides node name method" do
91
+ expect(doc.root.name).to eq('root')
92
+ end
93
+
94
+ it "provides node text method" do
95
+ child = doc.root.children.find { |n| n.is_a?(Nokogiri::XML::Element) }
96
+ expect(child.text).to be_a(String)
97
+ end
98
+
99
+ it "provides node children method" do
100
+ children = doc.root.children
101
+ expect(children).to be_an(Array)
102
+ end
103
+ end
104
+
105
+ describe "Schema validation compatibility" do
106
+ let(:xsd) do
107
+ <<~XSD
108
+ <?xml version="1.0"?>
109
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
110
+ <xs:element name="person">
111
+ <xs:complexType>
112
+ <xs:sequence>
113
+ <xs:element name="name" type="xs:string"/>
114
+ <xs:element name="age" type="xs:integer"/>
115
+ </xs:sequence>
116
+ </xs:complexType>
117
+ </xs:element>
118
+ </xs:schema>
119
+ XSD
120
+ end
121
+
122
+ let(:valid_xml) do
123
+ <<~XML
124
+ <?xml version="1.0"?>
125
+ <person>
126
+ <name>John</name>
127
+ <age>30</age>
128
+ </person>
129
+ XML
130
+ end
131
+
132
+ let(:invalid_xml) do
133
+ <<~XML
134
+ <?xml version="1.0"?>
135
+ <person>
136
+ <name>Jane</name>
137
+ <age>invalid</age>
138
+ </person>
139
+ XML
140
+ end
141
+
142
+ it "provides Schema.from_string method" do
143
+ schema = Nokogiri::XML::Schema.from_string(xsd)
144
+ expect(schema).to be_a(Nokogiri::XML::Schema)
145
+ end
146
+
147
+ it "provides Schema.from_document method" do
148
+ doc = Nokogiri::XML.parse(xsd)
149
+ schema = Nokogiri::XML::Schema.from_document(doc)
150
+ expect(schema).to be_a(Nokogiri::XML::Schema)
151
+ end
152
+
153
+ it "validates a valid document" do
154
+ schema = Nokogiri::XML::Schema.from_string(xsd)
155
+ doc = Nokogiri::XML.parse(valid_xml)
156
+ errors = doc.validate(schema)
157
+ expect(errors).to be_empty
158
+ end
159
+
160
+ it "returns errors for an invalid document" do
161
+ schema = Nokogiri::XML::Schema.from_string(xsd)
162
+ doc = Nokogiri::XML.parse(invalid_xml)
163
+ errors = doc.validate(schema)
164
+ expect(errors).not_to be_empty
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rxerces'
4
+
5
+ RSpec.shared_examples RXerces do
6
+ example 'version number is set to the expected value' do
7
+ expect(RXerces::VERSION).to eq('0.3.0')
8
+ expect(RXerces::VERSION).to be_frozen
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RXerces do
4
+ it "has a version number" do
5
+ expect(RXerces::VERSION).not_to be nil
6
+ end
7
+
8
+ describe ".XML" do
9
+ it "parses XML string" do
10
+ xml = '<root><child>text</child></root>'
11
+ doc = RXerces.XML(xml)
12
+ expect(doc).to be_a(RXerces::XML::Document)
13
+ end
14
+ end
15
+
16
+ describe ".parse" do
17
+ it "is an alias for .XML" do
18
+ xml = '<root><child>text</child></root>'
19
+ doc = RXerces.parse(xml)
20
+ expect(doc).to be_a(RXerces::XML::Document)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RXerces::XML::Schema do
4
+ let(:simple_xsd) do
5
+ <<~XSD
6
+ <?xml version="1.0" encoding="UTF-8"?>
7
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
8
+ <xs:element name="root">
9
+ <xs:complexType>
10
+ <xs:sequence>
11
+ <xs:element name="name" type="xs:string"/>
12
+ <xs:element name="age" type="xs:integer"/>
13
+ </xs:sequence>
14
+ </xs:complexType>
15
+ </xs:element>
16
+ </xs:schema>
17
+ XSD
18
+ end
19
+
20
+ let(:valid_xml) do
21
+ <<~XML
22
+ <?xml version="1.0"?>
23
+ <root>
24
+ <name>John</name>
25
+ <age>30</age>
26
+ </root>
27
+ XML
28
+ end
29
+
30
+ let(:invalid_xml) do
31
+ <<~XML
32
+ <?xml version="1.0"?>
33
+ <root>
34
+ <name>John</name>
35
+ <age>not-a-number</age>
36
+ </root>
37
+ XML
38
+ end
39
+
40
+ describe '.from_string' do
41
+ it 'creates a schema from an XSD string' do
42
+ schema = described_class.from_string(simple_xsd)
43
+ expect(schema).to be_a(described_class)
44
+ end
45
+
46
+ # Note: Xerces-C parser is very tolerant of invalid XML
47
+ # So we just skip testing for invalid XML for now
48
+ end
49
+
50
+ describe '.from_document' do
51
+ it 'creates a schema from a Document' do
52
+ schema_doc = RXerces::XML::Document.parse(simple_xsd)
53
+ schema = described_class.from_document(schema_doc)
54
+ expect(schema).to be_a(described_class)
55
+ end
56
+ end
57
+
58
+ describe 'validation' do
59
+ let(:schema) { described_class.from_string(simple_xsd) }
60
+
61
+ it 'validates a valid document' do
62
+ doc = RXerces::XML::Document.parse(valid_xml)
63
+ errors = doc.validate(schema)
64
+ expect(errors).to be_a(Array)
65
+ expect(errors).to be_empty
66
+ end
67
+
68
+ it 'returns validation errors for an invalid document' do
69
+ doc = RXerces::XML::Document.parse(invalid_xml)
70
+ errors = doc.validate(schema)
71
+ expect(errors).to be_a(Array)
72
+ expect(errors).not_to be_empty
73
+ expect(errors.first).to include('not-a-number')
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,17 @@
1
+ require 'rspec'
2
+ require 'rxerces'
3
+ require 'rxerces_shared'
4
+
5
+ RSpec.configure do |config|
6
+ # Enable flags like --only-failures and --next-failure
7
+ config.example_status_persistence_file_path = ".rspec_status"
8
+
9
+ # Disable RSpec exposing methods globally on `Module` and `main`
10
+ config.disable_monkey_patching!
11
+
12
+ config.expect_with :rspec do |c|
13
+ c.syntax = :expect
14
+ end
15
+
16
+ config.include_context(RXerces)
17
+ end
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+ require 'rxerces/nokogiri'
3
+
4
+ RSpec.describe "XPath support" do
5
+ let(:xml) do
6
+ <<-XML
7
+ <library>
8
+ <book id="1" category="fiction">
9
+ <title>1984</title>
10
+ <author>George Orwell</author>
11
+ <year>1949</year>
12
+ <price>15.99</price>
13
+ </book>
14
+ <book id="2" category="fiction">
15
+ <title>Brave New World</title>
16
+ <author>Aldous Huxley</author>
17
+ <year>1932</year>
18
+ <price>14.99</price>
19
+ </book>
20
+ <book id="3" category="non-fiction">
21
+ <title>Sapiens</title>
22
+ <author>Yuval Noah Harari</author>
23
+ <year>2011</year>
24
+ <price>18.99</price>
25
+ </book>
26
+ </library>
27
+ XML
28
+ end
29
+
30
+ let(:doc) { RXerces::XML::Document.parse(xml) }
31
+
32
+ describe "Document XPath queries" do
33
+ it "finds all book elements" do
34
+ books = doc.xpath('//book')
35
+ expect(books).to be_a(RXerces::XML::NodeSet)
36
+ expect(books.length).to eq(3)
37
+ end
38
+
39
+ it "finds all title elements" do
40
+ titles = doc.xpath('//title')
41
+ expect(titles.length).to eq(3)
42
+ expect(titles[0].text.strip).to eq('1984')
43
+ expect(titles[1].text.strip).to eq('Brave New World')
44
+ expect(titles[2].text.strip).to eq('Sapiens')
45
+ end
46
+
47
+ it "finds elements by path" do
48
+ authors = doc.xpath('/library/book/author')
49
+ expect(authors.length).to eq(3)
50
+ end
51
+
52
+ it "finds descendant elements" do
53
+ years = doc.xpath('//year')
54
+ expect(years.length).to eq(3)
55
+ end
56
+
57
+ it "finds price elements" do
58
+ prices = doc.xpath('//price')
59
+ expect(prices.length).to eq(3)
60
+ end
61
+
62
+ it "returns empty nodeset for non-matching xpath" do
63
+ result = doc.xpath('//nonexistent')
64
+ expect(result).to be_a(RXerces::XML::NodeSet)
65
+ expect(result.length).to eq(0)
66
+ end
67
+
68
+ it "can find nested elements" do
69
+ library_books = doc.xpath('/library/book')
70
+ expect(library_books.length).to eq(3)
71
+ end
72
+ end
73
+
74
+ describe "Node XPath queries" do
75
+ let(:root) { doc.root }
76
+
77
+ it "finds children from root element" do
78
+ books = root.xpath('.//book')
79
+ expect(books.length).to eq(3)
80
+ end
81
+
82
+ it "finds specific child elements" do
83
+ first_book = root.children.find { |n| n.is_a?(RXerces::XML::Element) }
84
+ titles = first_book.xpath('.//title')
85
+ expect(titles.length).to eq(1)
86
+ expect(titles[0].text.strip).to eq('1984')
87
+ end
88
+
89
+ it "finds descendant elements from node" do
90
+ first_book = root.children.find { |n| n.is_a?(RXerces::XML::Element) }
91
+ author = first_book.xpath('.//author')
92
+ expect(author.length).to eq(1)
93
+ expect(author[0].text.strip).to eq('George Orwell')
94
+ end
95
+
96
+ it "can use relative paths" do
97
+ books = root.xpath('book')
98
+ expect(books.length).to eq(3)
99
+ end
100
+
101
+ it "finds all descendants" do
102
+ all_titles = root.xpath('.//title')
103
+ expect(all_titles.length).to eq(3)
104
+ end
105
+ end
106
+
107
+ describe "Error handling" do
108
+ it "raises error for invalid XPath" do
109
+ expect {
110
+ doc.xpath('//[invalid')
111
+ }.to raise_error(RuntimeError, /XPath error/)
112
+ end
113
+ end
114
+
115
+ describe "Nokogiri compatibility" do
116
+ it "works with Nokogiri syntax" do
117
+ nokogiri_doc = Nokogiri::XML(xml)
118
+ books = nokogiri_doc.xpath('//book')
119
+ expect(books).to be_a(Nokogiri::XML::NodeSet)
120
+ expect(books.length).to eq(3)
121
+ end
122
+
123
+ it "can chain xpath on results" do
124
+ books = doc.xpath('//book')
125
+ expect(books.length).to eq(3)
126
+
127
+ # Access first book's title
128
+ first_book = books[0]
129
+ titles = first_book.xpath('.//title')
130
+ expect(titles.length).to eq(1)
131
+ expect(titles[0].text.strip).to eq('1984')
132
+ end
133
+
134
+ it "can iterate over xpath results" do
135
+ authors = doc.xpath('//author')
136
+ author_names = []
137
+ authors.each do |author|
138
+ author_names << author.text.strip
139
+ end
140
+ expect(author_names).to include('George Orwell', 'Aldous Huxley', 'Yuval Noah Harari')
141
+ end
142
+ end
143
+
144
+ describe "XPath limitations" do
145
+ it "notes that Xerces-C uses XML Schema XPath subset" do
146
+ # Xerces-C implements the XML Schema XPath subset, not full XPath 1.0
147
+ # This means the following are NOT supported:
148
+ # - Attribute predicates like [@id="1"]
149
+ # - Functions like last(), position(), text()
150
+ # - Comparison operators in predicates
151
+ #
152
+ # However, basic path expressions work well:
153
+ # - // (descendant-or-self)
154
+ # - / (child)
155
+ # - . (self)
156
+ # - .. (parent)
157
+
158
+ # Basic paths work
159
+ expect(doc.xpath('//book').length).to eq(3)
160
+ expect(doc.xpath('/library/book').length).to eq(3)
161
+ expect(doc.xpath('//title').length).to eq(3)
162
+ end
163
+ end
164
+ end
data.tar.gz.sig ADDED
Binary file
metadata CHANGED
@@ -1,12 +1,39 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rxerces
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
- - RXerces Contributors
7
+ - Daniel J. Berger
8
8
  bindir: bin
9
- cert_chain: []
9
+ cert_chain:
10
+ - |
11
+ -----BEGIN CERTIFICATE-----
12
+ MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MREwDwYDVQQDDAhkamJl
13
+ cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
14
+ MB4XDTE4MDMxODE1MjIwN1oXDTI4MDMxNTE1MjIwN1owPzERMA8GA1UEAwwIZGpi
15
+ ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
16
+ bTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALgfaroVM6CI06cxr0/h
17
+ A+j+pc8fgpRgBVmHFaFunq28GPC3IvW7Nvc3Y8SnAW7pP1EQIbhlwRIaQzJ93/yj
18
+ u95KpkP7tA9erypnV7dpzBkzNlX14ACaFD/6pHoXoe2ltBxk3CCyyzx70mTqJpph
19
+ 75IB03ni9a8yqn8pmse+s83bFJOAqddSj009sGPcQO+QOWiNxqYv1n5EHcvj2ebO
20
+ 6hN7YTmhx7aSia4qL/quc4DlIaGMWoAhvML7u1fmo53CYxkKskfN8MOecq2vfEmL
21
+ iLu+SsVVEAufMDDFMXMJlvDsviolUSGMSNRTujkyCcJoXKYYxZSNtIiyd9etI0X3
22
+ ctu0uhrFyrMZXCedutvXNjUolD5r9KGBFSWH1R9u2I3n3SAyFF2yzv/7idQHLJJq
23
+ 74BMnx0FIq6fCpu5slAipvxZ3ZkZpEXZFr3cIBtO1gFvQWW7E/Y3ijliWJS1GQFq
24
+ 058qERadHGu1yu1dojmFRo6W2KZvY9al2yIlbkpDrD5MYQIDAQABo3cwdTAJBgNV
25
+ HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUFZsMapgzJimzsbaBG2Tm8j5e
26
+ AzgwHQYDVR0RBBYwFIESZGpiZXJnOTZAZ21haWwuY29tMB0GA1UdEgQWMBSBEmRq
27
+ YmVyZzk2QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAW2tnYixXQtKxgGXq
28
+ /3iSWG2bLwvxS4go3srO+aRXZHrFUMlJ5W0mCxl03aazxxKTsVVpZD8QZxvK91OQ
29
+ h9zr9JBYqCLcCVbr8SkmYCi/laxIZxsNE5YI8cC8vvlLI7AMgSfPSnn/Epq1GjGY
30
+ 6L1iRcEDtanGCIvjqlCXO9+BmsnCfEVehqZkQHeYczA03tpOWb6pon2wzvMKSsKH
31
+ ks0ApVdstSLz1kzzAqem/uHdG9FyXdbTAwH1G4ZPv69sQAFAOCgAqYmdnzedsQtE
32
+ 1LQfaQrx0twO+CZJPcRLEESjq8ScQxWRRkfuh2VeR7cEU7L7KqT10mtUwrvw7APf
33
+ DYoeCY9KyjIBjQXfbj2ke5u1hZj94Fsq9FfbEQg8ygCgwThnmkTrrKEiMSs3alYR
34
+ ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
35
+ WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
36
+ -----END CERTIFICATE-----
10
37
  date: 1980-01-02 00:00:00.000000000 Z
11
38
  dependencies:
12
39
  - !ruby/object:Gem::Dependency
@@ -53,25 +80,52 @@ dependencies:
53
80
  version: '3.12'
54
81
  description: A Ruby XML library with Nokogiri-compatible API, powered by Xerces-C
55
82
  instead of libxml2
56
- email:
57
- - contributors@example.com
83
+ email: djberg96@gmail.com
58
84
  executables: []
59
85
  extensions:
60
86
  - ext/rxerces/extconf.rb
61
87
  extra_rdoc_files: []
62
88
  files:
89
+ - CHANGES.md
90
+ - Gemfile
63
91
  - LICENSE
64
92
  - README.md
93
+ - Rakefile
94
+ - certs/djberg96_pub.pem
95
+ - examples/basic_usage.rb
96
+ - examples/schema_example.rb
97
+ - examples/simple_example.rb
98
+ - examples/xpath_example.rb
65
99
  - ext/rxerces/extconf.rb
66
100
  - ext/rxerces/rxerces.cpp
67
101
  - ext/rxerces/rxerces.h
68
102
  - lib/rxerces.rb
69
- - lib/rxerces/rxerces.bundle
103
+ - lib/rxerces/nokogiri.rb
70
104
  - lib/rxerces/version.rb
71
- homepage: https://github.com/example/rxerces
105
+ - rxerces.gemspec
106
+ - spec/document_spec.rb
107
+ - spec/element_spec.rb
108
+ - spec/node_spec.rb
109
+ - spec/nodeset_spec.rb
110
+ - spec/nokogiri_compatibility_spec.rb
111
+ - spec/rxerces_shared.rb
112
+ - spec/rxerces_spec.rb
113
+ - spec/schema_spec.rb
114
+ - spec/spec_helper.rb
115
+ - spec/xpath_spec.rb
116
+ homepage: http://github.com/djberg96/rxerces
72
117
  licenses:
73
118
  - MIT
74
- metadata: {}
119
+ metadata:
120
+ homepage_uri: https://github.com/djberg96/rxerces
121
+ bug_tracker_uri: https://github.com/djberg96/rxerces/issues
122
+ changelog_uri: https://github.com/djberg96/rxerces/blob/main/CHANGES.md
123
+ documentation_uri: https://github.com/djberg96/rxerces/wiki
124
+ source_code_uri: https://github.com/djberg96/rxerces
125
+ wiki_uri: https://github.com/djberg96/rxerces/wiki
126
+ rubygems_mfa_required: 'true'
127
+ github_repo: https://github.com/djberg96/rxerces
128
+ funding_uri: https://github.com/sponsors/djberg96
75
129
  rdoc_options: []
76
130
  require_paths:
77
131
  - lib
@@ -89,4 +143,12 @@ requirements: []
89
143
  rubygems_version: 3.6.9
90
144
  specification_version: 4
91
145
  summary: Nokogiri-compatible XML library using Xerces-C
92
- test_files: []
146
+ test_files:
147
+ - spec/document_spec.rb
148
+ - spec/element_spec.rb
149
+ - spec/node_spec.rb
150
+ - spec/nodeset_spec.rb
151
+ - spec/nokogiri_compatibility_spec.rb
152
+ - spec/rxerces_spec.rb
153
+ - spec/schema_spec.rb
154
+ - spec/xpath_spec.rb
metadata.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ Q� �q��o �{�;?��-6��%�:��-ܪB�h�y,�P�U}�#loyp�w��c����M@X+>��]U�.��<z5��a'�m�z]G���1laA�x���w�V�`���b6��U�����s��z��=u��$�6��Vj6��~��x:�����
2
+ O��Е>d~�s��cYs���� ������tHgd�% �Y��@TtcԁI��S
Binary file