blackwolf1983 发表于 2013-2-7 17:04:07

Validated XML Output with Method Generation

 
 
# A DSL for validated XML outputclass XMLGrammar# Create an instance of this class, specifying a stream or object to# hold the output. This can be any object that responds to <<(String).def initialize(out)    @out = out# Remember where to send our outputend# Invoke the block in an instance that outputs to the specified stream.def self.generate(out, &block)    new(out).instance_eval(&block)end# Define an allowed element (or tag) in the grammar.# This class method is the grammar-specification DSL# and defines the methods that constitute the XML-output DSL.def self.element(tagname, attributes={})    @allowed_attributes ||= {}    @allowed_attributes = attributes    class_eval %Q{      def #{tagname}(attributes={}, &block)      tag(:#{tagname},attributes,&block)      end    }end# These are constants used when defining attribute values.OPT = :opt   # for optional attributesREQ = :req   # for required attributesBOOL = :bool   # for attributes whose value is their own namedef self.allowed_attributes    @allowed_attributesend# Output the specified object as CDATA, return nil.def content(text)    @out << text.to_s    nilend# Output the specified object as a comment, return nil.def comment(text)    @out << "<!-- #{text} -->"    nilend# Output a tag with the specified name and attribute.# If there is a block, invoke it to output or return content.# Return nil.def tag(tagname, attributes={})    # Output the tag name    @out << "<#{tagname}"    # Get the allowed attributes for this tag.    allowed = self.class.allowed_attributes    # First, make sure that each of the attributes is allowed.    # Assuming they are allowed, output all of the specified ones.    attributes.each_pair do |key,value|      raise "unknown attribute: #{key}" unless allowed.include?(key)      @out << " #{key}='#{value}'"    end    # Now look through the allowed attributes, checking for   # required attributes that were omitted and for attributes with    # default values that we can output.    allowed.each_pair do |key,value|      # If this attribute was already output, do nothing.      next if attributes.has_key? key      if (value == REQ)      raise "required attribute '#{key}' missing in <#{tagname}>"      elsif value.is_a? String      @out << " #{key}='#{value}'"      end    end    if block_given?      # This block has content      @out << '>'             # End the opening tag      content = yield         # Invoke the block to output or return content      if content            # If any content returned      @out << content.to_s# Output it as a string      end      @out << "</#{tagname}>" # Close the tag    else       # Otherwise, this is an empty tag, so just close it.      @out << '/>'    end    nil # Tags output themselves, so they don't return any content.endend 
class HTMLForm < XMLGrammarelement :form, :action => REQ,               :method => "GET",               :enctype => "application/x-www-form-urlencoded",               :name => OPTelement :input, :type => "text", :name => OPT, :value => OPT,                  :maxlength => OPT, :size => OPT, :src => OPT,                  :checked => BOOL, :disabled => BOOL, :readonly => BOOLelement :textarea, :rows => REQ, :cols => REQ, :name => OPT,                     :disabled => BOOL, :readonly => BOOLelement :button, :name => OPT, :value => OPT,                   :type => "submit", :disabled => OPTend 
HTMLForm.generate(STDOUT) docomment "This is a simple HTML form"form :name => "registration",       :action => "http://www.example.com/register.cgi" do    content "Name:"    input :name => "name"    content "Address:"    textarea :name => "address", :rows=>6, :cols=>40 do      "Please enter your mailing address here"    end    button { "Submit" }endend#<!-- This is a simple HTML form --><form name='registration' action='http://www.example.com/register.cgi' enctype='application/x-www-form-urlencoded' method='GET'>Name:<input name='name' type='text'/>Address:<textarea rows='6' cols='40' name='address'>Please enter your mailing address here</textarea><button type='submit'>Submit</button></form>>Exit code: 0
页: [1]
查看完整版本: Validated XML Output with Method Generation