Class: TaskJuggler::XMLElement

Inherits:
Object
  • Object
show all
Defined in:
lib/taskjuggler/XMLElement.rb

Overview

This class models an XML node that may contain other XML nodes. XML element trees can be constructed with the class constructor and converted into XML.

Direct Known Subclasses

XMLBlob, XMLComment, XMLNamedText, XMLText

Instance Method Summary collapse

Constructor Details

#initialize(name, attributes = {}, selfClosing = false, &block) ⇒ XMLElement

Construct a new XML element and include it in an existing XMLElement tree.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/taskjuggler/XMLElement.rb', line 23

def initialize(name, attributes = {}, selfClosing = false, &block)
  if (name.nil? && attributes.length > 0) ||
     (!name.nil? && !name.is_a?(String))
    raise ArgumentError, "Name must be nil or a String "
  end
  @name = name
  attributes.each do |n, v|
    if n.nil? || v.nil?
      raise ArgumentError,
        "Attribute name (#{n}) or value (#{v}) may not be nil"
    end
    unless v.is_a?(String)
      raise ArgumentError,
        "Attribute value of #{n} must be a String"
    end
  end
  @attributes = attributes
  # This can be set to true if <name /> is legal for this element.
  @selfClosing = selfClosing

  @children = block ? yield(block) : []
  # Allow blocks with single elements not to be Arrays. They will be
  # automatically converted into Arrays here.
  unless @children.is_a?(Array)
    @children = [ @children ]
  else
    @children.flatten!
  end

  # Convert all children that are text String objects into XMLText
  # objects.
  @children.collect! do |c|
    c.is_a?(String) ? XMLText.new(c) : c
  end

  # Make sure we have no nil objects in the list.
  @children.delete_if { |c| c.nil? }

  # Now all children must be XMLElement objects.
  @children.each do |c|
    unless c.is_a?(XMLElement)
      raise ArgumentError,
        "Element must be of type XMLElement, not #{c.class}: #{c.inspect}"
    end
  end
end

Instance Method Details

#<<(arg) ⇒ Object

Add a new child or a set of new childs to the element.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/taskjuggler/XMLElement.rb', line 71

def <<(arg)
  # If the argument is an array, we have to insert each element
  # individually.
  if arg.is_a?(XMLElement)
    @children << arg
  elsif arg.is_a?(String)
    @children << XMLText.new(arg)
  elsif arg.is_a?(Array)
    # Delete all nil entries
    arg.delete_if { |i| i.nil? }
    # Check that the rest are really all XMLElement objects.
    arg.each do |i|
      unless i.is_a?(XMLElement)
        raise ArgumentError,
          "Element must be of type XMLElement, not #{i.class}: #{i.inspect}"
      end
    end
    @children += arg
  elsif arg.nil?
    # Do nothing. Insertions of nil are simply ignored.
  else
    raise "Elements must be of type XMLElement not #{arg.class}"
  end
  self
end

#[](attribute) ⇒ Object

Return the value of attribute attribute.



105
106
107
# File 'lib/taskjuggler/XMLElement.rb', line 105

def [](attribute)
  @attributes[attribute]
end

#[]=(attribute, value) ⇒ Object

Add or change attribute to value.

Raises:

  • (ArgumentError)


98
99
100
101
102
# File 'lib/taskjuggler/XMLElement.rb', line 98

def []=(attribute, value)
  raise ArgumentError,
    "Attribute value #{value} is not a String" unless value.is_a?(String)
  @attributes[attribute] = value
end

#to_s(indent = 0) ⇒ Object

Return the element and all sub elements as properly formatted XML.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/taskjuggler/XMLElement.rb', line 111

def to_s(indent = 0)
  out = '<' + @name
  @attributes.keys.sort.each do |attrName|
    out << " #{attrName}=\"#{escape(@attributes[attrName], true)}\""
  end
  if @children.empty? && @selfClosing
    out << '/>'
  else
    out << '>'
    @children.each do |child|
      # We only insert newlines for multiple childs and after a tag has been
      # closed.
      if @children.size > 1 && !child.is_a?(XMLText) && out[-1] == ?>
        out << "\n" + indentation(indent + 1)
      end
      out << child.to_s(indent + 1)
    end
    out << "\n" + indentation(indent) if @children.size > 1 && out[-1] == ?>
    out << '</' + @name + '>'
  end
end