Paul wrote:
> James - can you make this additional code available?

Sure, with the typical disclaimer that goes with
skunkworks ruby-coding-on-the-sly-deep-inside-a-java-house code.

The code at the end of this post works for most cases.  It does not, for 
example, trap or fix characters in an incorrect encoding, and skips 
processing instructions (and probably CDATA sections, now that I think 
of it).  These omissions haven't been an issue for me, but YMMV and all 
that.  It builds useful XML (albeit with far more attributes than one 
might ever need).  Use at will, no warranties expressed or implied, not 
suitable for running nuclear power plants or medical equipment, mumble 
mumble mumble.

> 
> Also, when you spawn multiple browsers, did you investigate which
> process they are in. When I have tried this they all live in the same
> process, and therefore share cookies, so cant be used for testing site
> that use cookies.

I paid no mind to separate processes.  Cookies were shared, I'm sure, 
though I suspect this may be due to how the cookies were set by they 
server; I believe the cookies would be shared even if I started 
independent browser sessions by hand.

James

# ============================================================
# Code to walk an HTML node tree made available through the
# clIEController class.   It requires that the owner class have an
# attribute named @iec that points to an instance of the IEController
# class, like this:
#   @iec = ClIEController.new( true )
# Once you've navigated to a URL, you get the XML using:
# xml = recursive_dump()
# You can pass the xml to an REXML document to run XPath against it.

#--==============================================================
#++
def recursive_dump( el=nil, indent=0 )
   el ||= @iec.htmlNode
   name = el.nodeName.downcase
   space = " " * indent
   name.strip!
   s = "#{space}<#{name}"

   if el.attributes
     for at in el.attributes
       s << " #{at.name}='#{escape(at.value)}'" if attribute_valid?(at)
     end
   end

   s << ">\n"

   for node in el.childNodes
     if node.childNodes &&  node.childNodes.length > 0
       s  << recursive_dump( node, indent+1 )
     elsif node.nodeName.downcase == "#text"
       s << escape( node.data )
     elsif node.nodeName.downcase == "#comment"
       s << "<!--  " + node.data     + " -->\n"
     else
       name2 = node.nodeName.downcase
       space2 = " " * (indent + 1)
       s << "#{space2}<#{name2}"
       if node.attributes
         for at in node.attributes
  s << " #{at.name}='#{escape( at.value )}'" if attribute_valid?( at )
         end
       end
       s << ">\n"
       s << "#{space2}</#{name2}>\n"
     end
   end
   s << el.nodeValue  if  el.nodeValue
   s << "#{space}</#{name}>\n"
end

#--===================================================================
#++
def attribute_valid?( at )
   return false if at.value.to_s == "null"
   return false if at.value.to_s.strip.size < 1
   return false if at.name.to_s =~ /xml:/i
   true
end

#--====================================================================
#++
def escape( str )
   s = str.gsub( /&/, "&amp;")
   s.gsub!( /</, "&lt;")
   s.gsub!( />/, "&gt;")
   s.gsub!( /\'/, "&apos;")
   s.gsub( /\"/, "&quot;")
end