File: //usr/share/texmf/scripts/context/ruby/xmltools.rb
#!/usr/bin/env ruby
# program : xmltools
# copyright : PRAGMA Advanced Document Engineering
# version : 1.0 - 2002/2004
# author : Hans Hagen
# This script will harbor some handy manipulations on tex
# related files.
banner = ['XMLTools', 'version 1.1', '2002/2004', 'PRAGMA ADE/POD']
unless defined? ownpath
ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
$: << ownpath
end
require 'xmpl/switch'
require 'exa/logger'
class String
def astring(n=10)
gsub(/(\d+)/o) do $1.to_s.rjust(n) end.gsub(/ /o, '0')
end
def xstring
if self =~ /\'/o then
"\"#{self.gsub(/\"/, '"')}\""
else
"\'#{self}\'"
end
end
end
class Array
def asort(n=10)
sort {|x,y| x.astring(n) <=> y.astring(n)}
end
end
class Commands
include CommandBase
def dir
@xmlns = "xmlns='http://www.pragma-ade.com/rlg/xmldir.rng'"
pattern = @commandline.option('pattern')
recurse = @commandline.option('recurse')
stripname = @commandline.option('stripname')
longname = @commandline.option('longname')
url = @commandline.option('url')
outputfile = @commandline.option('output')
root = @commandline.option('root')
def generate(output,files,url,root,longname)
class << output
def xputs(str,n=0)
puts("#{' '*n}#{str}")
end
end
dirname = ''
output.xputs("<?xml version='1.0'?>\n\n")
if ! root || root.empty? then
rootatt = @xmlns
else
rootatt = " #{@xmlns} root='#{root}'"
end
rootatt += " timestamp='#{Time.now}'"
if url.empty? then
output.xputs("<files #{rootatt}>\n")
else
output.xputs("<files url='#{url}'#{rootatt}>\n")
end
files.each do |f|
bn, dn = File.basename(f), File.dirname(f)
if dirname != dn then
output.xputs("</directory>\n", 2) if dirname != ''
output.xputs("<directory name='#{dn}'>\n", 2)
dirname = dn
end
if longname && dn != '.' then
output.xputs("<file name='#{dn}/#{bn}'>\n", 4)
else
output.xputs("<file name='#{bn}'>\n", 4)
end
output.xputs("<base>#{bn.sub(/\..*$/,'')}</base>\n", 6)
if File.stat(f).file? then
bt = bn.sub(/^.*\./,'')
if bt != bn then
output.xputs("<type>#{bt}</type>\n", 6)
end
output.xputs("<size>#{File.stat(f).size}</size>\n", 6)
end
output.xputs("<date>#{File.stat(f).mtime.strftime("%Y-%m-%d %H:%M")}</date>\n", 6)
output.xputs("</file>\n", 4)
end
output.xputs("</directory>\n", 2) if dirname != ''
output.xputs("</files>\n")
end
if pattern.empty? then
report('provide --pattern=')
return
end
unless outputfile.empty? then
begin
output = File.open(outputfile,'w')
rescue
report("unable to open #{outputfile}")
return
end
else
report('provide --output')
return
end
if stripname && pattern.class == String && ! pattern.empty? then
pattern = File.dirname(pattern)
end
pattern = '*' if pattern.empty?
unless root.empty? then
unless FileTest.directory?(root) then
report("unknown root #{root}")
return
end
begin
Dir.chdir(root)
rescue
report("unable to change to root #{root}")
return
end
end
generate(output, globbed(pattern, recurse), url, root, longname)
output.close if output
end
alias ls :dir
def mmlpages
file = @commandline.argument('first')
eps = @commandline.option('eps')
jpg = @commandline.option('jpg')
png = @commandline.option('png')
style = @commandline.option('style')
modes = @commandline.option('modes')
file = file.sub(/\.xml/io, '')
long = "#{file}-mmlpages"
if FileTest.file?(file+'.xml') then
style = "--arg=\"style=#{style}\"" unless style.empty?
modes = "--mode=#{modes}" unless modes.empty?
if system("texmfstart texexec.pl --batch --pdf --once --result=#{long} --use=mmlpag #{style} #{modes} #{file}.xml") then
if eps then
if f = open("#{file}-mmlpages.txt") then
while line = f.gets do
data = Hash.new
if fields = line.split then
fields.each do |fld|
key, value = fld.split('=')
data[key] = value if key && value
end
if data.key?('p') then
page = data['p']
name = "#{long}-#{page.to_i-1}"
if eps then
report("generating eps file #{name}")
if system("pdftops -eps -f #{page} -l #{page} #{long}.pdf #{name}.eps") then
if data.key?('d') then
if epsfile = IO.read("#{name}.eps") then
epsfile.sub!(/^(\%\%BoundingBox:.*?$)/i) do
newline = $1 + "\n%%Baseline: #{data['d']}\n"
if data.key?('w') && data.key?('h') then
newline += "%%PositionWidth: #{data['w']}\n"
newline += "%%PositionHeight: #{data['h']}\n"
newline += "%%PositionDepth: #{data['d']}"
end
newline
end
if g = File.open("#{name}.eps",'wb') then
g.write(epsfile)
g.close
end
end
end
else
report("error in generating eps from #{name}")
end
end
end
end
end
f.close
else
report("missing data log file #{file}")
end
end
if png then
report("generating png file for #{long}")
system("imagemagick #{long}.pdf #{long}-%d.png")
end
if jpg then
report("generating jpg files for #{long}")
system("imagemagick #{long}.pdf #{long}-%d.jpg")
end
else
report("error in processing file #{file}")
end
system("texmfstart texutil --purge")
else
report("error in processing file #{file}")
end
end
def analyze
file = @commandline.argument('first')
result = @commandline.option('output')
if FileTest.file?(file) then
if data = IO.read(file) then
report("xml file #{file} loaded")
elements = Hash.new
attributes = Hash.new
entities = Hash.new
data.scan(/<([^>\s\/\!\?]+)([^>]*?)>/o) do
element, attributelist = $1, $2
if elements.key?(element) then
elements[element] += 1
else
elements[element] = 1
end
attributelist.scan(/\s*([^\=]+)\=([\"\'])(.*?)(\2)/) do
key, value = $1, $3
attributes[element] = Hash.new unless attributes.key?(element)
attributes[element][key] = Hash.new unless attributes[element].key?(key)
if attributes[element][key].key?(value) then
attributes[element][key][value] += 1
else
attributes[element][key][value] = 1
end
end
end
data.scan(/\&([^\;]+)\;/o) do
entity = $1
if entities.key?(entity) then
entities[entity] += 1
else
entities[entity] = 1
end
end
result = file.gsub(/\..*?$/, '') + '.xlg' if result.empty?
if f = File.open(result,'w') then
report("saving report in #{result}")
f.puts "<?xml version='1.0'?>\n"
f.puts "<document>\n"
if entities.length>0 then
f.puts " <entities>\n"
entities.keys.asort.each do |entity|
f.puts " <entity name=#{entity.xstring} n=#{entities[entity].to_s.xstring}/>\n"
end
f.puts " </entities>\n"
end
if elements.length>0 then
f.puts " <elements>\n"
elements.keys.sort.each do |element|
if attributes.key?(element) then
f.puts " <element name=#{element.xstring} n=#{elements[element].to_s.xstring}>\n"
if attributes.key?(element) then
attributes[element].keys.asort.each do |attribute|
f.puts " <attribute name=#{attribute.xstring}>\n"
attributes[element][attribute].keys.asort.each do |value|
f.puts " <instance value=#{value.xstring} n=#{attributes[element][attribute][value].to_s.xstring}/>\n"
end
f.puts " </attribute>\n"
end
end
f.puts " </element>\n"
else
f.puts " <element name=#{element.xstring} n=#{elements[element].to_s.xstring}/>\n"
end
end
f.puts " </elements>\n"
end
f.puts "</document>\n"
else
report("unable to open file '#{result}'")
end
else
report("unable to load file '#{file}'")
end
else
report("unknown file '#{file}'")
end
end
end
logger = EXA::ExaLogger.new(banner.shift)
commandline = CommandLine.new
commandline.registeraction('dir', 'generate directory listing')
commandline.registeraction('mmlpages','generate graphic from mathml')
commandline.registeraction('analyze', 'report entities and elements')
# commandline.registeraction('dir', 'filename --pattern= --output= [--recurse --stripname --longname --url --root]')
# commandline.registeraction('mmlpages','filename [--eps --jpg --png --style= --mode=]')
commandline.registeraction('ls')
commandline.registeraction('help')
commandline.registeraction('version')
commandline.registerflag('stripname')
commandline.registerflag('longname')
commandline.registerflag('recurse')
commandline.registervalue('pattern')
commandline.registervalue('url')
commandline.registervalue('output')
commandline.registervalue('root')
commandline.registerflag('eps')
commandline.registerflag('png')
commandline.registerflag('jpg')
commandline.registervalue('style')
commandline.registervalue('modes')
commandline.expand
Commands.new(commandline,logger,banner).send(commandline.action || 'help')