moxml 0.5.1 → 0.5.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 +4 -4
- data/lib/moxml/adapter/leptris.rb +10 -4
- data/lib/moxml/adapter/libxml.rb +14 -2
- data/lib/moxml/attribute_resolver.rb +8 -4
- data/lib/moxml/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6cadb7739071fa9a823f6a08fe5daa33c2313d22e4c4454aa491e975f62da5ee
|
|
4
|
+
data.tar.gz: b6682343586e2bf873c9067fccc68f03f2c67c8b10eafc418fcad6663320f2f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 67da3161b095e47aafe6d7e7327c2125a4458a9ef557c41c5f9d6465fccb01374d29c409178910b39426cf0cf7a42140d6858d4177c3f63b529690f397303796
|
|
7
|
+
data.tar.gz: c88f55e02c026e18f4c1a25578d9e27094835288e6ccc0dccff40633ff31029975125d9fcfb51ae5353f00ad5fa54fd8bef135d9e44c64da794b45513f728903
|
|
@@ -546,6 +546,10 @@ module Moxml
|
|
|
546
546
|
# returns those without name accessors). Both engines resolve
|
|
547
547
|
# expression prefixes against document-declared namespaces.
|
|
548
548
|
NATIVE_XPATH_CACHE = XPath::Cache.new(100)
|
|
549
|
+
# The gate decision is expression-intrinsic; re-walking the
|
|
550
|
+
# cached AST three times per xpath call cost ~23% of repeated
|
|
551
|
+
# selective queries, so the boolean caches beside it.
|
|
552
|
+
NATIVE_GATE_CACHE = XPath::Cache.new(100)
|
|
549
553
|
|
|
550
554
|
def xpath(node, expression, namespaces = {})
|
|
551
555
|
native = native_xpath(node, expression, namespaces)
|
|
@@ -623,11 +627,13 @@ module Moxml
|
|
|
623
627
|
# attribute-node results, or the nokogiri-compat xmlns:
|
|
624
628
|
# reserved prefix convention.
|
|
625
629
|
def native_expression?(expression)
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
630
|
+
NATIVE_GATE_CACHE.get_or_set(expression) do
|
|
631
|
+
ast = XPath::Parser.parse_with_cache(expression)
|
|
632
|
+
next false if ast_contains_type?(ast, :variable)
|
|
633
|
+
next false if uses_xmlns_prefix?(ast)
|
|
629
634
|
|
|
630
|
-
|
|
635
|
+
!selects_attribute_results?(ast)
|
|
636
|
+
end
|
|
631
637
|
rescue XPath::SyntaxError
|
|
632
638
|
false
|
|
633
639
|
end
|
data/lib/moxml/adapter/libxml.rb
CHANGED
|
@@ -7,6 +7,11 @@ require "libxml"
|
|
|
7
7
|
module Moxml
|
|
8
8
|
module Adapter
|
|
9
9
|
class Libxml < Base
|
|
10
|
+
# DOCTYPE prolog sniffer; see parse for the index-then-match
|
|
11
|
+
# strategy that keeps this off the hot path.
|
|
12
|
+
DOCTYPE_RE = /<!DOCTYPE\s+([^\s>]+)(?:\s+PUBLIC\s+"([^"]+)"\s+"([^"]+)"|\s+SYSTEM\s+"([^"]+)")?\s*>/i
|
|
13
|
+
private_constant :DOCTYPE_RE
|
|
14
|
+
|
|
10
15
|
autoload :EntityRefRegistry, "moxml/adapter/libxml/entity_ref_registry"
|
|
11
16
|
|
|
12
17
|
# Wrapper class to store DOCTYPE information
|
|
@@ -89,8 +94,15 @@ module Moxml
|
|
|
89
94
|
# parameter or XML declaration for byte interpretation.
|
|
90
95
|
xml_string = preprocess_entities(xml_string)
|
|
91
96
|
|
|
92
|
-
# Extract DOCTYPE before parsing
|
|
93
|
-
|
|
97
|
+
# Extract DOCTYPE before parsing. Locate the literal first:
|
|
98
|
+
# a plain memscan is ~2x cheaper than the regex's literal
|
|
99
|
+
# prefix scan on doctype-less documents (the common case),
|
|
100
|
+
# and matching from the found offset keeps captures
|
|
101
|
+
# identical.
|
|
102
|
+
doctype_idx = xml_string.index("<!DOCTYPE")
|
|
103
|
+
doctype_match = if doctype_idx
|
|
104
|
+
xml_string.match(DOCTYPE_RE, doctype_idx)
|
|
105
|
+
end
|
|
94
106
|
|
|
95
107
|
native_doc = begin
|
|
96
108
|
# Handle both string and file inputs
|
|
@@ -39,11 +39,15 @@ module Moxml
|
|
|
39
39
|
return nil if uri.nil?
|
|
40
40
|
|
|
41
41
|
element.attributes.find do |attr|
|
|
42
|
-
|
|
42
|
+
# attr.name allocates on several adapters (native string,
|
|
43
|
+
# plus leptris' force_encoding dup) — read it once per probe
|
|
44
|
+
attr_name = attr.name
|
|
45
|
+
local_name(attr_name) == local && attribute_uri(element, attr, attr_name) == uri
|
|
43
46
|
end
|
|
44
47
|
else
|
|
45
48
|
element.attributes.find do |attr|
|
|
46
|
-
|
|
49
|
+
attr_name = attr.name
|
|
50
|
+
local_name(attr_name) == name && attribute_uri(element, attr, attr_name).nil?
|
|
47
51
|
end
|
|
48
52
|
end
|
|
49
53
|
end
|
|
@@ -170,11 +174,11 @@ module Moxml
|
|
|
170
174
|
# adapters that report a prefix without resolving it (rexml/ox for
|
|
171
175
|
# the prebound xml prefix) and adapters that expose neither
|
|
172
176
|
# namespace nor separate prefix (leptris qualified names).
|
|
173
|
-
def attribute_uri(element, attr)
|
|
177
|
+
def attribute_uri(element, attr, attr_name = nil)
|
|
174
178
|
ns = attr.namespace
|
|
175
179
|
return ns.uri unless ns.nil? || ns.uri.to_s.empty?
|
|
176
180
|
|
|
177
|
-
prefix = ns&.prefix || prefix_part(attr.name)
|
|
181
|
+
prefix = ns&.prefix || prefix_part(attr_name || attr.name)
|
|
178
182
|
return nil if prefix.nil? || prefix.empty?
|
|
179
183
|
return XML_NAMESPACE_URI if prefix == "xml"
|
|
180
184
|
|
data/lib/moxml/version.rb
CHANGED