blob: 13a2d1b093b702134ae7f73d1f995fb52943f3c1 [file] [log] [blame]
#
# xml.tcl --
#
# Syntax:
#
# ::rivet::xml string ?tag ?attr val? ?attr val?? ?tag ?attr val? ?attr val??
#
# or
#
# ::rivet::xml ?tag ?attr val? ?attr val??
#
# Example 1:
#
# trivial nested markup fragment
#
# ::rivet::xml Test b i
# <= <b><i>Test</i></b>
#
# Example 2:
#
# XHTML Element with attributes
#
# ::rivet::xml Test [list div class box id testbox] b i
# <= <div class="box" id="testbox"><b><i>Test</i></b></div>
#
# Example 3
#
# ::rivet::xml "anything ..." div [list a href "http://..../" title "info message"]
# <= <div><a href="http://..../" title="info message">anything ...</a></div>
#
# Example 4
#
# ::rivet::xml "" [list a attr1 val1 attr2 val2] [list b attr1 val1 attr2 val2]
# <= <a attr1="val1" attr2="val2"><b attr1="val1" attr2="val2"></b></a>
#
# Example 5
#
# single self closing element
#
# ::rivet::xml [list a attr1 val1 attr2 val2]
# <= <a attr1="val1" attr2="val2" />
#
namespace eval ::rivet {
proc xml {textstring args} {
set single_element [::rivet::lempty $args]
if {$single_element} {
set tags_list [list $textstring]
if {[::rivet::lempty $tags_list]} { return "" }
} else {
set tags_list $args
}
set tags_stack {}
set el {}
set xmlout ""
foreach el $tags_list {
set el [lassign $el tag]
lappend tags_stack $tag
append xmlout "<$tag"
foreach {attrib attrib_v} $el {
append xmlout " $attrib=\"$attrib_v\""
}
append xmlout ">"
}
if {[::rivet::lempty $tags_stack]} {
return $textstring
} elseif {$single_element} {
# variable 'el' keeps the last (innermost) attribute-value list
if {[::rivet::lempty $el] == 1} {
set xmlout [string replace $xmlout end end " />"]
} else {
set xmlout [string replace $xmlout end end "/>"]
}
if {[llength $tags_stack] > 1} {
set xmlout [append xmlout "</[join [lreverse [lrange $tags_stack 0 end-1]] "></"]>"]
}
return $xmlout
} else {
return [append xmlout "$textstring</[join [lreverse $tags_stack] "></"]>"]
}
}
}