Element Context

Notes:

The context for an element is a hash of processing directives that influence the way XML is read, stored, and written. The context entries are:

The default context for a new element is {}. You can set the context at element-creation time:

d = REXML::Document.new('', {compress_whitespace: :all, raw: :all})
d.context # => {:compress_whitespace=>:all, :raw=>:all}

You can reset the entire context by assigning a new hash:

d.context = {ignore_whitespace_nodes: :all}
d.context # => {:ignore_whitespace_nodes=>:all}

Or you can create or modify an individual entry:

d.context[:raw] = :all
d.context # => {:ignore_whitespace_nodes=>:all, :raw=>:all}

:respect_whitespace

Affects: REXML::Element.new, REXML::Element.text=.

By default, all parsed whitespace is respected (that is, stored whitespace not compressed):

xml_string = '<root><foo>a   b</foo>    <bar>c   d</bar>   <baz>e   f</baz></root>'
d = REXML::Document.new(xml_string)
d.to_s # => "<root><foo>a   b</foo>    <bar>c   d</bar>   <baz>e   f</baz></root>"

Use :respect_whitespace with an array of element names to specify the elements that are to have their whitespace respected; other elements’ whitespace, and whitespace between elements, will be compressed.

In this example: foo and baz will have their whitespace respected; bar and the space between elements will have their whitespace compressed:

d = REXML::Document.new(xml_string, {respect_whitespace: ['foo', 'baz']})
d.to_s # => "<root><foo>a   b</foo> <bar>c d</bar> <baz>e   f</baz></root>"
bar = d.root[2] # => <bar> ... </>
bar.text = 'X   Y'
d.to_s # => "<root><foo>a   b</foo> <bar>X Y</bar> <baz>e   f</baz></root>"

:compress_whitespace

Affects: REXML::Element.new, REXML::Element.text=.

Use compress_whitespace: :all to compress whitespace both within and between elements:

xml_string = '<root><foo>a   b</foo>    <bar>c   d</bar>   <baz>e   f</baz></root>'
d = REXML::Document.new(xml_string, {compress_whitespace: :all})
d.to_s # => "<root><foo>a b</foo> <bar>c d</bar> <baz>e f</baz></root>"

Use :compress_whitespace with an array of element names to compress whitespace in those elements, but not in other elements nor between elements.

In this example, foo and baz will have their whitespace compressed; bar and the space between elements will not:

d = REXML::Document.new(xml_string, {compress_whitespace: ['foo', 'baz']})
d.to_s # => "<root><foo>a b</foo>    <bar>c   d</bar>   <baz>e f</baz></root>"
foo = d.root[0] # => <foo> ... </>
foo.text= 'X   Y'
d.to_s # => "<root><foo>X Y</foo>    <bar>c   d</bar>   <baz>e f</baz></root>"

:ignore_whitespace_nodes

Affects: REXML::Element.new.

Use ignore_whitespace_nodes: :all to omit all whitespace-only elements.

In this example, bar has a text node, while nodes foo and baz do not:

xml_string = '<root><foo>   </foo><bar> BAR </bar><baz>   </baz></root>'
d = REXML::Document.new(xml_string, {ignore_whitespace_nodes: :all})
d.to_s # => "<root><foo> FOO </foo><bar/><baz> BAZ </baz></root>"
root = d.root   # => <root> ... </>
foo = root[0]   # => <foo/>
bar = root[1]   # => <bar> ... </>
baz = root[2]   # => <baz/>
foo.first.class # => NilClass
bar.first.class # => REXML::Text
baz.first.class # => NilClass

Use :ignore_whitespace_nodes with an array of element names to specify the elements that are to have whitespace nodes ignored.

In this example, bar and baz have text nodes, while node foo does not.

xml_string = '<root><foo>   </foo><bar> BAR </bar><baz>   </baz></root>'
d = REXML::Document.new(xml_string, {ignore_whitespace_nodes: ['foo']})
d.to_s # => "<root><foo/><bar> BAR </bar><baz>   </baz></root>"
root = d.root   # => <root> ... </>
foo = root[0]   # => <foo/>
bar = root[1]   # => <bar> ... </>
baz = root[2]   # => <baz> ... </>
foo.first.class # => NilClass
bar.first.class # => REXML::Text
baz.first.class # => REXML::Text

:raw

Affects: Element.text=, Element.add_text, Text.to_s.

Parsing of a elements is not affected by raw:

xml_string = '<root><a>0 &lt; 1</a><b>1 &gt; 0</b></root>'
d = REXML::Document.new(xml_string, {:raw => ['a']})
d.root.to_s # => "<root><a>0 &lt; 1</a><b>1 &gt; 0</b></root>"
a, b = *d.root.elements
a.to_s # => "<a>0 &lt; 1</a>"
b.to_s # => "<b>1 &gt; 0</b>"

But Element#text= is affected:

a.text = '0 &lt; 1'
b.text = '1 &gt; 0'
a.to_s # => "<a>0 &lt; 1</a>"
b.to_s # => "<b>1 &amp;gt; 0</b>"

As is Element.add_text:

a.add_text(' so 1 &gt; 0')
b.add_text(' so 0 &lt; 1')
a.to_s # => "<a>0 &lt; 1 so 1 &gt; 0</a>"
b.to_s # => "<b>1 &amp;gt; 0 so 0 &amp;lt; 1</b>"