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
, notREXML::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>"
= d.root[2] # => <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/>
= root[1] # => <bar> ... </>
baz = root[2] # => <baz/>
foo.first.class # => NilClass
.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/>
= root[1] # => <bar> ... </>
baz = root[2] # => <baz> ... </>
foo.first.class # => NilClass
.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 < 1</a><b>1 > 0</b></root>'
d = REXML::Document.new(xml_string, {:raw => ['a']})
d.root.to_s # => "<root><a>0 < 1</a><b>1 > 0</b></root>"
a, b = *d.root.elements
a.to_s # => "<a>0 < 1</a>"
b.to_s # => "<b>1 > 0</b>"
But Element#text= is affected:
a.text = '0 < 1'
b.text = '1 > 0'
a.to_s # => "<a>0 < 1</a>"
b.to_s # => "<b>1 &gt; 0</b>"
As is Element.add_text:
a.add_text(' so 1 > 0')
b.add_text(' so 0 < 1')
a.to_s # => "<a>0 < 1 so 1 > 0</a>"
b.to_s # => "<b>1 &gt; 0 so 0 &lt; 1</b>"