Standards

This document should comply with the standards below. Click on one to check.

Valid XHTML 1.0!

Valid CSS!

Decorate XML

This simple program copies decorates one xml file with another. Two files are input. One is the decoration for the other. It looks for lines in the decoration that contain a string like [decorated body goes here]. When it finds one, that string is replaced by the body of the other file, the decorated file. Below is the source.

# Decorate the input.
# Usage: ruby -s decoratexml.rb -with=decore.xhtml [input]
# The decore is copied to the output.
# Strings in the decore like [decorated tag goes here]
# are replaced with the tagged section of the input.
# Strings in the decore like [date goes here]
# are replaced with the current date in yyyy-mm-dd form.
# Strings in the decore like [global var goes here]
# are replaced with the value of global variable $var.
# e.g. ruby -s decoratexml.rb -var=value ...
# Strings in the decore like [env var goes here]
# are replaced with the value of environment variable $var.
# Strings in the decore like [system command goes here]
# are replaced with the stdout of running "command".

require 'rexml/document'

decore = nil
decore = $with if $with
source = STDIN
source = File.open( ARGV[0] ) if 0 < ARGV.length

if ! decore
  puts "usage: ruby -s decoratexml.rb -with=decore.xhtml [input]"
  exit
end

xml = REXML::Document.new(source)

#global_variables.each { |g| puts g }

#wanted = "$with"
#puts eval wanted

File.open( decore ).each { |theLine|
  if ( m = /\[decorated ([^\] ]*) goes here\]/.match theLine )
    selector = m[1]
    if ( m2 = /([^.#]+)\.(.+)/.match selector )
      tag = m2[1]
      tagclass = m2[2]
      ea = xml.elements.to_a( "//#{tag}[@class='#{tagclass}']" )
      section = ea.first
    elsif ( m2 = /([^.#]+)#(.+)/.match selector )
      tag = m2[1]
      tagname = m2[2]
      ea = xml.elements.to_a( "//#{tag}[@name='#{tagname}']" )
      if ea.size < 1
        ea = xml.elements.to_a( "//#{tag}[@id='#{tagname}']" )
      end
      section = ea.first
    else
      section = xml.elements["//#{selector}"]
    end
    if section
      puts m.pre_match +
           section.text +
           section.elements.each { |theElement| theElement.to_s }.join( "\n" ) +
           m.post_match
    else
      puts theLine
    end
  elsif ( m = /\[date goes here\]/.match theLine )
    puts m.pre_match + Time.now.strftime( "%Y-%m-%d" ) + m.post_match
  elsif ( m = /\[global ([^ ]*) goes here\]/.match theLine )
    g = eval "$" + m[1]
    puts theLine unless g
    puts m.pre_match + g + m.post_match if g
  elsif ( m = /\[env ([^ ]+) goes here\]/.match theLine )
    e = ENV[m[1]]
    puts theLine unless e
    puts m.pre_match + e + m.post_match if e
  elsif ( m = /\[system (.+) goes here\]/.match theLine )
#   puts m.pre_match + %x{#{m[1]}} + m.post_match
    print m.pre_match
    system m[1]
    puts m.post_match
  else
    puts theLine
  end
}

Look at the Makefile in this directory to see one way it can be used. We export some shell variables that are used within decoratexml.html.uc. This way all the file names appear in the Makefile and none are hidden in decoratexml.html.uc. Ubercat.rb is then applied to create decoratexml.html. At last decore.xhtml is applied by decoratexml.rb to create decoratexml.xhtml.

Notice that all pages, those being decorated and those used as decoration as well as the result, should be readily readable and understandable when viewed in a browser.

Notice also that decoration can be nested. c.f. SiteMesh

The tag in the syntax [undecorated tag goes here] is like a CSS selector. So I'm going to call it a "selector". There are only a few forms it can take:

Other Insertions

Future

Helpful might be:

Maybe the terms should be changed:

undecorated
The raw file that will be decorated.
decore
The file that will be wrapped around the undecorated file.
decorated
The result

So the undecorated + the decore -> the decorated. This will allow us to refer in the decore to both the undecorated and the decorated. e.g. we might want the file name of the decorated in the footer. Hence there might be both "[undecorated body goes here]" and "[decorated filename goes here]".

Perhaps a syntax like [undecorated attr of selector goes here] would be useful? Or other CSS like selector syntax like .class, tag subtag, etc.?

We could add some other stuff to make it a bit like a poor man's XSLT. Note that we want to continue the idea that every page stands on it's own, and can be reasonably viewed and understood in a web browser.

Maybe strip any mock up division (<div class="mockup">). This would allow web designers to put in mock text to see how a decore might look.


http://www.BlossomAssociates.net/ubercat/decoratexml.xhtml 2007-08-27