lib/handsoap/xml_mason.rb in troelskn-handsoap-0.2.9 vs lib/handsoap/xml_mason.rb in troelskn-handsoap-0.3.0
- old
+ new
@@ -1,31 +1,47 @@
# -*- coding: utf-8 -*-
module Handsoap
+ # XmlMason is a simple XML builder.
module XmlMason
- HTML_ESCAPE = { '&' => '&', '"' => '"', '>' => '>', '<' => '<' }
+ XML_ESCAPE = { '&' => '&', '"' => '"', '>' => '>', '<' => '<' }
- def self.html_escape(s)
- s.to_s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }
+ def self.xml_escape(s)
+ s.to_s.gsub(/[&"><]/) { |special| XML_ESCAPE[special] }
end
class Node
def initialize
@namespaces = {}
end
- def add(node_name, value = nil, *flags)
+ def add(node_name, value = nil, *flags) # :yields: Handsoap::XmlMason::Element
prefix, name = parse_ns(node_name)
node = append_child Element.new(self, prefix, name, value, flags)
if block_given?
yield node
end
end
+ # Registers a prefix for a namespace.
+ #
+ # You must register a namespace, before you can refer it.
def alias(prefix, namespaces)
@namespaces[prefix] = namespaces
end
+ # Finds the first element whos +node_name+ equals +name+
+ #
+ # Doesn't regard namespaces/prefixes.
+ def find(name)
+ raise NotImplementedError.new
+ end
+ # Finds all elements whos +node_name+ equals +name+
+ #
+ # Doesn't regard namespaces/prefixes.
+ def find_all(name)
+ raise NotImplementedError.new
+ end
def parse_ns(name)
matches = name.match /^([^:]+):(.*)$/
if matches
[matches[1] == '*' ? @prefix : matches[1], matches[2]]
else
@@ -34,11 +50,11 @@
end
private :parse_ns
end
class Document < Node
- def initialize
+ def initialize # :yields: Document
super
@document_element = nil
if block_given?
yield self
end
@@ -72,22 +88,22 @@
class TextNode
def initialize(text)
@text = text
end
def to_s(indentation = '')
- XmlMason.html_escape(@text)
+ XmlMason.xml_escape(@text)
end
end
class RawContent < TextNode
def to_s(indentation = '')
@text
end
end
class Element < Node
- def initialize(parent, prefix, node_name, value = nil, flags = [])
+ def initialize(parent, prefix, node_name, value = nil, flags = []) # :yields: Handsoap::XmlMason::Element
super()
# if prefix.to_s == ""
# raise "missing prefix"
# end
@parent = parent
@@ -100,33 +116,44 @@
end
if block_given?
yield self
end
end
+ # Returns the document that this element belongs to, or self if this is the document.
def document
@parent.respond_to?(:document) ? @parent.document : @parent
end
+ # Returns the qname (prefix:nodename)
def full_name
@prefix.nil? ? @node_name : (@prefix + ":" + @node_name)
end
+ # Adds a child node.
+ #
+ # You usually won't need to call this method, but will rather use +add+
def append_child(node)
if value_node?
raise "Element already has a text value. Can't add nodes"
end
@children << node
return node
end
+ # Sets the inner text of this element.
+ #
+ # By default the string is escaped, but you can pass the flag :raw to inject XML.
+ #
+ # You usually won't need to call this method, but will rather use +add+
def set_value(value, *flags)
if @children.length > 0
raise "Element already has children. Can't set value"
end
if flags && flags.include?(:raw)
@children = [RawContent.new(value)]
else
@children = [TextNode.new(value)]
end
end
+ # Sets the value of an attribute.
def set_attr(name, value)
full_name = parse_ns(name).join(":")
@attributes[name] = value
end
def find(name)
@@ -169,11 +196,11 @@
def to_s(indentation = '')
# todo resolve attribute prefixes aswell
if @prefix && (not defines_namespace?(@prefix))
set_attr "xmlns:#{@prefix}", get_namespace(@prefix)
end
- name = XmlMason.html_escape(full_name)
- attr = (@attributes.any? ? (" " + @attributes.map { |key, value| XmlMason.html_escape(key) + '="' + XmlMason.html_escape(value) + '"' }.join(" ")) : "")
+ name = XmlMason.xml_escape(full_name)
+ attr = (@attributes.any? ? (" " + @attributes.map { |key, value| XmlMason.xml_escape(key) + '="' + XmlMason.xml_escape(value) + '"' }.join(" ")) : "")
if @children.any?
if value_node?
children = @children[0].to_s(indentation + " ")
else
children = @children.map { |node| "\n" + node.to_s(indentation + " ") }.join("") + "\n" + indentation