Class: Philiprehberger::XmlBuilder::Document
- Inherits:
-
Object
- Object
- Philiprehberger::XmlBuilder::Document
- Defined in:
- lib/philiprehberger/xml_builder/document.rb
Overview
Accumulates XML nodes and renders the final document.
Used as the context object inside XmlBuilder.build blocks.
Constant Summary collapse
- PI_TARGET_PATTERN =
Valid PI target pattern per the XML spec (simplified).
/\A[A-Za-z_][\w.-]*\z/
Instance Attribute Summary collapse
-
#children ⇒ Object
readonly
Returns the value of attribute children.
-
#encoding ⇒ Object
readonly
Returns the value of attribute encoding.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Instance Method Summary collapse
-
#append(other) ⇒ void
Append children from another Document into this document.
-
#cdata(content) ⇒ void
Add a CDATA section.
-
#comment(text) ⇒ void
Add an XML comment.
-
#initialize(version: '1.0', encoding: 'UTF-8', declaration: true) ⇒ Document
constructor
A new instance of Document.
-
#insert_fragment(xml_string) ⇒ void
Insert a raw XML fragment string into the current position.
-
#method_missing(method_name, *args, &block) ⇒ Object
Support method_missing for DSL-style tag creation.
-
#namespace(prefix, uri) ⇒ void
Register an XML namespace prefix and URI.
-
#namespace_tag(prefix, name, attributes = {}) { ... } ⇒ Node
Add a namespace-prefixed element.
-
#processing_instruction(target, content = nil, **attrs) ⇒ void
(also: #pi)
Add a processing instruction.
-
#raw(string) ⇒ void
Add raw XML content without escaping.
- #respond_to_missing?(_method_name, _include_private = false) ⇒ Boolean
-
#soap_envelope(version: '1.1') {|header, body| ... } ⇒ void
Build a SOAP envelope using a block-based DSL.
-
#tag(name, attributes = {}) { ... } ⇒ Node
Add an XML element with optional attributes and nested children.
-
#text(content) ⇒ void
Add escaped text content to the current element.
-
#to_s ⇒ String
Render the document as a compact XML string (no indentation).
-
#to_xml(indent: nil) ⇒ String
Render the document as an XML string with optional indentation.
Constructor Details
#initialize(version: '1.0', encoding: 'UTF-8', declaration: true) ⇒ Document
Returns a new instance of Document.
13 14 15 16 17 18 19 20 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 13 def initialize(version: '1.0', encoding: 'UTF-8', declaration: true) @version = version @encoding = encoding @declaration = declaration @children = [] @node_stack = [] @namespaces = {} end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
Support method_missing for DSL-style tag creation.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 225 def method_missing(method_name, *args, &block) first_arg = args.first attributes = {} text_content = nil if first_arg.is_a?(Hash) attributes = first_arg elsif first_arg text_content = first_arg.to_s attributes = args[1] if args[1].is_a?(Hash) end if text_content tag(method_name, attributes) { text(text_content) } elsif block tag(method_name, attributes, &block) else tag(method_name, attributes) end end |
Instance Attribute Details
#children ⇒ Object (readonly)
Returns the value of attribute children.
9 10 11 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 9 def children @children end |
#encoding ⇒ Object (readonly)
Returns the value of attribute encoding.
9 10 11 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 9 def encoding @encoding end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
9 10 11 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 9 def version @version end |
Instance Method Details
#append(other) ⇒ void
This method returns an undefined value.
Append children from another Document into this document.
Copies all top-level children from the source document into the current insertion point (either the document root or the current parent element).
201 202 203 204 205 206 207 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 201 def append(other) raise Error, 'append expects a Document' unless other.is_a?(Document) other.children.each do |child| current_parent.push(child) end end |
#cdata(content) ⇒ void
This method returns an undefined value.
Add a CDATA section.
53 54 55 56 57 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 53 def cdata(content) raise Error, 'CDATA content must not contain "]]>"' if content.to_s.include?(']]>') current_parent.push("<![CDATA[#{content}]]>") end |
#comment(text) ⇒ void
This method returns an undefined value.
Add an XML comment.
63 64 65 66 67 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 63 def comment(text) raise Error, 'Comment text must not contain "--"' if text.to_s.include?('--') current_parent.push("<!-- #{text} -->") end |
#insert_fragment(xml_string) ⇒ void
This method returns an undefined value.
Insert a raw XML fragment string into the current position.
This is an alias for #raw, provided for semantic clarity when composing fragments.
216 217 218 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 216 def insert_fragment(xml_string) raw(xml_string) end |
#namespace(prefix, uri) ⇒ void
This method returns an undefined value.
Register an XML namespace prefix and URI.
Registered namespaces are automatically added as xmlns attributes when using namespace_tag.
138 139 140 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 138 def namespace(prefix, uri) @namespaces[prefix.to_s] = uri end |
#namespace_tag(prefix, name, attributes = {}) { ... } ⇒ Node
Add a namespace-prefixed element.
Automatically includes the xmlns declaration for the prefix if it was registered via #namespace and this is the first use in the current scope.
152 153 154 155 156 157 158 159 160 161 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 152 def namespace_tag(prefix, name, attributes = {}, &) prefixed_name = "#{prefix}:#{name}" uri = @namespaces[prefix.to_s] attrs = if uri { "xmlns:#{prefix}" => uri }.merge(attributes) else attributes end tag(prefixed_name, attrs, &) end |
#processing_instruction(target, content = nil, **attrs) ⇒ void Also known as: pi
This method returns an undefined value.
Add a processing instruction.
Accepts either a legacy positional content string or keyword attributes. When attrs are given, renders as <?target key=“value” key2=“value2”?>. When a content string is given, renders as <?target content?>.
83 84 85 86 87 88 89 90 91 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 83 def processing_instruction(target, content = nil, **attrs) validate_pi_target!(target) if content.is_a?(String) current_parent.push("<?#{target} #{content}?>") else current_parent.push(ProcessingInstruction.new(target, attrs)) end end |
#raw(string) ⇒ void
This method returns an undefined value.
Add raw XML content without escaping.
100 101 102 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 100 def raw(string) current_parent.push(string.to_s) end |
#respond_to_missing?(_method_name, _include_private = false) ⇒ Boolean
247 248 249 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 247 def respond_to_missing?(_method_name, _include_private = false) true end |
#soap_envelope(version: '1.1') {|header, body| ... } ⇒ void
This method returns an undefined value.
Build a SOAP envelope using a block-based DSL.
Supports SOAP 1.1 (default) and 1.2. Automatically sets the correct namespace URI and creates the Envelope, Header, and Body elements.
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 171 def soap_envelope(version: '1.1') uri = case version when '1.1' then 'http://schemas.xmlsoap.org/soap/envelope/' when '1.2' then 'http://www.w3.org/2003/05/soap-envelope' else raise Error, "Unsupported SOAP version: #{version}. Use '1.1' or '1.2'." end header_children = [] body_children = [] yield(header_children, body_children) if block_given? tag('soap:Envelope', 'xmlns:soap' => uri) do tag('soap:Header') do header_children.each { |child_block| child_block.call(self) } end tag('soap:Body') do body_children.each { |child_block| child_block.call(self) } end end end |
#tag(name, attributes = {}) { ... } ⇒ Node
Add an XML element with optional attributes and nested children.
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 28 def tag(name, attributes = {}, &block) node = Node.new(name, attributes) if block @node_stack.push(node) block.call @node_stack.pop end current_parent.push(node) node end |
#text(content) ⇒ void
This method returns an undefined value.
Add escaped text content to the current element.
45 46 47 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 45 def text(content) current_parent.push(Escaper.escape(content.to_s)) end |
#to_s ⇒ String
Render the document as a compact XML string (no indentation).
107 108 109 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 107 def to_s to_xml end |
#to_xml(indent: nil) ⇒ String
Render the document as an XML string with optional indentation.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 115 def to_xml(indent: nil) parts = [] if @declaration parts << "<?xml version=\"#{@version}\" encoding=\"#{@encoding}\"?>" parts << (indent ? "\n" : '') end @children.each do |child| parts << render_child(child, indent: indent, level: 0) end parts.join end |