rxerces 0.2.0 → 0.4.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGES.md +20 -0
- data/README.md +26 -2
- data/examples/schema_example.rb +107 -0
- data/ext/rxerces/extconf.rb +42 -0
- data/ext/rxerces/rxerces.cpp +834 -7
- data/lib/rxerces/nokogiri.rb +1 -0
- data/lib/rxerces/version.rb +1 -1
- data/rxerces.gemspec +5 -2
- data/spec/document_spec.rb +54 -0
- data/spec/node_spec.rb +448 -0
- data/spec/nokogiri_compatibility_spec.rb +69 -0
- data/spec/rxerces_shared.rb +1 -1
- data/spec/schema_spec.rb +76 -0
- data/spec/xpath_spec.rb +252 -18
- data.tar.gz.sig +0 -0
- metadata +7 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c6ba3896b05b5303ed0842c6ccc0376ce27e0325301dafe54472c73f9298ed9
|
|
4
|
+
data.tar.gz: 45844824ec1ca0ba91acf214cd1369466b40e1e0d7d1a653ed5ad7807a488e58
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d9513b47e15bf8219c9cfc0a801763b656622e0f00c517d4e3cc3065b7775555d03ec1ad933eb309933e9bb9563ec234f66d19ce179693a265bac1a9a9d52f7e
|
|
7
|
+
data.tar.gz: 8df33c1af2dc29c325e2b82a148b2adaa75d61d1e80a7dba466b39cb0896ea9a26da3c53b564a84643330c70d88f239202ee87b3fedb7c2ca66e4b82e5eb4112
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## 0.4.0 - 15-Dec-2025
|
|
2
|
+
* Now uses Xalan if installed for xpath 1.0 compliance.
|
|
3
|
+
* Added Node#search.
|
|
4
|
+
* Added Node#at and Node#at_xpath.
|
|
5
|
+
* Added Document#encoding.
|
|
6
|
+
* Added Node#namespace.
|
|
7
|
+
* Added a placeholder css method for now, it's on the TODO list.
|
|
8
|
+
|
|
9
|
+
## 0.3.0 - 14-Dec-2025
|
|
10
|
+
* Added Node#parent.
|
|
11
|
+
* Added Element#attributes.
|
|
12
|
+
* Added Node#next_node and Node#next_sibling.
|
|
13
|
+
* Added Node#previous_node and Node#previous_sibling.
|
|
14
|
+
* Added Element#add_child.
|
|
15
|
+
* Added Node#remove and Node#unlink.
|
|
16
|
+
* Added Document#create_element.
|
|
17
|
+
* Added Element#inner_xml and Element#inner_html.
|
|
18
|
+
* Added Node#path.
|
|
19
|
+
* Added Node#blank?
|
|
20
|
+
|
|
1
21
|
## 0.2.0 - 13-Dec-2025
|
|
2
22
|
* The nokogiri compatibility layer is now optional.
|
|
3
23
|
* Fixed up the gemspec with real values instead of the AI generated junk.
|
data/README.md
CHANGED
|
@@ -39,6 +39,28 @@ sudo apt-get install libxerces-c-dev
|
|
|
39
39
|
sudo yum install xerces-c-devel
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
+
### Xalan
|
|
43
|
+
|
|
44
|
+
For XPath 1.0 compliance, you will need to install the Xalan library. Note
|
|
45
|
+
that this is optional, and rxerces will default to using the Xpath support
|
|
46
|
+
from Xerces, which is more limited.
|
|
47
|
+
|
|
48
|
+
**Ubuntu/Debian:**
|
|
49
|
+
```bash
|
|
50
|
+
sudo apt-get install libxalan-c-dev
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Fedora/RHEL:**
|
|
54
|
+
```bash
|
|
55
|
+
sudo yum install xalan-c-devel
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Note that MacOS, contrary to what the documentation currently says, does not
|
|
59
|
+
have a brew package for Xalan. You will either need to use Mac ports or clone
|
|
60
|
+
and build the code manually. I found that it required some tweaking to work:
|
|
61
|
+
|
|
62
|
+
https://github.com/apache/xalan-c/pull/44
|
|
63
|
+
|
|
42
64
|
### Install the Gem
|
|
43
65
|
|
|
44
66
|
Add this line to your application's Gemfile:
|
|
@@ -156,7 +178,7 @@ puts doc.to_s
|
|
|
156
178
|
|
|
157
179
|
### XPath Queries
|
|
158
180
|
|
|
159
|
-
RXerces supports XPath queries using Xerces-C's XPath implementation:
|
|
181
|
+
RXerces supports XPath queries using Xerces-C's XPath implementation by default:
|
|
160
182
|
|
|
161
183
|
```ruby
|
|
162
184
|
xml = <<-XML
|
|
@@ -206,6 +228,8 @@ Not supported:
|
|
|
206
228
|
|
|
207
229
|
For more complex queries, you can combine basic XPath with Ruby's `select` and `find` methods.
|
|
208
230
|
|
|
231
|
+
For full XPath 1.0 support, install the Xalan library.
|
|
232
|
+
|
|
209
233
|
## API Reference
|
|
210
234
|
|
|
211
235
|
### RXerces Module
|
|
@@ -270,7 +294,7 @@ bundle exec rake
|
|
|
270
294
|
|
|
271
295
|
- Uses Apache Xerces-C 3.x for XML parsing
|
|
272
296
|
- C++ extension compiled with Ruby's native extension API
|
|
273
|
-
- XPath support is basic (full XPath requires
|
|
297
|
+
- XPath support is basic by default (full XPath requires Xalan)
|
|
274
298
|
- Memory management handled by Ruby's GC and Xerces-C's DOM
|
|
275
299
|
|
|
276
300
|
## Differences from Nokogiri
|
|
@@ -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
|
data/ext/rxerces/extconf.rb
CHANGED
|
@@ -29,4 +29,46 @@ unless find_header('xercesc/util/PlatformUtils.hpp')
|
|
|
29
29
|
puts "Proceeding with compilation..."
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
# Check for Xalan-C (optional for enhanced XPath support)
|
|
33
|
+
# Use dir_config which handles --with-xalan-dir and --with-xalan-include/lib
|
|
34
|
+
dir_config('xalan')
|
|
35
|
+
|
|
36
|
+
# Also try to auto-detect in common locations
|
|
37
|
+
if RUBY_PLATFORM =~ /darwin/
|
|
38
|
+
homebrew_xalan = `brew --prefix xalan-c 2>/dev/null`.chomp
|
|
39
|
+
if !homebrew_xalan.empty? && File.directory?(homebrew_xalan)
|
|
40
|
+
$INCFLAGS << " -I#{homebrew_xalan}/include" unless $INCFLAGS.include?("-I#{homebrew_xalan}/include")
|
|
41
|
+
$LDFLAGS << " -L#{homebrew_xalan}/lib" unless $LDFLAGS.include?("-L#{homebrew_xalan}/lib")
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Try standard locations
|
|
46
|
+
xalan_found_prefix = nil
|
|
47
|
+
['/usr/local', '/opt/local', '/usr'].each do |prefix|
|
|
48
|
+
if File.directory?("#{prefix}/include/xalanc")
|
|
49
|
+
$INCFLAGS << " -I#{prefix}/include" unless $INCFLAGS.include?("-I#{prefix}/include")
|
|
50
|
+
$LDFLAGS << " -L#{prefix}/lib" unless $LDFLAGS.include?("-L#{prefix}/lib")
|
|
51
|
+
xalan_found_prefix = prefix
|
|
52
|
+
break
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Check for Xalan libraries
|
|
57
|
+
# Note: We skip the header check because Xalan C++ headers require C++ compilation
|
|
58
|
+
# which mkmf's find_header doesn't handle well. The library check is sufficient.
|
|
59
|
+
if have_library('xalanMsg') && have_library('xalan-c')
|
|
60
|
+
$CXXFLAGS << " -DHAVE_XALAN"
|
|
61
|
+
# Add rpath so the dynamic libraries can be found at runtime
|
|
62
|
+
if xalan_found_prefix
|
|
63
|
+
$LDFLAGS << " -Wl,-rpath,#{xalan_found_prefix}/lib"
|
|
64
|
+
end
|
|
65
|
+
puts "Xalan-C found: Full XPath 1.0 support enabled"
|
|
66
|
+
else
|
|
67
|
+
puts "Xalan-C not found: Using Xerces XPath subset"
|
|
68
|
+
puts "For full XPath 1.0 support, install Xalan-C:"
|
|
69
|
+
puts " macOS: Build from source (no homebrew formula available)"
|
|
70
|
+
puts " Linux: May be available via package manager"
|
|
71
|
+
puts " Or specify: --with-xalan-dir=/path/to/xalan"
|
|
72
|
+
end
|
|
73
|
+
|
|
32
74
|
create_makefile('rxerces/rxerces')
|