Class: Xqruby::Document

Inherits:
BlankSlate
  • Object
show all
Defined in:
lib/xqruby/xqruby.rb

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Document

Create an Xqruby Document The method expects a hash that contain the possible elements :root => value : The name of the root or top-most element of the document :xml => value : A string containing an XML document :url => value : A URL pointing to an XML document :file => filename : A filename pointing to an XML file :validate => true|false : whether to validate the document being read from

an XML string, URL or file

:resolve_includes => true|false replaces xi:include elements by the content they refer to :namespace => provides a namespace prefix to the elements



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/xqruby/xqruby.rb', line 45

def initialize(options)
  # extract options
  validate = options[:validate] ? options[:validate] : false
  root = options[:root]
  xml = options[:xml]
  url = options[:url]
  file = options[:file]
  namespace = options[:namespace]
  resolve_includes = options[:resolve_includes] ? options[:resolve_includes] : false
  
  if root
    unless namespace
      @root = XOM::Element.new "#{root}"
    else
      @root = XOM::Element.new "#{root}", namespace
      prefix = root.to_s.split(":").first if root.include? ":"
      (@namespaces ||= {})[prefix] = namespace if prefix
    end
    
    @doc = XOM::Document.new @root
  else
    builder = XOM::Builder.new validate 
  end
  
  if xml
    @doc = builder.build(xml, nil)
  elsif url
    @doc = builder.build url
  elsif file
    java_file = Lang::File.new file        
    @doc = builder.build java_file       
  end
  
  if resolve_includes
    @doc = XOM::XIncluder.resolve(@doc)
  end
  
  @root = @doc.get_root_element unless @root
  @target = @root
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object

Dynamic Proxy behavior Add XML elements (tags) based on the name of the method called on the Document instance, blocks passed get processed recursively



89
90
91
92
93
94
95
96
97
98
99
100
101
102
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/xqruby/xqruby.rb', line 89

def method_missing(sym, *args, &block)
  if sym.to_s != 'class' && sym.to_s != 'to_s' && sym.to_s != 'inspect' # WTF? If I don't do this I
    text = nil                                 # end up with extraneous tags        
    attrs = nil                                # in the resulting document!!
    namespace = nil
    sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
    prefix = sym.to_s.split(":").first if sym.to_s.include? ":"
    args.each do |arg|
      case arg
      when Hash
        if arg.has_key? :namespace
          namespace = arg[:namespace]
          prefix = sym.to_s.split(":").first
        else
          attrs ||= {}
          attrs.merge!(arg)
        end
      else
        text ||= ''
        text << arg.to_s
      end
    end
    
    # try to get the namespace from the saved namespaces
    if prefix != nil && namespace.nil? && @namespaces != nil
      namespace = "#{@namespaces[prefix]}"
    end
    
    unless namespace
      tag = XOM::Element.new sym.to_s
    else
      tag = XOM::Element.new sym.to_s, namespace
    end 
    
    _add_attributes(tag, attrs)
    
    if block
      _nested_structures(block, tag)
    elsif !text.nil?              
      tag.append_child text
    end
    
    @target.append_child tag
  end
  
  self
end

Instance Method Details

#attributes(attrs) ⇒ Object

Adds attributes to the current target element (pointer to an element in the document by default the root of the document)



251
252
253
# File 'lib/xqruby/xqruby.rb', line 251

def attributes(attrs)
  _add_attributes(@target, attrs)
end

#comment!(string) ⇒ Object

Appends a comment node at the current position in the document



143
144
145
146
147
# File 'lib/xqruby/xqruby.rb', line 143

def comment!(string)
  comment = XOM::Comment.new string
  @target.append_child(comment)
  self
end

#doc_type!(root_element_name, public_id = '', system_id = '') ⇒ Object

Appends an XML document type declaration at the current position in the document



202
203
204
205
206
# File 'lib/xqruby/xqruby.rb', line 202

def doc_type!(root_element_name, public_id='', system_id='')
  doctype = XOM::DocType(root_element_name, public_id, system_id)
  @doc.insert_child(doctype, 0)
  self
end

#extract_textObject

Returns the value of the document as defined by XPath 1.0. This is the same as the value of the root element, which is the complete PCDATA content of the root element, without any tags, comments, or processing instructions after all entity and character references have been resolved.



