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.
-
#pretty(indent: 2) ⇒ String
Render the document as a pretty-printed XML string with default 2-space indentation.
-
#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.
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 233 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).
209 210 211 212 213 214 215 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 209 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.
224 225 226 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 224 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.
146 147 148 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 146 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.
160 161 162 163 164 165 166 167 168 169 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 160 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 |
#pretty(indent: 2) ⇒ String
Render the document as a pretty-printed XML string with default 2-space indentation.
115 116 117 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 115 def pretty(indent: 2) to_xml(indent: indent) 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
255 256 257 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 255 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.
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 179 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.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/philiprehberger/xml_builder/document.rb', line 123 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 |