Class: SimpleRSS::XmlElement
- Inherits:
-
Object
- Object
- SimpleRSS::XmlElement
- Defined in:
- lib/simple-rss/xml_element.rb
Overview
rbs_inline: enabled
Instance Attribute Summary collapse
-
#attributes ⇒ Object
readonly
: Hash[String, String].
-
#base_urls ⇒ Object
readonly
: Array.
-
#content ⇒ Object
readonly
: String.
-
#name ⇒ Object
readonly
: String.
-
#namespaces ⇒ Object
readonly
: Hash[String, String].
Class Method Summary collapse
Instance Method Summary collapse
- #children ⇒ Object
-
#initialize(name, attributes, content, parent) ⇒ XmlElement
constructor
A new instance of XmlElement.
- #matches?(local_name, namespace) ⇒ Boolean
- #namespace ⇒ Object
- #raw ⇒ Object
- #rss?(local_name) ⇒ Boolean
- #selected?(selector) ⇒ Boolean
- #text ⇒ Object
- #xhtml_content ⇒ Object
Constructor Details
#initialize(name, attributes, content, parent) ⇒ XmlElement
Returns a new instance of XmlElement.
11 12 13 14 15 16 17 18 19 |
# File 'lib/simple-rss/xml_element.rb', line 11 def initialize(name, attributes, content, parent) @name = name @attributes = self.class.attributes(attributes).transform_values { |value| CGI.unescapeHTML(value) } @content = content.to_s @namespaces = parent.fetch(:namespaces).merge(@attributes.select { |key, _value| key == "xmlns" || key.start_with?("xmlns:") }) base_url = @attributes["xml:base"] @base_urls = parent.fetch(:base_urls).dup @base_urls << base_url if base_url end |
Instance Attribute Details
#attributes ⇒ Object (readonly)
: Hash[String, String]
5 6 7 |
# File 'lib/simple-rss/xml_element.rb', line 5 def attributes @attributes end |
#base_urls ⇒ Object (readonly)
: Array
8 9 10 |
# File 'lib/simple-rss/xml_element.rb', line 8 def base_urls @base_urls end |
#content ⇒ Object (readonly)
: String
6 7 8 |
# File 'lib/simple-rss/xml_element.rb', line 6 def content @content end |
#name ⇒ Object (readonly)
: String
4 5 6 |
# File 'lib/simple-rss/xml_element.rb', line 4 def name @name end |
#namespaces ⇒ Object (readonly)
: Hash[String, String]
7 8 9 |
# File 'lib/simple-rss/xml_element.rb', line 7 def namespaces @namespaces end |
Class Method Details
.attributes(attributes) ⇒ Object
92 93 94 95 96 97 98 99 100 |
# File 'lib/simple-rss/xml_element.rb', line 92 def self.attributes(attributes) values = {} #: Hash[String, String] attributes.scan(/([\w:.-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/m) do name = Regexp.last_match(1) value = Regexp.last_match(2) || Regexp.last_match(3) values[name] = value if name && value end values end |
.child_elements(content) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/simple-rss/xml_element.rb', line 103 def self.child_elements(content) elements = [] #: Array[[String, String, String?]] current_element = nil #: [String, String, String?]? depth = 0 body_start = 0 position = 0 while (token = SimpleRSS::XML_TAG_PATTERN.match(content, position)) position = token.end(0) attributes = token[3] next unless attributes if token[1] == "/" depth = [depth - 1, 0].max if depth.zero? && current_element current_element[2] = content[body_start...token.begin(0)] current_element = nil end next end self_closing = attributes.rstrip.end_with?("/") if depth.zero? element = [token[2].to_s, attributes, nil] #: [String, String, String?] elements << element current_element = element unless self_closing body_start = token.end(0) end depth += 1 unless self_closing end elements end |
Instance Method Details
#children ⇒ Object
22 23 24 25 26 |
# File 'lib/simple-rss/xml_element.rb', line 22 def children self.class.child_elements(content).map do |name, attributes, body| self.class.new(name, attributes, body, { namespaces: namespaces, base_urls: base_urls }) end end |
#matches?(local_name, namespace) ⇒ Boolean
34 35 36 |
# File 'lib/simple-rss/xml_element.rb', line 34 def matches?(local_name, namespace) name.split(":").last == local_name && self.namespace == namespace end |
#namespace ⇒ Object
29 30 31 |
# File 'lib/simple-rss/xml_element.rb', line 29 def namespace namespaces[name.include?(":") ? "xmlns:#{name.split(":").first}" : "xmlns"] end |
#raw ⇒ Object
63 64 65 |
# File 'lib/simple-rss/xml_element.rb', line 63 def raw { name: name, namespace: namespace, attributes: attributes, content: content } end |
#rss?(local_name) ⇒ Boolean
39 40 41 42 43 |
# File 'lib/simple-rss/xml_element.rb', line 39 def rss?(local_name) return false if name.include?(":") && namespace.nil? name.split(":").last == local_name && SimpleRSS::RSS_NAMESPACES.include?(namespace) end |
#selected?(selector) ⇒ Boolean
46 47 48 49 50 51 52 53 |
# File 'lib/simple-rss/xml_element.rb', line 46 def selected?(selector) if selector.start_with?("{") namespace, local_name = selector.delete_prefix("{").split("}", 2) return local_name ? matches?(local_name, namespace) : false end name == selector end |
#text ⇒ Object
56 57 58 59 60 |
# File 'lib/simple-rss/xml_element.rb', line 56 def text content.split(/(<!\[CDATA\[.*?\]\]>)/m).map do |part| part.start_with?("<![CDATA[") ? part[9...-3].to_s : CGI.unescapeHTML(part.gsub(/<!--.*?-->|<\?.*?\?>/m, "")) end.join.strip end |
#xhtml_content ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/simple-rss/xml_element.rb', line 68 def xhtml_content scopes = [namespaces] content.gsub(SimpleRSS::XML_TAG_PATTERN) do |token| name = Regexp.last_match(2).to_s attributes = Regexp.last_match(3) closing = Regexp.last_match(1) == "/" next token unless attributes if closing context = scopes.last || namespaces scopes.pop if scopes.size > 1 else declarations = self.class.attributes(attributes).select { |key, _value| key == "xmlns" || key.start_with?("xmlns:") } context = (scopes.last || namespaces).merge(declarations.transform_values { |value| CGI.unescapeHTML(value) }) scopes << context unless attributes.rstrip.end_with?("/") end namespace = context[name.include?(":") ? "xmlns:#{name.split(":").first}" : "xmlns"] next token unless namespace == "http://www.w3.org/1999/xhtml" token.sub(name, name.split(":").last.to_s) end.strip end |