235
236
237
# File 'lib/xqruby/xqruby.rb', line 235

def extract_text
  @doc.get_value
end

#find_first_tag_by_name(tag_name) ⇒ Object

Returns the value of the first child element with the specified name in no namespace. If there is no such element, it returns nill.



210
211
212
213
# File 'lib/xqruby/xqruby.rb', line 210

def find_first_tag_by_name(tag_name)
  element = @root.get_first_child_element tag_name
  element ? element.get_value : nil
end

#nil?Boolean

See Jim Weirich’s comment on builder (plus all the test frameworks seem to call nil? on objects being tested

Returns:

  • (Boolean)


227
228
229
# File 'lib/xqruby/xqruby.rb', line 227

def nil?
  false
end

#processing_instruction!(target, data) ⇒ Object

Appends a processing instruction at the current position in the document



157
158
159
160
161
# File 'lib/xqruby/xqruby.rb', line 157

def processing_instruction!(target, data)
  pi = XOM::ProcessingInstruction.new(target, data)
  @target.append_child(pi)
  self
end

#query(xpath_query) ⇒ Object

Returns the values of the nodes selected by the XPath expression in the context of this node in document order as defined by XSLT. This XPath expression must not contain any namespace prefixes.



218
219
220
221
222
223
# File 'lib/xqruby/xqruby.rb', line 218

def query(xpath_query)
  nodes = @doc.query xpath_query      
  result = Array.new
  (0..nodes.size-1).each do |i| result << nodes.get(i).get_value end
  result
end

#tag!(sym, *args, &block) ⇒ Object

Create a tag named sym. Other than the first argument which is the tag name, the arguments are the same as the tags implemented via method_missing. XOM will throw an exception if you pass something with a prefix but no associated namespace



183
184
185
186
# File 'lib/xqruby/xqruby.rb', line 183

def tag!(sym, *args, &block)
  method_missing(sym.to_sym, *args, &block)
  self
end

#target!(xpath_query) ⇒ Object

Attempts to reposition the document pointer based on the first match of and XQuery expression. Return true is the pointer was successfully moved and false otherwise



166
167
168
169
170
171
172
173
174
175
176
# File 'lib/xqruby/xqruby.rb', line 166

def target!(xpath_query)
  nodes = @doc.query xpath_query
  (0..nodes.size-1).each do |i| 
    node = nodes.get(i)
    if node.class == XOM::Element
      @target = node
      return true
    end        
  end
  return false
end

#text!(string) ⇒ Object

Appends a text node at the current position in the document



150
151
152
153
154
# File 'lib/xqruby/xqruby.rb', line 150

def text!(string)
  text = XOM::Text.new string
  @target.append_child(text)
  self
end

#to_canonical_formObject

Returns XML in the format specified by the Canonica XML Version 1.0 (w3.org/TR/2001/REC-xml-c14n-20010315 or Exclusive XML) Canonicalization Version 1.0 (w3.org/TR/2002/REC-xml-exc-c14n-20020718/)



242
243
244
245
246
247
# File 'lib/xqruby/xqruby.rb', line 242

def to_canonical_form
  baos = Lang::ByteArrayOutputStream.new
  outputter = XOM::Canonicalizer.new baos
  outputter.write(@doc)
  baos.to_string
end

#to_pretty_xml(indent = 2, line_length = 0, encoding = 'utf-8', preserve_base_uri = true) ⇒ Object

Returns a pretty-formatted document with the given indent, max line length and encoding. The preserve_base_uri determines whether preserves the original base URIs by inserting extra xml:base attributes.



191
192
193
194
195
196
197
198
# File 'lib/xqruby/xqruby.rb', line 191

def to_pretty_xml(indent=2, line_length=0, encoding='utf-8', preserve_base_uri=true)
  baos = Lang::ByteArrayOutputStream.new      
  serializer = XOM::Serializer.new(baos, encoding)
  serializer.indent = indent 
  serializer.max_length = line_length
  serializer.write @doc 
  baos.to_string
end

#to_xmlObject

Returns the XML document as a single line, e.g. no formatting



138
139
140
# File 'lib/xqruby/xqruby.rb', line 138

def to_xml
  @doc.to_xml
end