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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 71254540124db9069ed4366fe61e6efa20d0d74fe4c92f5f8b51793bca16099d
4
- data.tar.gz: ba91d5747e0394f5cd5149921af75d838e97815f0dc8b2b09528ac775530461d
3
+ metadata.gz: 8a6f91adbbf73a000b638acc525461a8e0a06ce847bff4f8fd48ad5faf117483
4
+ data.tar.gz: ce10fe12e10294c5012624263cdbc05e4d751c7f62cad3647b2d73f88b19b8ab
5
5
  SHA512:
6
- metadata.gz: 6e26d2111e1ef02ed72fdac2e532d38201dfba9de4b1521bbf22046c2a23a1a821f0ad42368d47520f61139caa0aca365169399abf6ce79b2fa6fd337e0e0026
7
- data.tar.gz: 6897cb5b3f9755c4cab71735c4ca5eeaf5a3e85917c67d6a4e5903adb3312067de51961262ec7470ca7b91c1984007d58090f7078081a8400692358be870acc7
6
+ metadata.gz: c70510870068a501df10218e42c2eee838df962588929e0731d7e37eb250a80f3e875f77646a254681b976f487435fa531aca4144c1efc39ba22c6ec79c722fc
7
+ data.tar.gz: 47cacc7b927ff6ea7a5c206cd24d2d44fb52bc74ebdb314d05fa67d3bacd8f228113d7053f759626f70acde116ddcfffa194969c85a46a6a8e7e5850f906f36e
checksums.yaml.gz.sig ADDED
@@ -0,0 +1,4 @@
1
+ ���\�|� 1�"�F:\�A� ��Ի�pI�r4s�h�ҿ��>H݄����{,�R��ҩ���rV87]�B�*̃_��}��jf�k u�0�Ҩ�ܸ=PIR8���Z��ܯ�
2
+ kl��k@�'��(;�T�0��F-a��p�B"�(�Tu����pz8R�}'H#7}F@O/�L�l��H�h�%[%�
3
+ ^���ju�W��� ^��R/}-nUU�ZU�Q��j��ϳkS�q͆��GyQ:��:��`�q���� ��<ǯo��xt
4
+ ��3\Q K�gI���\9Lԟݺ��Zi�A��
data/CHANGES.md ADDED
@@ -0,0 +1,21 @@
1
+ ## 0.3.0 - 14-Dec-2025
2
+ * Added Node#parent.
3
+ * Added Element#attributes.
4
+ * Added Node#next_node and Node#next_sibling.
5
+ * Added Node#previous_node and Node#previous_sibling.
6
+ * Added Element#add_child.
7
+ * Added Node#remove and Node#unlink.
8
+ * Added Document#create_element.
9
+ * Added Element#inner_xml and Element#inner_html.
10
+ * Added Node#path.
11
+ * Added Node#blank?
12
+
13
+ ## 0.2.0 - 13-Dec-2025
14
+ * The nokogiri compatibility layer is now optional.
15
+ * Fixed up the gemspec with real values instead of the AI generated junk.
16
+ * Updated the Rakefile a bit, reworked some of the tasks.
17
+ * Minor spec updates.
18
+ * Added my cert.
19
+
20
+ ## 0.1.0 - 12-Dec-2025
21
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake', '~> 13.0'
6
+ gem 'rake-compiler', '~> 1.2'
7
+ gem 'rspec', '~> 3.12'
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Ruby](https://github.com/djberg96/rxerces/actions/workflows/ci.yml/badge.svg)](https://github.com/djberg96/rxerces/actions/workflows/ci.yml)
2
+
1
3
  # RXerces
2
4
 
3
5
  A Ruby XML library with a Nokogiri-compatible API, powered by Apache Xerces-C instead of libxml2.
@@ -73,10 +75,10 @@ puts root.name # => "root"
73
75
 
74
76
  ### Nokogiri Compatibility
75
77
 
76
- RXerces provides a `Nokogiri` module for drop-in compatibility:
78
+ RXerces provides optional Nokogiri compatibility. Require `rxerces/nokogiri` to enable drop-in replacement:
77
79
 
78
80
  ```ruby
79
- require 'rxerces'
81
+ require 'rxerces/nokogiri'
80
82
 
81
83
  # Use Nokogiri syntax
82
84
  doc = Nokogiri.XML('<root><child>text</child></root>')
