context - rexml: Ruby Standard Library Documentation

## Element Context¶ ↑

Notes:

- All code on this page presupposes that the following has been executed:

      require 'rexml/document'

- For convenience, examples on this page use `REXML::Document.new`, not `REXML::Element.new`. This is completely valid, because `REXML::Document` is a subclass of `REXML::Element`.

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:

- `:respect_whitespace`: controls treatment of whitespace.

- `:compress_whitespace`: determines whether whitespace is compressed.

- `:ignore_whitespace_nodes`: determines whether whitespace-only nodes are to be ignored.

- `:raw`: controls treatment of special characters and entities.

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>"