REXML - text nodes

J

Jesper Olsen

I'm testing the REXML module (Ruby 1.8).

I have this simple XML ducument "test.xml":

<vxml:prompt>
You have chosen to stay at the
<vxml:value expr="field_hotel"/> tonight
</vxml:prompt>

which I analyse with this script:

require "rexml/document"
include REXML

file=File.new("test.xml")
doc=Document.new file

doc.elements.each("vxml:prompt") do |element|
puts "Text:" + element.text
element.elements.each() do |child|
puts "SubElement:" + child.name
end
end

The output is
Text:
You have chosen to stay at the
SubElement:value

The "text" method only returns the first "text node" in the prompt
element,
and there is only one child element. So apperantly text nodes are not
part
of the child elements array...

How do I access the remaining text?

I assume this is possible, but unfortunately the
http://www.germane-software.com/software/rexml seems to
be down today, so I can't get to the documentation.

Cheers
Jesper
 
B

Brian Candler

The "text" method only returns the first "text node" in the prompt
element,

It returns the first text child of the given node:

" text( path = nil )

A convenience method which returns the String value of the first child
text element, if one exists, and nil otherwise.

Note that an element may have multiple Text elements, perhaps
separated by other children. Be aware that this method only returns
the first Text node."
and there is only one child element. So apperantly text nodes are not
part
of the child elements array...

How do I access the remaining text?

They are children of the node, but you have explicitly called
Element#elements which filters out the non-text children:

[documentation for REXML::Elements]

each( xpath=nil, &block) {|e if e.kind_of? Element }| ...}

Iterates through all of the child Elements, optionally filtering them
by a given XPath
xpath: optional. If supplied, this is a String XPath, and is used to
filter the children, so that only matching children are yielded. Note
that XPaths are automatically filtered for Elements, so that
non-Element children will not be yielded

...and text children are REXML::Text, not REXML::Element, so are skipped.

However you can use Element#each to iterate over all the children, both Text
and Element:

require "rexml/document"
include REXML

file=File.new("test2.xml")
doc=Document.new file

doc.each do |element|
element.each do |child|
if child.is_a?(REXML::Text)
puts "Text: #{child.to_s.inspect}"
else
puts "SubElement: #{child.name}"
end
end
end

Regards,

Brian.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top