@@ -86,6 +88,8 @@ puts doc.root.name # => "root"
86
88
  Nokogiri::XML::Document == RXerces::XML::Document # => true
87
89
  ```
88
90
 
91
+ **Note:** If you don't need Nokogiri compatibility, just `require 'rxerces'` and use the `RXerces` module directly.
92
+
89
93
  ### Working with Nodes
90
94
 
91
95
  ```ruby
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ require "rake/extensiontask"
2
+ require "rspec/core/rake_task"
3
+ require "rake/clean"
4
+ require "rbconfig"
5
+ include RbConfig
6
+
7
+ CLEAN.include(
8
+ '**/*.gem', # Gem files
9
+ '**/*.rbc', # Rubinius
10
+ '**/*.o', # C object file
11
+ '**/*.log', # Ruby extension build log
12
+ '**/*.lock', # Gemfile.lock
13
+ '**/Makefile', # C Makefile
14
+ '**/conftest.dSYM', # OS X build directory
15
+ "**/*.#{CONFIG['DLEXT']}" # C shared object
16
+ )
17
+
18
+ namespace :gem do
19
+ desc "Create the sys-uname gem"
20
+ task :create => [:clean] do
21
+ require 'rubygems/package'
22
+ spec = Gem::Specification.load('rxerces.gemspec')
23
+ spec.signing_key = File.join(Dir.home, '.ssh', 'gem-private_key.pem')
24
+ Gem::Package.build(spec)
25
+ end
26
+
27
+ desc "Install the sys-uname gem"
28
+ task :install => [:create] do
29
+ file = Dir["*.gem"].first
30
+ sh "gem install #{file}"
31
+ end
32
+ end
33
+
34
+ Rake::ExtensionTask.new("rxerces") do |ext|
35
+ ext.lib_dir = "lib/rxerces"
36
+ end
37
+
38
+ RSpec::Core::RakeTask.new(:spec) do |t|
39
+ t.verbose = false
40
+ t.rspec_opts = '-f documentation -w'
41
+ end
42
+
43
+ task default: [:compile, :spec]
@@ -0,0 +1,26 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MREwDwYDVQQDDAhkamJl
3
+ cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
4
+ MB4XDTE4MDMxODE1MjIwN1oXDTI4MDMxNTE1MjIwN1owPzERMA8GA1UEAwwIZGpi
5
+ ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
6
+ bTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALgfaroVM6CI06cxr0/h
7
+ A+j+pc8fgpRgBVmHFaFunq28GPC3IvW7Nvc3Y8SnAW7pP1EQIbhlwRIaQzJ93/yj
8
+ u95KpkP7tA9erypnV7dpzBkzNlX14ACaFD/6pHoXoe2ltBxk3CCyyzx70mTqJpph
9
+ 75IB03ni9a8yqn8pmse+s83bFJOAqddSj009sGPcQO+QOWiNxqYv1n5EHcvj2ebO
10
+ 6hN7YTmhx7aSia4qL/quc4DlIaGMWoAhvML7u1fmo53CYxkKskfN8MOecq2vfEmL
11
+ iLu+SsVVEAufMDDFMXMJlvDsviolUSGMSNRTujkyCcJoXKYYxZSNtIiyd9etI0X3
12
+ ctu0uhrFyrMZXCedutvXNjUolD5r9KGBFSWH1R9u2I3n3SAyFF2yzv/7idQHLJJq
13
+ 74BMnx0FIq6fCpu5slAipvxZ3ZkZpEXZFr3cIBtO1gFvQWW7E/Y3ijliWJS1GQFq
14
+ 058qERadHGu1yu1dojmFRo6W2KZvY9al2yIlbkpDrD5MYQIDAQABo3cwdTAJBgNV
15
+ HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUFZsMapgzJimzsbaBG2Tm8j5e
16
+ AzgwHQYDVR0RBBYwFIESZGpiZXJnOTZAZ21haWwuY29tMB0GA1UdEgQWMBSBEmRq
17
+ YmVyZzk2QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAW2tnYixXQtKxgGXq
18
+ /3iSWG2bLwvxS4go3srO+aRXZHrFUMlJ5W0mCxl03aazxxKTsVVpZD8QZxvK91OQ
19
+ h9zr9JBYqCLcCVbr8SkmYCi/laxIZxsNE5YI8cC8vvlLI7AMgSfPSnn/Epq1GjGY
20
+ 6L1iRcEDtanGCIvjqlCXO9+BmsnCfEVehqZkQHeYczA03tpOWb6pon2wzvMKSsKH
21
+ ks0ApVdstSLz1kzzAqem/uHdG9FyXdbTAwH1G4ZPv69sQAFAOCgAqYmdnzedsQtE
22
+ 1LQfaQrx0twO+CZJPcRLEESjq8ScQxWRRkfuh2VeR7cEU7L7KqT10mtUwrvw7APf
23
+ DYoeCY9KyjIBjQXfbj2ke5u1hZj94Fsq9FfbEQg8ygCgwThnmkTrrKEiMSs3alYR
24
+ ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
25
+ WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
26
+ -----END CERTIFICATE-----
@@ -0,0 +1,75 @@
1
+ require 'rxerces'
2
+ require 'rxerces/nokogiri'
3
+
4
+ puts "=== RXerces Basic Usage Example ===\n\n"
5
+
6
+ # Parse XML
7
+ xml = <<-XML
8
+ <library name="City Library">
9
+ <book id="1" isbn="978-0451524935">
10
+ <title>1984</title>
11
+ <author>George Orwell</author>
12
+ <year>1949</year>
13
+ </book>
14
+ <book id="2" isbn="978-0060850524">
15
+ <title>Brave New World</title>
16
+ <author>Aldous Huxley</author>
17
+ <year>1932</year>
18
+ </book>
19
+ </library>
20
+ XML
21
+
22
+ puts "1. Parsing XML document..."
23
+ doc = RXerces.XML(xml)
24
+ puts " ✓ Document parsed successfully\n\n"
25
+
26
+ # Access root element
27
+ puts "2. Accessing root element..."
28
+ root = doc.root
29
+ puts " Root element name: #{root.name}"
30
+ puts " Library name: #{root['name']}\n\n"
31
+
32
+ # Navigate children
33
+ puts "3. Navigating child elements..."
34
+ books = root.children.select { |n| n.is_a?(RXerces::XML::Element) }
35
+ puts " Found #{books.length} books:\n\n"
36
+
37
+ books.each do |book|
38
+ title = book.children.find { |n| n.name == 'title' }
39
+ author = book.children.find { |n| n.name == 'author' }
40
+ year = book.children.find { |n| n.name == 'year' }
41
+
42
+ puts " Book ##{book['id']}:"
43
+ puts " Title: #{title.text.strip}"
44
+ puts " Author: #{author.text.strip}"
45
+ puts " Year: #{year.text.strip}"
46
+ puts " ISBN: #{book['isbn']}"
47
+ puts
48
+ end
49
+
50
+ # Modify document
51
+ puts "4. Modifying the document..."
52
+ first_book = books.first
53
+ first_book['rating'] = '5 stars'
54
+ title = first_book.children.find { |n| n.name == 'title' }
55
+ puts " Added rating to first book: #{first_book['rating']}"
56
+ puts " First book title: #{title.text.strip}\n\n"
57
+
58
+ # Serialize back to XML
59
+ puts "5. Serializing to XML..."
60
+ xml_output = doc.to_xml
61
+ puts " ✓ Document serialized successfully"
62
+ puts "\n Output preview:"
63
+ puts " " + xml_output.lines.first(3).join(" ")
64
+ puts " ...\n\n"
65
+
66
+ # Nokogiri compatibility
67
+ puts "6. Testing Nokogiri compatibility..."
68
+ nokogiri_doc = Nokogiri.XML('<test><item>Hello World</item></test>')
69
+ puts " Parsed with Nokogiri.XML: #{nokogiri_doc.root.name}"
70
+ item = nokogiri_doc.root.children.find { |n| n.is_a?(Nokogiri::XML::Element) }
71
+ puts " Item text: #{item.text}"
72
+ puts " Document class: #{nokogiri_doc.class}"
73
+ puts " ✓ Nokogiri compatibility confirmed\n\n"
74
+
75
+ puts "=== Example Complete ==="
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/rxerces'
3
+
4
+ # Define an XSD schema
5
+ schema_xsd = <<~XSD
6
+ <?xml version="1.0"?>
7
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
8
+ <xs:element name="person">
9
+ <xs:complexType>
10
+ <xs:sequence>
11
+ <xs:element name="name" type="xs:string"/>
12
+ <xs:element name="age" type="xs:integer"/>
13
+ <xs:element name="email" type="xs:string"/>
14
+ </xs:sequence>
15
+ </xs:complexType>
16
+ </xs:element>
17
+ </xs:schema>
18
+ XSD
19
+
20
+ puts "=" * 60
21
+ puts "RXerces Schema Validation Example"
22
+ puts "=" * 60
23
+
24
+ # Create a schema from the XSD
25
+ puts "\nCreating schema from XSD..."
26
+ schema = RXerces::XML::Schema.from_string(schema_xsd)
27
+ puts "✓ Schema created successfully"
28
+
29
+ # Test 1: Valid document
30
+ puts "\n" + "-" * 60
31
+ puts "Test 1: Validating a VALID document"
32
+ puts "-" * 60
33
+
34
+ valid_xml = <<~XML
35
+ <?xml version="1.0"?>
36
+ <person>
37
+ <name>John Doe</name>
38
+ <age>30</age>
39
+ <email>john@example.com</email>
40
+ </person>
41
+ XML
42
+
43
+ doc = RXerces::XML::Document.parse(valid_xml)
44
+ errors = doc.validate(schema)
45
+ if errors.empty?
46
+ puts "✓ Document is VALID (no validation errors)"
47
+ else
48
+ puts "✗ Document has validation errors:"
49
+ errors.each { |error| puts " - #{error}" }
50
+ end
51
+
52
+ # Test 2: Invalid document (missing required element)
53
+ puts "\n" + "-" * 60
54
+ puts "Test 2: Validating an INVALID document (missing 'email')"
55
+ puts "-" * 60
56
+
57
+ invalid_xml = <<~XML
58
+ <?xml version="1.0"?>
59
+ <person>
60
+ <name>Jane Doe</name>
61
+ <age>25</age>
62
+ </person>
63
+ XML
64
+
65
+ doc2 = RXerces::XML::Document.parse(invalid_xml)
66
+ errors2 = doc2.validate(schema)
67
+ if errors2.empty?
68
+ puts "✓ Document is VALID (no validation errors)"
69
+ else
70
+ puts "✗ Document has validation errors (as expected):"
71
+ errors2.each { |error| puts " - #{error}" }
72
+ end
73
+
74
+ # Test 3: Invalid document (wrong type)
75
+ puts "\n" + "-" * 60
76
+ puts "Test 3: Validating an INVALID document (wrong type for 'age')"
77
+ puts "-" * 60
78
+
79
+ invalid_xml2 = <<~XML
80
+ <?xml version="1.0"?>
81
+ <person>
82
+ <name>Bob Smith</name>
83
+ <age>not-a-number</age>
84
+ <email>bob@example.com</email>
85
+ </person>
86
+ XML
87
+
88
+ doc3 = RXerces::XML::Document.parse(invalid_xml2)
89
+ errors3 = doc3.validate(schema)
90
+ if errors3.empty?
91
+ puts "✓ Document is VALID (no validation errors)"
92
+ else
93
+ puts "✗ Document has validation errors (as expected):"
94
+ errors3.each { |error| puts " - #{error}" }
95
+ end
96
+
97
+ # You can also create a schema from a document
98
+ puts "\n" + "-" * 60
99
+ puts "Creating schema from a Document object..."
100
+ puts "-" * 60
101
+ schema_doc = RXerces::XML::Document.parse(schema_xsd)
102
+ schema2 = RXerces::XML::Schema.from_document(schema_doc)
103
+ puts "✓ Schema created from Document"
104
+
105
+ puts "\n" + "=" * 60
106
+ puts "Full XSD validation is now implemented using Xerces-C!"
107
+ puts "=" * 60
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'rxerces'
4
+
5
+ puts "=== RXerces Simple Example (No Nokogiri) ===\n\n"
6
+
7
+ xml = <<-XML
8
+ <bookstore>
9
+ <book>
10
+ <title>1984</title>
11
+ <author>George Orwell</author>
12
+ </book>
13
+ </bookstore>
14
+ XML
15
+
16
+ # Parse using RXerces directly
17
+ doc = RXerces.XML(xml)
18
+
19
+ puts "Document parsed successfully!"
20
+ puts "Root element: #{doc.root.name}"
21
+ puts
22
+
23
+ # Find the book
24
+ book = doc.root.children.find { |n| n.is_a?(RXerces::XML::Element) }
25
+ title = book.children.find { |n| n.name == 'title' }
26
+ author = book.children.find { |n| n.name == 'author' }
27
+
28
+ puts "Book found:"
29
+ puts " Title: #{title.text.strip}"
30
+ puts " Author: #{author.text.strip}"
31
+ puts
32
+
33
+ puts "=== Example Complete ===\n"
34
+ puts "Note: This example uses RXerces directly without Nokogiri compatibility."
@@ -0,0 +1,108 @@
1
+ require 'rxerces'
2
+ require 'rxerces/nokogiri'
3
+
4
+ puts "=== RXerces XPath Example ===\n\n"
5
+
6
+ xml = <<-XML
7
+ <bookstore>
8
+ <book category="fiction">
9
+ <title>1984</title>
10
+ <author>George Orwell</author>
11
+ <year>1949</year>
12
+ <price>15.99</price>
13
+ </book>
14
+ <book 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 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
+ </bookstore>
27
+ XML
28
+
29
+ doc = RXerces.XML(xml)
30
+
31
+ puts "1. Finding all books:"
32
+ books = doc.xpath('//book')
33
+ puts " Found #{books.length} books"
34
+ puts
35
+
36
+ puts "2. Finding all titles:"
37
+ titles = doc.xpath('//title')
38
+ titles.each do |title|
39
+ puts " - #{title.text.strip}"
40
+ end
41
+ puts
42
+
43
+ puts "3. Finding all authors:"
44
+ authors = doc.xpath('//author')
45
+ authors.each do |author|
46
+ puts " - #{author.text.strip}"
47
+ end
48
+ puts
49
+
50
+ puts "4. Using absolute paths:"
51
+ bookstore_books = doc.xpath('/bookstore/book')
52
+ puts " Found #{bookstore_books.length} books via absolute path"
53
+ puts
54
+
55
+ puts "5. Querying from a specific node:"
56
+ first_book = books[0]
57
+ title = first_book.xpath('.//title').first
58
+ author = first_book.xpath('.//author').first
59
+ puts " First book: #{title.text.strip} by #{author.text.strip}"
60
+ puts
61
+
62
+ puts "6. Combining XPath with Ruby methods:"
63
+ puts " All books with their details:"
64
+ books.each_with_index do |book, i|
65
+ title_node = book.xpath('.//title').first
66
+ author_node = book.xpath('.//author').first
67
+ year_node = book.xpath('.//year').first
68
+ price_node = book.xpath('.//price').first
69
+
70
+ puts " Book #{i + 1}:"
71
+ puts " Title: #{title_node.text.strip}"
72
+ puts " Author: #{author_node.text.strip}"
73
+ puts " Year: #{year_node.text.strip}"
74
+ puts " Price: $#{price_node.text.strip}"
75
+ puts " Category: #{book['category']}"
76
+ puts
77
+ end
78
+
79
+ puts "7. Filtering with Ruby:"
80
+ puts " Fiction books only:"
81
+ fiction_books = books.select { |book| book['category'] == 'fiction' }
82
+ fiction_books.each do |book|
83
+ title = book.xpath('.//title').first
84
+ puts " - #{title.text.strip}"
85
+ end
86
+ puts
87
+
88
+ puts "8. Finding nested elements:"
89
+ all_prices = doc.xpath('//book/price')
90
+ puts " Found #{all_prices.length} prices:"
91
+ total = 0
92
+ all_prices.each do |price|
93
+ amount = price.text.strip.to_f
94
+ total += amount
95
+ puts " - $#{amount}"
96
+ end
97
+ puts " Total: $#{'%.2f' % total}"
98
+ puts
99
+
100
+ puts "9. Nokogiri compatibility:"
101
+ nokogiri_doc = Nokogiri.XML(xml)
102
+ nokogiri_books = nokogiri_doc.xpath('//book')
103
+ puts " Parsed with Nokogiri: #{nokogiri_books.length} books found"
104
+ puts
105
+
106
+ puts "=== Example Complete ==="
107
+ puts "\nNote: Xerces-C supports the XML Schema XPath subset."
108
+ puts "For advanced filtering, combine basic XPath with Ruby methods."