# Features covered: Schema validation
#
# Tested functionalities:
#    schema-1.*: Basics, interface
#    schema-2.*: Grammar definition ref
#    schema-3.*: Grammar definition choice
#    schema-4.*: Script level validation with event
#    schema-5.*: dom parse -validateCmd
#    schema-6.*: expat parser -validateCmd
#    schema-7.*: Validation checks.
#    schema-8.*: tdom::schema validate method
#    schema-9.*: Choice
#    schema-10.*: Any
#    schema-11.*: attribute, nsattribute
#    schema-12.*: schemaCmd domvalidate
#    schema-13.*: XML namespaces
#    schema-14.*: text
#    schema-15.*: Constraint cmd tcl
#    schema-16.*: interleave
#    schema-17.*: info
#    schema-18.*: reportcmd, validation error recover
#    schema-19.*: keyspace
#    schema-20.*: domunique
#    schema-21.*: internal: buffers
#    schema-22.*: defelementtype, elementtype
#    schema-23.*: validatefile
#    schema-24.*: validatechannel
#    schema-25.*: domxpathboolean
#    schema-26.*: info domNode
#    schema-27.*: Text constraint commands available outsite schema context
#
# Copyright (c) 2018-2020 Rolf Ade.

source [file join [file dir [info script]] loadtdom.tcl]

if {[dom featureinfo schema]} {

testConstraint 8.5 [package vsatisfies [package present Tcl] 8.5]
testConstraint listformat [package vsatisfies [package present Tcl] 8.5]

proc dummycallback {args} {}

proc sortcps {a b} {
    switch -- [string compare [lindex $a 0] [lindex $b 0]] {
        -1 {return -1}
        1 {return 1}
        default {
            return [string compare [lindex $a 1] [lindex $b 1]]
        }
    }
}

test schema-1.1 {create} {
    tdom::schema create grammar
    grammar start doc
    grammar delete
} {}

test schema-1.2 {grammar cmd outside context} {
    catch {tdom::schema::element}
} {1}

test schema-1.3 {grammar cmd} {
    tdom::schema create grammar
    grammar defpattern somePattern {
        element foo !
    }
    grammar delete
} {}

test schema-1.4 {grammar cmd} {
    tdom::schema create grammar
    grammar defpattern somePattern {
        for {set i 0} {$i < 100} {incr i} {
            element foo$i !
        }
    }
    grammar delete
} {}

test schema-1.5 {grammar cmd} {
    tdom::schema create grammar
    grammar defelement doc {
        element elm1
        element elm2 *
    }
    grammar defelement elm1 {}
    grammar defelement elm2 {}
    grammar delete
} {}

test schema-1.6 {quants} {
    tdom::schema create grammar
    grammar defelement doc {
        element elm1
        element elm2 *
        element elm3 !
        element elm4 +
        element elm5 ?
        element elm6 1
        element elm7 5
        element elm8 12
        element elm9 {0 3}
        element elm9 {1 12}
        element elm10 "8 "
    }
    grammar delete
} {}

test schema-1.7 {quants} {
    tdom::schema create grammar
    grammar defelement doc {
        for {set i 0} {$i < 100} {incr i} {
            element elm$i [list $i [expr {$i + 1}]]
        }
    }
    grammar delete
} {}

test schema-1.8 {Same element name in different Namespaces} {
    tdom::schema create grammar
    grammar defelement doc {
        element elm1
        element elm2
    }
    grammar defelement doc ns1 {
        # Forward defined element inherits child namespace
        element elm1
        element elm2
    }
    grammar defelement doc ns2 {
        # Forward defined element inherits child namespace
        element elm1
        element elm2
    }
    grammar defelement elm1 ns2 {}
    grammar defelement elm2 ns2 any
    set result [catch {
        grammar defelement elm1 ns1 {
            choice {
                element fooElem
                element barElem +
            }
            error
        }
    }]
    grammar defelement elm1 ns1 any
    grammar defelement elm2 ns1 {}
    grammar delete
    set result
} 1

test schema-1.9 {Same element name in different Namespaces} {
    tdom::schema create grammar
    set result [catch {
        grammar defelement doc {
            element elm1
            element elm2
        }
        grammar defelement doc ns1 {
            # Forward defined element inherits child namespace
            element elm1
            element elm2
        }
        grammar defelement doc ns2 {
            # Forward defined element inherits child namespace
            element elm1
            element elm2
        }
        grammar defelement elm1 ns2 {}
        grammar defelement elm2 ns2 any
        grammar defelement elm1 ns1 {
            choice {
                element fooElem
                element barElem +
            }
            error
        }
    }]
    grammar delete
    set result
} 1

test schema-1.10 {Local element definition} {
    tdom::schema create grammar
    grammar defelement doc {
        element elm1
        element elm1 1 {
            element a
            element b
        }
    }
    grammar defelement c text
    grammar defelement d text
    grammar defelement elm1 {
        element c
        element d
    }
    grammar delete
} {}

test schema-1.11 {define} {
    tdom::schema create grammar
    set result [catch {grammar define {
        element elm1
    }} errMsg]
    grammar delete
    lappend result $errMsg
} {1 {Command not allowed at top level in schema define evaluation}}

test schema-1.12 {define} {
    tdom::schema create grammar
    set result [catch {grammar define {
        defelement elm1 {
            element a
            element b
        }
        element elm1
    }} errMsg]
    grammar delete
    lappend result $errMsg
} {1 {Command not allowed at top level in schema define evaluation}}

test schema-1.13 {define lots of elements} {
    tdom::schema create s
    s define {
        defelement elm1 {
            for {set i 1} {$i <= 1000} {incr i} {
                element a$i ?
            }
        }
        for {set i 1} {$i <= 1000} {incr i} {
            defelement a$i {}
        }
    }
    s delete
} {}

test schema-1.14 {refer local element definition with element} {
    tdom::schema create s
    s define {
        defelement elm1 {
            element elm ! {
                element a ! {
                    text
                }
            }
        }
        defelement elm2 {
            element elm
        }
    }
    set result [list]
    foreach xml {
        <elm1><elm><a>foo</a></elm></elm1>
        <elm1><elm></elm></elm1>
        <elm2><elm><a>foo</a></elm></elm2>
        <elm2><elm></elm></elm2>
    } {
        lappend result [s validate $xml ]
    }
    s delete
    set result 
} {1 0 0 1}

test schema-1.14 {define start w/ namespace} {
    tdom::schema create s
    s start doc http://foo.bar
    s defelement doc http://foo.bar {
        element a
        element b
    }
    foreach elm {a b} {
        s defelement $elm http://foo.bar {}
    }
    set result [list]
    foreach xml {
        {<doc xmlns="http://foo.bar"><a/><b/></doc>}
        {<a:doc xmlns:a="http://foo.bar"><a:a/><a:b/></a:doc>}
        {<a:doc xmlns:a="http://foo.bar"><a xmlns="http://foo.bar"/><a:b/></a:doc>}
        {<doc><a/><b/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0}

test schema-1.14a {define start w/ namespace} {
    tdom::schema create s
    s prefixns {ns1 http://foo.bar}
    s start doc ns1
    s defelement doc ns1 {
        element a
        element b
    }
    foreach elm {a b} {
        s defelement $elm ns1 {}
    }
    set result [list]
    foreach xml {
        {<doc xmlns="http://foo.bar"><a/><b/></doc>}
        {<a:doc xmlns:a="http://foo.bar"><a:a/><a:b/></a:doc>}
        {<a:doc xmlns:a="http://foo.bar"><a xmlns="http://foo.bar"/><a:b/></a:doc>}
        {<doc><a/><b/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0}

test schema-1.15 {call structure constraint outside define/defelement} {
    set result [catch {tdom::schema::element foo} errMsg]
    lappend result $errMsg
    tdom::schema create grammar
    lappend result [catch {tdom::schema::element foo} errMsg]
    lappend result $errMsg
    lappend result [catch {grammar define {::tdom::schema::element foo}} errMsg]
    lappend result $errMsg
    lappend result [catch {grammar defelement bar {::tdom::schema::element foo}} errMsg]
    lappend result $errMsg
    grammar delete
    set result
} {1 {Command called outside of schema context} 1 {Command called outside of schema context} 1 {Command not allowed at top level in schema define evaluation} 0 {}}

test schema-1.16 {call another schema cmd in a schema definition script} {
    tdom::schema create s1
    s1 define {
        defelement s1a {
            element s1b *
            element s1c
        }
        ::tdom::schema ::s2
        s2 define {
            defelement s1a {
                element s1b *
                element s1c
            }
        }
        defelement s1b {
            element s1b1
        }
    }
    set result [list]
    foreach xml {
        <s1a/>
        <s1a><s1b/><s1c/></s1a>
        <s1a><s1c/></s1a>
        <s1a><s1b><s1b1/></s1b><s1c/></s1a>
    } {
        lappend result [s1 validate $xml]
        lappend result [s2 validate $xml]
    }
    s1 delete
    s2 delete
    set result
} {0 0 0 1 1 1 1 0}

test schema-1.17 {call schema cmd evaluation in his own schema definition script} {
    tdom::schema create s1
    set result [catch {s1 define {
        defelement s1a {
            s1 defelement s1b {
                element s1b1
            }
            element s1b *
            element s1c
        }
    }} errMsg]
    s1 delete
    set result
} 1

test schema-1.18 {delete schema cmd in definition script} {
    tdom::schema create s
    s define {
        defelement e {
            s delete
            element e1 1 {
                set ::result [catch {s delete}]
            }
        }
    }
    lappend result [info commands s]
} {1 {}}

test schema-1.19 {call top level schema cmd in definition script} {
    tdom::schema create s
    set result [catch {s define {
        defelement e {
            element e1 1 {
                deftexttype foo {minLength 1}
                defelement bar {}
            }
            element bar
        }
    }}]
    lappend result [info commands s]
    s delete
    set result
} {1 s}

test schema-1.20 {call top level schema cmd in definition script} {
    tdom::schema create s
    set result [catch {s defelement e {
            element e1 1 {
                deftexttype foo {minLength 1}
                defelement bar {}
            }
            element bar
        }
    }]
    lappend result [info commands s]
    s delete
    set result
} {1 s}

test schema-1.21 {Create other schema cmd in definition script} {
    tdom::schema create s1
    s1 defelement e {
        element e1 1 {}
        element e1 1 {
            ::tdom::schema create ::s2
            ::s2 define {
                defelement s2 {
                    element s2e
                    element s2ee
                }
                foreach e {s2e s2ee} {
                    defelement $e {text}
                }
            }
        }
    }
    set result [info commands s1]
    lappend result [info commands s2]
    foreach xml {
        <e><e1/><e1/></e>
        <s2><s2e>foo</s2e><s2ee/></s2>
    } {
        lappend result [s1 validate $xml]
        lappend result [s2 validate $xml]
    }
    s2 delete
    s1 delete
    set result
} {s1 s2 1 0 0 1}

test schema-1.22 {nrForwardDefinitions} {
    tdom::schema create s
    set result [list]
    s define {
        defelement e {
            lappend ::result [s info nrForwardDefinitions]
            element e1
            lappend ::result [s info nrForwardDefinitions]
            element e1
            lappend ::result [s info nrForwardDefinitions]
            element e2
            lappend ::result [s info nrForwardDefinitions]
        }
        foreach e {e1 e2} {
            defelement $e {text}
            lappend ::result [s info nrForwardDefinitions]
        }
    }
    s delete
    set result
} {0 1 1 2 1 0}

test schema-1.23 {prefixns} {
    tdom::schema create s
    set result [list]
    lappend result [s prefixns]
    lappend result [s prefixns {a b}]
    lappend result [s prefixns]
    lappend result [s prefixns {a b a b c d}]
    lappend result [s prefixns {}]
    lappend result [s prefixns ""]
    lappend result [catch {s prefixns a b c} errMsg]
    lappend result $errMsg
    lappend result [catch {s prefixns {a b c}} errMsg]
    lappend result $errMsg
    lappend result [catch {s prefixns "a \{"} errMsg]
    lappend result $errMsg
    s delete
    set result
} {{} {a b} {a b} {a b a b c d} {} {} 1 {wrong # args: should be "s prefixns ?prefixUriList?"} 1 {The optional argument to prefixns must be a 'prefix namespace' pairs list} 1 {The optional argument to prefixns must be a 'prefix namespace' pairs list}}

test schema-1.24 {prefixns} {
    tdom::schema create s
    set result [list]
    lappend result [s define prefixns]
    lappend result [s define {prefixns {a b}}]
    lappend result [s define {prefixns}]
    lappend result [s define {prefixns {a b a b c d}}]
    lappend result [s define {prefixns {}}]
    lappend result [s define {prefixns ""}]
    lappend result [catch {s define {prefixns a b c}} errMsg]
    lappend result $errMsg
    lappend result [catch {s define {prefixns {a b c}}} errMsg]
    lappend result $errMsg
    lappend result [catch {s define {prefixns "a \{"}} errMsg]
    lappend result $errMsg
    s delete
    set result
} {{} {a b} {a b} {a b a b c d} {} {} 1 {wrong # args: should be "prefixns ?prefixUriList?"} 1 {The optional argument to prefixns must be a 'prefix namespace' pairs list} 1 {The optional argument to prefixns must be a 'prefix namespace' pairs list}}

test schema-1.25 {prefixns} {
    set result [list]
    set schema {
        defelement doc ns1 {
            element e
        }
    }
    set xml {<doc xmlns="http://tdom.org/test"><e/></doc>}
    # 1
    tdom::schema create s
    s define $schema
    lappend result [s validate $xml]
    s delete
    # 2
    tdom::schema create s
    s prefixns {ns1 http://tdom.org/test}
    s define $schema
    lappend result [s validate $xml]
    s delete
    # 3
    tdom::schema create s
    s prefixns {ns1 http://foo.bar}
    s define $schema
    lappend result [s validate $xml]
    s delete
    # 4
    tdom::schema create s
    s prefixns {ns1 http://tdom.org/test ns1 http://foo.bar}
    s define $schema
    lappend result [s validate $xml]
    s delete
    # 5
    tdom::schema create s
    s prefixns {ns1 http://foo.bar ns1 http://tdom.org/test}
    s define $schema
    lappend result [s validate $xml]
    s delete
    # 6
    tdom::schema create s
    s prefixns {ns1 http://foo.bar}
    s prefixns {ns1 http://tdom.org/test ns1 http://foo.bar}
    s define $schema
    lappend result [s validate $xml]
    s delete
    # 7
    tdom::schema create s
    s define {
        prefixns {ns1 http://tdom.org/test}
        defelement doc ns1 {
            element e
        }
        prefixns {ns2 http://foo.bar}
        defelement e ns2 {text {minLength 1}}
    }
    lappend result [s validate $xml]
    s delete
    # 8
    tdom::schema create s
    s define {
        prefixns {ns1 http://tdom.org/test}
        defelement doc ns1 {
            namespace http://foo.bar {
                element e 
            }
        }
        prefixns {ns2 http://foo.bar}
        defelement e ns2 {text {minLength 1}}
    }
    lappend result [s validate $xml]
    # 9
    lappend result [s validate {<doc xmlns="http://tdom.org/test"><e xmlns="http://foo.bar"/></doc>}]
    # 10
    lappend result [s validate {<doc xmlns="http://tdom.org/test"><e xmlns="http://foo.bar">foo</e></doc>}]
    s delete
    # 11 
    tdom::schema create s
    s define {
        prefixns {ns1 http://tdom.org/test ns2 http://foo.bar}
        defelement doc ns1 {
            namespace ns2 {
                element e 
            }
        }
        prefixns {ns2 http://foo.bar}
        defelement e ns2 {text {minLength 1}}
    }
    lappend result [s validate $xml]
    # 12
    lappend result [s validate {<doc xmlns="http://tdom.org/test"><e xmlns="http://foo.bar"/></doc>}]
    # 13
    lappend result [s validate {<doc xmlns="http://tdom.org/test"><e xmlns="http://foo.bar">foo</e></doc>}]
    s delete
    set result
} {0 1 0 1 0 1 1 0 0 1 0 0 1}

test schema-1.26 {prefixns} {
    tdom::schema create s
    set result [list]
    lappend result [catch {
        s defelement doc {
            prefixns {a http://foo.bar}
            namespace a {
                element e
            }
        }
    } errMsg]
    lappend result $errMsg
    lappend result [catch {
        s defelement doc {
            namespace a {
                element e
            }
            prefixns {a http://foo.bar}
        }
    } errMsg]
    lappend result $errMsg
    lappend result [catch {
        s define {
            defelement doc {
                prefixns {a http://foo.bar}
                namespace a {
                    element e
                }
            }
        }
    } errMsg]
    lappend result $errMsg
    lappend result [catch {
        s define {
            defelement doc {
                s prefixns {a http://foo.bar}
                namespace a {
                    element e
                }
            }
        }
    } errMsg]
    lappend result $errMsg
    s delete
    set result
} {1 {Command only allowed at lop level} 1 {Command only allowed at lop level} 1 {Command not allowed in nested schema define script} 1 {This recursive call is not allowed}}

test schema-1.27 {prefixns} {
    tdom::schema create s
    s define {
        prefixns {a http:://some.uri}
        defelement doc a {}
    }
    set result [s validate {<b:doc xmlns:b="a"/>} errMsg]
    lappend result $errMsg
    s delete
    set result
} {0 {error "Unknown element" at line 1 character 20}}

test schema-1.28 {defelement} {
    tdom::schema s
    set result [catch {
        s defelement e {
            defelement a {
                element b
            }
        }
    }]
    s delete
    set result
} 1
        
test schema-1.29 {defelement} {
    tdom::schema s
    catch {
        s defelement e {
            element a 
            element b
            error "some"
        }
    }
    s defelement e {
        element a 
        element b
    }
    set result [list]
    foreach xml {
        <e/>
        <e><a/></e>
        <e><a/><b/></e>
        <e><a/><b/><b/></e>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0}

test schema-1.30 {recurive allowed element} {
    tdom::schema s
    s define {
        defelement doc {
            element n
        }
        defelement n {
            element n ?
        }
    }
    set xml "<doc>"
    # That's 200000 (and one) nesting level
    append xml [string repeat "<n><n><n><n><n><n><n><n><n><n>" 20000]
    append xml "<n/>"
    append xml [string repeat "</n></n></n></n></n></n></n></n></n></n>" 20000]
    append xml "</doc>"
    set result [s validate $xml]
    s delete
    set result
} 1

test schema-1.31 {recurive allowed element} {
    tdom::schema s
    s define {
        defelement doc {
            element n
        }
        defelement n {
            element n ?
        }
    }
    set xml "<doc>"
    # That's 200000 (and one) nesting level
    append xml [string repeat "<n><n><n><n><n><n><n><n><n><n>" 20000]
    append xml "<a/>"
    append xml [string repeat "</n></n></n></n></n></n></n></n></n></n>" 20000]
    append xml "</doc>"
    set result [s validate $xml errMsg]
    s delete
    list $result $errMsg
} {0 {error "Element "a" doesn't match" at line 1 character 600009}}

test schema-1.32 {Unknown root element} {
    tdom::schema s
    s define {
        defelement e {
            element doc ? {
                element e
            }
        }
    }
    set result [s validate <doc><e><doc><e/></doc></e></doc>]
    s delete
    set result
} 0

test schema-1.33 {Error after local defined element} {
    tdom::schema s
    set result [catch {
        s define {
            defelement a {
                element b ! {
                    element c ! {}
                    error "triggered"
                }
                element a ! {
                    element c ! {}
                }
                error
            }
        }
    }]
    s delete
    set result
} 1

test schema-1.34 {defelement nested in defelement nested in define} {
    tdom::schema s
    set result [catch {
        s define {
            defelement a {
                defelement b {
                    element c ! {}
                }
            }
        }
    } errMsg]
    s delete
    lappend result $errMsg
} {1 {Command not allowed in nested schema define script}}

test schema-1.35 {deftexttype nested in deftexttype nested in define} {
    tdom::schema s
    set result [catch {
        s define {
            deftexttype foo {
                minLength 2
                ::tdom::schema::deftexttype bar {
                    maxLength 2
                }
            }
        }
    } errMsg]
    s define {
        deftexttype foo {
            minLength 2
        }
        deftexttype bar {
            maxLength 2
        }
    }
    s delete
    lappend result $errMsg
} {1 {Command called in invalid schema context}}

test schema-2.1 {grammar definition: ref} {
    tdom::schema create grammar
    grammar defpattern thisPattern {
        element a
        element b
    }
    grammar defpattern thatPattern {
        element c
        element d
    }
    grammar defelement doc {
        ref thisPattern
        ref thatPattern ?
    }
    grammar delete
} {}

test schema-2.2 {grammar definition: ref} {
    tdom::schema create grammar
    set result [grammar info nrForwardDefinitions]
    grammar defelement doc {
        ref thisPattern
        ref thatPattern ?
    }
    lappend result [grammar info nrForwardDefinitions]
    grammar delete
    set result
} {0 2}

test schema-2.3 {forward defined ref} {
    set defs {
        {
            ref thisPattern ?
        }
        {
            ref thatPattern
        }
        {
            ref thisPattern ?
            ref thatPattern
        }
        {
            ref thisPattern ?
            element a
        }
        {
            ref thatPattern
            element a
        }
    }
    set xmlinput {
        <doc/>
        <doc><a/></doc>
        <doc><unknown/></doc>
    }
    set result [list]
    foreach def $defs {
        tdom::schema create s
        s defelement doc $def
        foreach xml $xmlinput {
            lappend result [s validate $xml errMsg]
        }
        s delete
    }
    set result
} {1 0 0 1 0 0 1 0 0 0 1 0 0 1 0}

test schema-2.3a {forward defined ref} {
    tdom::schema s
    s defelement doc {
        ref some
        element a
    }
    set result [s validate <doc><a/></doc>]
    lappend result [s info nrForwardDefinitions]
    s delete
    set result
} {1 2}

test schema-2.4 {forward definded element} {
    set defs {
        {
            element thisElement ?
        }
        {
            element thatElement
        }
        {
            element thisElement ?
            element thatElement
        }
        {
            element thisElement ?
            element a
        }
        {
            element thatElement
            element a
        }
    }
    set xmlinput {
        <doc/>
        <doc><a/></doc>
        <doc><unknown/></doc>
    }
    set result [list]
    foreach def $defs {
        tdom::schema create s
        s defelement doc $def
        foreach xml $xmlinput {
            lappend result [s validate $xml errMsg]
        }
        s delete
    }
    set result
} {1 0 0 0 0 0 0 0 0 0 1 0 0 0 0}

test schema-3.1 {grammar definition: choice} {
    tdom::schema create grammar
    grammar defelement doc {
        element elm
        choice {
            element fooElem
            element barElem +
        }
        choice ? {
            element one {2 3}
            element two
        }
        element three
    }
    grammar delete
} {}

test schema-3.2 {grammar definition: choice} {
    tdom::schema create grammar
    grammar defpattern thisPattern {
        element elm
        choice {
            element fooElem
            element barElem +
        }
        choice ? {
            element one {2 3}
            element two
        }
        element three
    }
    grammar delete
} {}

proc pullValidate {g xml} {
    tdom::pullparser pp
    pp input $xml
    while {[pp next] ne "END_DOCUMENT"} {
        switch [pp state] {
            "START_TAG" {
                $g event start [pp tag]
            }
            "END_TAG" {
                $g event end
            }
            "TEXT" {
                $g event text [pp text]
            }
        }
    }
}

test schema-4.1 {validation} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    pullValidate grammar {
        <doc><e1/></doc>
    }
    if {[grammar info vstate] ne "FINISHED"} {
        error "Wrong state."
    }
    grammar reset
    pullValidate grammar {
        <doc><e1/><e2/></doc>
    }
    if {[grammar info validationstate] ne "FINISHED"} {
        error "Wrong state."
    }
    grammar reset
    pullValidate grammar {
        <doc><e1/><e2/><e2/><e2/></doc>
    }
    if {[grammar info vstate] ne "FINISHED"} {
        error "Wrong state."
    }
    grammar delete
} {}

test schema-4.1a {validation} {
    tdom::schema create s
    s defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        s defelement $e {}
    }
    set result [list]
    foreach xml {
        <doc><e1/></doc>
        <doc><e1/><e2/></doc>
        <doc><e1/><e2/><e2/><e2/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1}

test schema-4.2 {validation} {
    tdom::schema create s
    s defelement doc {
        element e1 *
    }
    s defelement e1 {
        element ee1
        element ee2
    }
    foreach e {ee1 ee2} {
        s defelement $e {}
    }
    set result [list]
    foreach xml {
        <doc></doc>
        <doc><e1/></doc>
        <doc><e1><ee1/><ee2/></e1></doc>
        <doc><e1><ee1/><ee2/></e1><e1><ee1/><ee2/></e1><e1><ee1/><ee2/></e1></doc>
        <doc><e1><ee1/><ee2/></e1><e1><ee1/><ee2/><unknown/></e1></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 0 1 1 0}

test schema-4.3 {validation} {
    tdom::schema s 
    s define {
        defelement addressBook {
            element card *
        }
        defelement card {
            element name
            element email
        }
        foreach e {name email} {
            defelement $e {text}
        }
    }
    set result [s validate {
<addressBook>
  <card>
    <name>John Smith</name>
    <email>js@example.com</email>
  </card>
  <card>
    <name>Fred Bloggs</name>
    <email>fb@example.net</email>
  </card>
</addressBook>        
    }]
    s delete
    set result
} 1

proc schema-4.4 {scmd} {
    global result
    catch {$scmd event start foo} errMsg
    lappend result $errMsg
}

test schema-4.4 {event on itself in called script} {
    tdom::schema s
    s defelement doc {
        element a ?
        tcl schema-4.4 [self]
        element b ?
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {{This method is not allowed in nested evaluation} 1 {This method is not allowed in nested evaluation} 1 {This method is not allowed in nested evaluation} 1}

proc schema-4.5 {scmd} {
    global result
    $scmd event start foo
}

test schema-4.5 {event on itself in called script} {
    tdom::schema s
    s defelement doc {
        element a ?
        tcl schema-4.5 [self]
        element b ?
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><b/></doc>
    } {
        lappend result [catch {s validate $xml errMsg} errMsg]
        lappend result $errMsg
    }
    s delete
    set result
} {1 {error "This method is not allowed in nested evaluation" at line 1 character 6} 1 {error "This method is not allowed in nested evaluation" at line 1 character 15} 1 {error "This method is not allowed in nested evaluation" at line 1 character 13}}

test schema-4.6 {event start with namespace} {
    tdom::schema s
    s defelement doc http://tdom.org/test {
        element a ! text
    }
    s event start doc http://tdom.org/test
    s event start a http://tdom.org/test
    s event text "some text"
    s event end
    s event end
    s delete
} {}

test schema-4.7 {event start with namespace} {
    tdom::schema s
    s defelement doc http://tdom.org/test {
        element a 1 {
            attribute att1
        }
    }
    s event start doc http://tdom.org/test
    set result [catch {s event start a http://tdom.org/test} errMsg]
    lappend result $errMsg
    s delete
    set result
} {1 {Missing mandatory attribute(s)}}

test schema-4.8 {event start with namespace} {
    tdom::schema s
    s defelement doc http://tdom.org/test {
        element a 1 {
            attribute att1
        }
    }
    s event start doc http://tdom.org/test
    s event start a {att1 "some data"} http://tdom.org/test
    s event end
    s event end
    s delete
} {}

test schema-4.9 {event start with namespace w/ namespaced attribute} {
    tdom::schema s
    s defelement doc http://tdom.org/test {
        element a 1 {
            nsattribute att1 http://tdom.org/test
        }
    }
    s event start doc http://tdom.org/test
    s event start a {{att1 http://tdom.org/test} "some data"} http://tdom.org/test
    s event end
    s event end
} {}

proc schema-4.10 {scmd} {
    error "Error raised in schema-4.10"
}
test schema-4.10 {event - tcl error in called script} {
    tdom::schema s
    s defelement doc {
        tcl schema-4.10 [self]
        element a
    }
    s event start doc 
    set result [catch {s event start a} errMsg]
    lappend result $errMsg
    s delete
    set result
} {1 {Error raised in schema-4.10}}

test schema-4.11 {event - invalid root} {
    tdom::schema s
    s defelement doc {}
    s reportcmd dummycallback
    s event start doo
    s delete
} {}

test schema-4.12 {event - text without root} {
    tdom::schema s
    s defelement doc {}
    s reportcmd dummycallback
    set result [catch {s event text foo} errMsg]
    lappend result $errMsg
    s delete
    set result
} {1 {No validation started}}

test schema-5.1 {dom parse -validateCmd} {
    set result [catch {
        [dom parse -validateCmd tdom::schema <doc/>]
    }]
} 1

test schema-5.2 {dom parse -validateCmd} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    dom parse -validateCmd grammar {
        <doc><e1/></doc>
    } doc
    $doc delete
    dom parse -validateCmd grammar {
        <doc><e1/><e2/></doc>
    } doc
    $doc delete
    dom parse -validateCmd grammar {
        <doc><e1/><e2/><e2/><e2/></doc>
    } doc
    $doc delete
} {}

proc schema-5.3 {base systemId publicId} {
    return [list "string" "" "<foo/>"]
}

test schema-5.3 {dom parse -validateCmd} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    set result [catch {dom parse -validateCmd grammar \
                           -externalentitycommand schema-5.3 {
                               <!DOCTYPE doc [
                                              <!ENTITY e1 PUBLIC "e1" "e1.xml">
                                             ]>
                                   <doc>&e1;</doc>} doc} errMsg]
    grammar delete
    set result
} 1

test schema-5.4 {define} {
    tdom::schema create grammar
    grammar define {
        defelement elm1 {
            element a
            element b
        }
        defelement a {
            element c
        }
        defelement b {}
        defelement c {}
    }
    set doc [dom parse -validateCmd grammar {
        <elm1><a><c/></a><b/></elm1>
    }]
    $doc delete
    grammar delete
} {}

test schema-5.5 {validate tmml doc files} {
    tdom::schema s
    set docdir [file join [file dir [info script]] ../doc]
    set file [file join $docdir tmml.schema]
    set fd [open $file]
    set tmmlschema [read $fd]
    close $fd
    s define $tmmlschema
    set result {}
    foreach tmmlfile {
        domDoc.xml
        domNode.xml
        dom.xml
        expatapi.xml
        expat.xml
        pullparser.xml
        schema.xml
        tdomcmd.xml
    } {
        set file [file join $docdir $tmmlfile]
        set fd [open $file]
        set tmmldoc [read $fd]
        close $fd
        lappend result [s validate $tmmldoc]
    }
    s delete
    set result
} {1 1 1 1 1 1 1 1}

test schema-6.1 {expat parser with -validateCmd} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    ::xml::parser p -validateCmd grammar
    set result [catch {p parse {<doc><e2/></doc>}} errMsg]
    p delete
    grammar delete
    set result
} 1

test schema-6.2 {expat parser with -validateCmd} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    ::xml::parser p -validateCmd grammar -final 0
    set result [list]
    p parse {<doc><e}
    lappend result [catch {grammar validate <doc><e1/><e2/><e2/></doc>} errMsg]
    lappend result $errMsg
    lappend result [grammar info vstate]
    p parse {1/></doc>}
    p configure -final 1
    p reset
    lappend result [grammar validate <doc><e1/><e2/><e2/></doc>]
    grammar delete
    p delete
    set result
} {1 {The schema command is busy} VALIDATING 1}

test schema-6.3 {expat parser with -validateCmd} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    ::xml::parser p -validateCmd grammar -final 0
    set result [list]
    p parse {<do}
    lappend result [catch {grammar validate <doc><e1/><e2/><e2/></doc>} errMsg]
    lappend result $errMsg
    lappend result [grammar info vstate]
    p parse {c><e1/></doc>}
    p configure -final 1
    p reset
    lappend result [grammar validate <doc><e1/><e2/><e2/></doc>]
    grammar delete
    p delete
    set result
} {0 1 READY 1}

test schema-6.4 {expat parser with -validateCmd} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    ::xml::parser p -validateCmd grammar -final 0
    set result [list]
    p parse {<do}
    lappend result [catch {grammar validate <doc><e1/><e2/><e2/></doc>} errMsg]
    lappend result $errMsg
    lappend result [grammar info vstate]
    p parse {c}
    p parse {><e1/></doc>}
    p configure -final 1
    p reset
    lappend result [grammar validate <doc><e1/><e2/><e2/></doc>]
    grammar delete
    p delete
    set result
} {0 1 READY 1}

proc elementstart-6.5 {name attList} {
    lappend ::result $name
}

test schema-6.5 {expat parser with -validateCmd} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    ::xml::parser p -validateCmd grammar -final 0\
        -elementstartcommand elementstart-6.5
    set result [list]
    p parse {<do}
    p parse {c}
    p parse {><e1/></doc>}
    p configure -final 1
    p reset
    lappend result [grammar validate <doc><e1/><e2/><e2/></doc>]
    grammar delete
    p delete
    set result
} {doc e1 1}

proc elementstart-6.6 {name attList} {
    lappend ::result $name
    if {$name eq "doc"} {
        grammar delete
    }
}

test schema-6.6 {expat parser with -validateCmd} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    ::xml::parser p -validateCmd grammar -final 0\
        -elementstartcommand elementstart-6.6
    set result [list]
    p parse {<do}
    p parse {c}
    p parse {><e1/></doc>}
    p configure -final 1
    p reset
    lappend result [info command grammar]
    p delete
    set result
} {doc e1 {}}

test schema-7.1 {group} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        group ! {
            element e1
            element e2
        }
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    dom parse -validateCmd grammar {
        <doc><e1/><e1/><e2/><e2/><e2/><e2/></doc>
    } doc
    $doc delete
    grammar delete
} {}

test schema-7.1.1 {group} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            element e1
            group ! {
                element e1
                element e2
            }
            group ! {
                element e1
                element e2
            }
            element e2 *
        }
        foreach e {e1 e2} {
            defelement $e {}
        }
    }
    dom parse -validateCmd grammar {
        <doc><e1/><e1/><e2/><e1/><e2/><e2/><e2/><e2/></doc>
    } doc
    $doc delete
    grammar delete
} {}

test schema-7.2 {group} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        group 2 {
            element e1
            element e2
        }
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    dom parse -validateCmd grammar {
        <doc><e1/><e1/><e2/><e1/><e2/><e2/><e2/><e2/></doc>
    } doc
    $doc delete
    grammar delete
} {}

test schema-7.2.1 {group} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            element e1
            group 2 {
                element e1
                element e2
            }
            element e2 *
        }
        foreach e {e1 e2} {
            defelement $e {}
        }
    }
    dom parse -validateCmd grammar {
        <doc><e1/><e1/><e2/><e1/><e2/><e2/><e2/><e2/></doc>
    } doc
    $doc delete
    grammar delete
} {}

test schema-7.3 {group with inline defined element} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            element e1
            group 2 {
                element e1 1 {
                    element e2
                }
                element e2
            }
            element e2 *
        }
        foreach e {e1 e2} {
            defelement $e {}
        }
    }
    dom parse -validateCmd grammar {
        <doc><e1/><e1><e2/></e1><e2/><e1><e2/></e1><e2/><e2/><e2/><e2/></doc>
    } doc
    $doc delete
    grammar delete
} {}

test schema-7.4 {group with inline defined element} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group {
                element e1
                element e1 1 {
                    element e2
                }
                element e2
            }
        }
        foreach e {e1 e2} {
            defelement $e {}
        }
    }
    dom parse -validateCmd grammar {
        <doc><e1/><e1><e2/></e1><e2/></doc>
    } doc
    $doc delete
    grammar delete
} {}

test schema-7.5 {group with inline defined element} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group {
                element e1
                element e1 1 {
                    element e2
                }
                element e2
            }
        }
        foreach e {e1 e2} {
            defelement $e {}
        }
    }
    ::xml::parser p -validateCmd grammar
    p parse {
        <doc><e1/><e1><e2/></e1><e2/></doc>
    }
    p delete
    grammar delete
} {}

test schema-7.6 {nested groups via refs} {
    tdom::schema create grammar
    grammar define {
        defpattern a foouri {
            group {
                element e1
                element e1 1 {
                    element e2
                }
                element e2
            }
            element e3 ?
        }
        defpattern b foouri {
            element b1 3
            group 3 {
                element b2
                ref a
            }
        }
        foreach e {e1 e2 e3 b1 b2} {
            defelement $e foouri {}
        }
        defelement doc foouri {
            group {
                ref a
                ref b 
            }
        }
    }
    set result [grammar validate {
         <doc xmlns="foouri">
           <!-- ref a start -->
           <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <e3/>
           <!-- ref a end -->
           <!-- ref b start -->
           <b1/>
           <b1/>
           <b1/>
           <b2/>
           <!-- inside ref b: ref a start -->
           <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <!-- inside ref b: ref a end -->
           <b2/>
           <!-- inside ref b: ref a start -->
           <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <!-- inside ref b: ref a end -->
           <b2/>
           <!-- inside ref b: ref a start -->
           <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <!-- inside ref b: ref a end -->
           <!-- ref b end -->
         </doc>
    }]
    grammar delete
    set result
} 1

test schema-7.7 {nested groups via refs} {
    tdom::schema create grammar
    grammar define {
        defpattern a  {
            group {
                element e1
                element e1 1 {
                    element e2
                }
                element e2
            }
            element e3 ?
        }
        defpattern b  {
            element b1 *
            group 1 {
                element b2
                ref a
            }
        }
        foreach e {e1 e2 e3 b1 b2} {
            defelement $e  {}
        }
        defelement doc  {
            group 2 {
                ref b
            }
        }
    }
    set doc [dom parse -validateCmd grammar {
         <doc>
           <!-- ref b start -->
        <b2/>
        <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <e3/>
           <!-- inside ref b: ref a end -->
           <!-- inside ref b: ref a start -->
        <b2/>
        <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <e3/>
           <!-- inside ref b: ref a end -->
           <!-- ref b end -->
         </doc>
    }]
    $doc delete
    set result [grammar validate {
         <doc>
           <!-- ref b start -->
           <b2/>
           <!-- inside ref b: ref a start -->
           <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <e3/>
           <!-- inside ref b: ref a end -->
           <!-- inside ref b: ref a start -->
        <b2/>
        <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <e3/>
           <!-- inside ref b: ref a end -->
           <!-- ref b end -->
         </doc>
    } msg]
    grammar delete
    set result
} 1

test schema-7.8 {nested groups via refs} {
    tdom::schema create grammar
    grammar define {
        defpattern a foouri {
            group {
                element e1
                element e1 1 {
                    element e2
                }
                element e2
            }
            element e3 ?
        }
        foreach e {e1 e2 e3 b1 b2} {
            defelement $e foouri {}
        }
        defelement doc foouri {
            group {
                ref a
            }
        }
    }
    set doc [dom parse -validateCmd grammar {
         <doc xmlns="foouri">
           <!-- ref a start -->
           <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <e3/>
           <!-- ref a end -->
         </doc>
    }]
    $doc delete
    grammar delete
} {}

test schema-7.9 {loop over seq} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group * {
                element a
                element b
            }
            element c
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [grammar validate <doc><c/></doc>]
    grammar delete
    set result
} 1

test schema-7.10 {loop over seq} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group {
                element a
                element b
            }
            element c
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [grammar validate <doc><c/></doc>]
    grammar delete
    set result
} 0

test schema-7.10a {loop over seq} {
    tdom::schema create grammar
    set result [catch {grammar define {
        defelement doc {
            group 2 {
                element a
                element b
            }
            element c
            foreach e {a b c} {
                defelement $e {}
            }
        }
    }}]
    grammar delete
    set result
} 1

test schema-7.10b {loop over seq} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group {
                element a
                element b
            }
            element c
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [grammar validate <doc><a/></b><c/></doc> errMsg]
    grammar delete
    set result
} 0

test schema-7.10c {loop over seq} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group {
                element a
                element b
            }
            element c
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [catch {
        set doc [dom parse -validateCmd grammar <doc><a/></b><c/></doc>]
    }]
    grammar delete
    set result
} 1

test schema-7.11 {loop over seq} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group * {
                element a
                element b
            }
            element c
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc><c/></doc>
        <doc><a/><b/><c/></doc>
        <doc><a/><b/><a/><b/><c/></doc>
        <doc><a/><b/><a/><b/></doc>
    } {
        lappend result [grammar validate $xml]
    }
    grammar delete
    set result
} {1 1 1 0}

test schema-7.11b {loop over seq} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group 2 {
                element a ?
                element b ?
            }
            element c
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc><c/></doc>
        <doc><a/><b/><c/></doc>
        <doc><a/><b/><a/><b/><c/></doc>
        <doc><a/><b/><a/><b/></doc>
    } {
        lappend result [grammar validate $xml]
    }
    grammar delete
    set result
} {1 1 1 0}

test schema-7.12 {loop over seq} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group {
                element a
                element b
            }
            element c
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [grammar validate <doc><c/></doc> errMsg]
    lappend result [grammar validate <doc><a/><b/><c/><d/></doc>]
    lappend result [grammar validate <doc><a/><b/><c/></doc>]
    lappend result [grammar validate <doc><a/><b/><a/><b/><c/></doc>]
    lappend result [grammar validate <doc><a/><b/></doc>]
    grammar delete
    set result
} {0 0 1 0 0}

test schema-7.13 {long sequence} {
    tdom::schema create s
    s define {
        defelement doc {
            for {set i 1} {$i < 200} {incr i} {
                element e$i
            }
        }
        for {set i 1} {$i < 200} {incr i} {
            defelement e$i {element a}
        }
        defelement a {}
    }
    set xml "<doc>"
    for {set i 1} {$i < 200} {incr i} {
        append xml "<e$i><a/></e$i>"
    }
    append xml "</doc>"
    set result [s validate $xml]
    s delete
    set result
} 1


test schema-7.14 {mixed} {
    tdom::schema create s
    s define {
        defelement doc {
            mixed {
                element a
                element b
            }
        }
        foreach e {a b} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc></doc>
        <doc>text</doc>
        <doc>text<a/></doc>
        <doc><a/></doc>
        <doc>some<a/><b/></doc>
        <doc>some<a/><unknown/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 1 1 0}

test schema-7.14a {mixed} {
    tdom::schema create s
    s define {
        defelement doc {
            mixed ! {
                element a
                element b
            }
        }
        foreach e {a b} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc>text</doc>
        <doc>text<a/></doc>
        <doc><a/></doc>
        {<doc><b/>to much</doc>}
        <doc>some<a/><b/></doc>
        <doc><unknown/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 0 1 0 0 0}

test schema-7.14b {mixed} {
    tdom::schema create s
    s define {
        defelement doc {
            mixed ! {
                element a *
                element b
            }
        }
        foreach e {a b} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc>text</doc>
        <doc>text<a/></doc>
        <doc><a/></doc>
        <doc><a/><a/><a/></doc>
        <doc><b/></doc>
        {<doc><b/>to much</doc>}
        <doc><b/><b/></doc>
        <doc>some<a/><b/></doc>
        <doc><unknown/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 0 1 1 1 0 0 0 0}

test schema-7.15 {choice with optional choices} {
    tdom::schema create s
    s define {
        defelement doc {
            choice {
                element a *
                element b *
            }
            element c
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><c/></doc>
        <doc><a/><a/><a/></doc>
        <doc><a/><a/><a/><c/></doc>
        <doc><b/><b/><b/><c/></doc>
        <doc><c/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 1 1 1}

test schema-7.15a {choice with optional choices} {
    tdom::schema create s
    s define {
        defelement doc {
            choice {
                element a *
                element b *
            }
        }
        foreach e {a b} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><c/></doc>
        <doc><a/><a/><a/></doc>
        <doc><a/><a/><a/><c/></doc>
        <doc><b/><b/><b/><c/></doc>
        <doc><b/><b/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 0 1 0 0 1}

test schema-7.15b {choice with optional choices} {
    tdom::schema create s
    s define {
        defelement doc {
            choice {
                element a *
                element b
            }
        }
        foreach e {a b} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><c/></doc>
        <doc><a/><a/><a/></doc>
        <doc><a/><a/><a/><c/></doc>
        <doc><b/><b/><b/><c/></doc>
        <doc><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 0 1 0 0 1}

test schema-7.16 {choice with optional choices} {
    tdom::schema create s
    s define {
        defelement doc {
            choice {
                element a *
                group * {
                    element aa
                    element ab ?
                }
            }
            element c
        }
        foreach e {a aa ab c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><c/></doc>
        <doc><a/><a/><a/></doc>
        <doc><a/><a/><a/><c/></doc>
        <doc><aa/><c/></doc>
        <doc><aa/><ab/><aa/><c/></doc>
        <doc><aa/><ab/><aa/><aa/><ab/><c/></doc>
        <doc><c/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 1 1 1 1 1}

test schema-7.17 {choice with optional choices} {
    tdom::schema create s
    s define {
        defelement doc {
            choice {
                element a *
                group {
                    element aa
                    element ab ?
                }
            }
            element c
        }
        foreach e {a aa ab c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><c/></doc>
        <doc><a/><a/><a/></doc>
        <doc><a/><a/><a/><c/></doc>
        <doc><aa/><c/></doc>
        <doc><aa/><ab/><aa/><c/></doc>
        <doc><aa/><ab/><aa/><aa/><ab/><c/></doc>
        <doc><c/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 1 1 0 0 1}

test schema-7.18 {choice} {
    tdom::schema create s
    s define {
        defelement doc {
            choice {
                element a
                group {
                    element aa
                    element ab ?
                }
            }
            element c
        }
        foreach e {a aa ab c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><c/></doc>
        <doc><a/><a/><a/></doc>
        <doc><a/><a/><a/><c/></doc>
        <doc><aa/><c/></doc>
        <doc><aa/><ab/><aa/><c/></doc>
        <doc><aa/><ab/><aa/><aa/><ab/><c/></doc>
        <doc><c/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 0 1 0 0 0}

test schema-7.19 {choice with quantified choice} {
    tdom::schema create s
    s define {
        defelement doc {
            choice {
                element a {0 2}
                group {
                    element aa
                    element ab ?
                }
            }
            element c
        }
        foreach e {a aa ab c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><c/></doc>
        <doc><a/><a/><c/></doc>
        <doc><a/><a/></doc>
        <doc><a/><a/><a/></doc>
        <doc><a/><a/><a/><c/></doc>
        <doc><aa/><c/></doc>
        <doc><aa/><ab/><aa/><c/></doc>
        <doc><aa/><ab/><aa/><aa/><ab/><c/></doc>
        <doc><c/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 1 0 0 0 1 0 0 1}

test schema-7.20 {group with only optional content} {
    tdom::schema create s
    s define {
        defelement doc {
            element a
            group {
                element b ?
                element c ?
            }
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><c/></doc>
        <doc><a/><a/><c/></doc>
        <doc><a/><b/></doc>
        <doc><a/><b/><c/></doc>
        <doc><b/><c/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 0 1 1 0}

test schema-7.21 {group with only optional content} {
    set def {
        group + {
            element c ?
            element a ?
            element b ?
        }
        element d
    }
    set result [list]
    tdom::schema s
    s defelement doc $def
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><c/><d/></doc>
        <doc><c/><d/></doc>
        <doc><a/><a/><c/><d/></doc>
        <doc><a/><b/><d/></doc>
        <doc><a/><b/><c/><d/></doc>
        <doc><b/><c/><d/></doc>
        <doc><d/></doc>
        <doc><d/><d/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 1 1 1 1 1 1 0}

test schema-7.22 {Constraint text content in seq} {
    tdom::schema s
    s defelement doc {
        element a
        text {
            minLength 4
        }
        element b
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/>1234<b/></doc>
        <doc><a/>123<b/></doc>
        <doc><a/>12345<b/></doc>
        {<doc><a/>    <b/></doc>}
        {<doc>  <a/>    <b/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 0 1 0 0}

test schema-7.23 {Whitespace in implicit defined element} {
    tdom::schema s
    s defelement doc {
        element a
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a></a></doc>
        {<doc>  <a></a></doc>}
        {<doc>  <a></a>  </doc>}
        {<doc>  <a>  </a>  </doc>}
        {<doc><a>12</a></doc>}
        {<doc><a>  </a></doc>}
        {<doc><a/>    <b/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 0 0 0 0}

test schema-7.23a {Whitespace in implicit defined element} {
    tdom::schema s
    s defelement doc {
        element a
    }
    set result [list]
    foreach xml {
        {<doc><a>  </a></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0}

test schema-8.1 {validate method} {
    tdom::schema create grammar
    grammar defelement doc {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e {}
    }
    set result [grammar validate <doc><e1/></doc>]
    lappend result [grammar validate <doc><e1/><e1/></doc> errMsg]
    lappend result [grammar validate <doc><e1/><e2/></doc> errMsg]
    lappend result [grammar validate <doc><e1/><e2/><e2/><e2/></doc> errMsg]
    lappend result [grammar validate <doc><e1/><e2/><e2/><e1/></doc> errMsg]
    grammar delete
    set result
} {1 0 1 1 0}

test schema-8.2 {validate method} {
    tdom::schema create grammar
    grammar defelement doc foouri {
        element e1
        element e2 *
    }
    foreach e {e1 e2} {
        grammar defelement $e foouri {}
    }
    set result [grammar validate {<doc xmlns="foouri"><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e1/></doc>} errMsg]
    grammar delete
    set result
} {1 0}

test schema-8.3 {validate method: white space between elements} {
    tdom::schema create grammar
    grammar define {
        defpattern a  {
            group {
                element e1
                element e1 1 {
                    element e2
                }
                element e2
            }
            element e3 ?
        }
        defpattern b  {
            element b1 *
            group 2 {
                element b2
                ref a
            }
        }
        foreach e {e1 e2 e3 b1 b2} {
            defelement $e  {}
        }
        defelement doc  {
            group {
                ref b
            }
        }
    }
    set result [grammar validate {
         <doc>
           <!-- ref b start -->
           <b2/>
           <!-- inside ref b: ref a start -->
           <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <e3/>
           <!-- inside ref b: ref a end -->
           <!-- inside ref b: ref a start -->
        <b2/>
        <e1/>
           <e1>
             <e2/>
           </e1>
           <e2/>
           <e3/>
           <!-- inside ref b: ref a end -->
           <!-- ref b end -->
         </doc>
    } msg]
    grammar delete
    set result
} 1

test schema-8.4 {illegal text} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group * {
                element a
                element b
            }
            element c
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [grammar validate <doc><a/><b/>wrong<c/></doc> errMsg]
    grammar delete
    set result
} 0

test schema-8.5 {illegal text - expat not signaling XML_STATUS_SUSPENDED although XML_StopParser() was called in handler, again.} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            group * {
                element a
                element b
            }
            element c
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [grammar validate <doc><a/><b/>wrong<c/></doc> errMsg]
    grammar delete
    set result
} 0

test schema-8.6 {} {
    tdom::schema create s
    s define {
        defelement doc {}
    }
    set result [s validate <doc/>]
    lappend result [s validate <wrong/>]
    s start mydoc
    lappend result [s validate <doc/>]
    s delete
    set result
} {1 0 0}

proc schema-8.7 {scmd} {
    global result
    lappend result "in schema-8.7"
    $scmd delete
    error "this is deliberate"
}
test schema-8.7 {Delete schema cmd in script called by validation} {
    set result ""
    lappend result [info commands s]
    tdom::schema s
    lappend result [info commands s]
    s defelement doc {
        tcl schema-8.7 [self]
    }
    lappend result [catch {s validate <doc/>} errMsg]
    lappend result $errMsg
    lappend result [info commands s]
    lappend result [catch {s delete}]
} {{} s {in schema-8.7} 1 {error "this is deliberate" at line 1 character 6} {} 1}

test schema-9.1 {choice} {
    tdom::schema create grammar
    grammar define {
        defelement doc foouri {
            choice * {
                element e1
                element e2
            }
        }
        foreach e {e1 e2} {
            defelement $e foouri {}
        }
    }
    set result [grammar validate {<doc xmlns="foouri"/>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e2/><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e1/><e2/><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e1/><e2/><e1/><e2/><e2/></doc>}]
    grammar delete
    set result
} {1 1 1 1 1 1}

test schema-9.2 {group} {
    tdom::schema create grammar
    grammar define {
        defelement doc foouri {
            group {
                element e1
                element e2 *
            }
        }
        foreach e {e1 e2} {
            defelement $e foouri {}
        }
    }
    set result [grammar validate {<doc xmlns="foouri"/>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e2/><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e1/><e2/><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e1/><e2/><e1/><e2/><e2/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e2/><e2/></doc>}]
    grammar delete
    set result
} {0 1 0 0 0 0 1}

test schema-9.3 {choice} {
    tdom::schema create grammar
    grammar define {
        defelement doc foouri {
            choice * {
                element e1
                group {
                    element e2
                    element e3
                }
            }
        }
        foreach e {e1 e2} {
            defelement $e foouri {}
        }
    }
    set result [grammar validate {<doc xmlns="foouri"/>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e2/><e3/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e2/><e3/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e2/><e3/><e2/><e3/><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e2/><e2/></doc>}]
    grammar delete
    set result
} {1 1 1 1 1 1 0}

test schema-9.4 {choice} {
    tdom::schema create grammar
    grammar define {
        defelement doc foouri {
            choice 2 {
                element e1
                group {
                    element e2
                    element e3
                }
            }
        }
        foreach e {e1 e2 e3} {
            defelement $e foouri {}
        }
    }
    set result [grammar validate {<doc xmlns="foouri"/>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e2/><e3/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e2/><e3/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e2/><e3/><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e1/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e2/><e3/><e2/><e3/></doc>}]
    lappend result [grammar validate {<doc xmlns="foouri"><e1/><e2/><e2/></doc>}]
    grammar delete
    set result
} {0 0 0 1 1 1 1 0}

test schema-9.5 {choice as choice child} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            choice {
                element e1
                element e2
                choice {
                    element e2
                    element e3
                }
            }
        }
        foreach e {e1 e2 e3} {
            defelement $e foouri {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><e1/></doc>
        <doc><e2/><e3/></doc>
        <doc><e2/></doc>
        <doc><e3/></doc>
        <doc><e4></doc>
    } {
        lappend result [grammar validate $xml]
    }
    grammar delete
    set result
} {0 1 0 1 1 0}

test schema-9.6 {mixed as choice child} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            choice {
                element e1
                element e2
                mixed {
                    element e2
                    element e3
                }
            }
        }
        foreach e {e1 e2 e3} {
            defelement $e foouri {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><e1/></doc>}
        {<doc><e2/><e3/></doc>}
        {<doc><e2/></doc>}
        {<doc><e3/></doc>}
        {<doc><e4></doc>}
    } {
        lappend result [grammar validate $xml]
    }
    grammar delete
    set result
} {1 1 0 1 1 0}

test schema-9.7 {choice as mixed child} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            mixed {
                element e1
                element e2
                choice {
                    element e2
                    element e3
                }
            }
        }
        foreach e {e1 e2 e3} {
            defelement $e foouri {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><e1/></doc>}
        {<doc><e2/><e3/></doc>}
        {<doc><e2/></doc>}
        {<doc><e3/></doc>}
        {<doc><e4></doc>}
    } {
        lappend result [grammar validate $xml]
    }
    grammar delete
    set result
} {1 1 1 1 1 0}

test schema-9.8 {choice as choice child} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            choice {
                element e1
                element e2
                choice 2 {
                    element e3
                    element e4
                }
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><e1/></doc>}
        {<doc><e2/><e3/></doc>}
        {<doc><e2/></doc>}
        {<doc><e3/><e3/></doc>}
        {<doc><e4/><e3/></doc>}
        {<doc><e4></doc>}
    } {
        lappend result [grammar validate $xml]
    }
    grammar delete
    set result
} {0 1 0 1 1 1 0}

test schema-9.9 {choice with optional cp belong the choices} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            element e1
            choice {
                element e2
                element e3 ?
            }
            element e4 ?
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><e1/></doc>}
        {<doc><e1/><e2/></doc>}
        {<doc><e1/><e3/></doc>}
        {<doc><e1/><e4/></doc>}
        {<doc><e1/><e2/><e4/></doc>}
        {<doc><e1/><e3/><e4/></doc>}
    } {
        lappend result [grammar validate $xml]
    }
    grammar delete
    set result
} {0 1 1 1 1 1 1}

test schema-9.10 {choice with may choices} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            element e1
            choice * {
                for {set i 1} {$i <= 20} {incr i} {
                    element ee$i
                }
            }
            element e2 ?
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><e1/></doc>}
        {<doc><e1/><e2/></doc>}
        {<doc><e1/><ee3/></doc>}
        {<doc><e1/><ee4/></doc>}
        {<doc><e1/><e2/><ee4/></doc>}
        {<doc><e1/><ee2/><e2/></doc>}
    } {
        lappend result [grammar validate $xml]
    }
    grammar delete
    set result
} {0 1 1 1 1 0 1}

test schema-9.11 {choice with may choices} {
    tdom::schema create grammar
    grammar define {
        defelement doc {
            element e1
            choice * {
                for {set i 1} {$i <= 20} {incr i} {
                    namespace foo {
                        element ee$i
                    }
                    element ee$i
                }
            }
            element e2 ?
        }
    }
    set result [list]
    foreach xml {
        {<doc xmlns:foo="foo"/>}
        {<doc xmlns:foo="foo"><e1/></doc>}
        {<doc xmlns:foo="foo"><e1/><e2/></doc>}
        {<doc xmlns:foo="foo"><e1/><ee3/></doc>}
        {<doc xmlns:foo="foo"><e1/><foo:ee4/></doc>}
        {<doc xmlns:foo="foo"><e1/><e2/><ee4/></doc>}
        {<doc xmlns:foo="foo"><e1/><foo:ee2/><e2/></doc>}
    } {
        lappend result [grammar validate $xml]
    }
    grammar delete
    set result
} {0 1 1 1 1 0 1}

test schema-10.1 {any} {
    tdom::schema create s
    s define {
        defelement doc {
            element a
            any
            element b
        }
        defelement a {}
        defelement b {}
    }
    set result [list]
    foreach xml {
        <doc><a/><something/><b/></doc>
        <doc><a/><a><b>text</b><c><c><c/></c></c></a><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1}            

test schema-10.2 {any} {
    tdom::schema create s
    s define {
        defelement doc {
            element a
            any 1
            element b
        }
        defelement a {}
        defelement b {}
    }
    set result [s validate {<doc><a/><something/><b/></doc>}]
    lappend result [s validate {<doc><a/><something/><something/><b/></doc>}]
    lappend result [s validate {<doc><a/><b/></doc>}]
    lappend result [s validate {<doc><a/><a><b>text</b><c><c><c/></c></c></a><b/></doc>}]
    s delete
    set result
} {1 0 0 1}

test schema-10.3 {any} {
    tdom::schema create s
    s define {
        defelement doc {
            element a
            any ?
            element b
        }
        defelement a {}
        defelement b {}
    }
    set result [s validate {<doc><a/><something/><b/></doc>}]
    lappend result [s validate {<doc><a/><something/><something/><b/></doc>}]
    lappend result [s validate {<doc><a/><b/></doc>}]
    lappend result [s validate {<doc><a/><a><b>text</b><c><c><c/></c></c></a><b/></doc>}]
    s delete
    set result
} {1 0 0 1}

test schema-10.4 {any} {
    tdom::schema create s
    s define {
        defelement doc {
            element a
            any 2
            element b
        }
        defelement a {}
        defelement b {}
    }
    set result [list]
    foreach xml {
        {<doc><a/><something/><b/></doc>}
        {<doc><a/><something/><something/><b/></doc>}
        {<doc><a/><b/></doc>}
        {<doc><a/><a><b>text</b><c><c><c/></c></c></a><b/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 0 0}

test schema-10.5 {any} {
    tdom::schema create s
    s define {
        defelement doc {
            element a
            any http://foo.bar 2
            element b
        }
        defelement a {}
        defelement b {}
    }
    set result [list]
    foreach xml {
        {<doc><a/><something/><b/></doc>}
        {<doc><a/><something/><something/><b/></doc>}
        {<doc><a/><b/></doc>}
        {<doc><a/><a><b>text</b><c><c><c/></c></c></a><b/></doc>}
        {<doc xmlns:ns="http://foo.bar"><a/><ns:a/><ns:b>some</ns:b><b/></doc>}
        {<doc xmlns:ns="http://foo.bar" xmlns:ns1="http://foo.bar"><a/><ns1:a/><ns:b>some</ns:b><b/></doc>}
        {<doc xmlns:ns="http://foo.bar" xmlns:ns1="http://foo.grill"><a/><ns1:a/><ns:b>some</ns:b><b/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 1 1 0}

test schema-10.6 {any} {
    tdom::schema create s
    s define {
        defelement doc {
            any
        }
    }
    set result [list]
    foreach xml {
        {<doc><a:some xmlns:a="uri"/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1}

test schema-11.1 {attribute} {
    tdom::schema create s
    s define {
        defelement doc {
            attribute attr1
            attribute attr2 ?
        }
    }
    set result [s validate {<doc attr1="foo" attr2="bar"/>}]
    lappend result [s validate {<doc attr1="foo"/>}]
    lappend result [s validate {<doc attr2="bar"/>}]
    lappend result [s validate {<doc attr1="foo" attr2="bar" unknownAtt="grill"/>}]
    s delete
    set result
} {1 1 0 0}

test schema-11.1a {attribute} {
    tdom::schema create s
    s define {
        defelement doc {
            attribute attr1
            attribute attr2 ?
        }
    }
    set result [list]
    foreach xml {
        {<doc attr1="foo" attr2="bar"/>}
        {<doc attr1="foo"/>}
        {<doc attr2="bar"/>}
        {<doc attr1="foo" attr2="bar" unknownAtt="grill"/>}
    } {
        lappend result [catch {set doc [dom parse -validateCmd s $xml]} errMsg]
        catch {$doc delete}
        s reset
    }
    s delete
    set result
} {0 0 1 1}

test schema-11.1b {attribute} {
    tdom::schema create s
    s define {
        defelement doc {
            attribute attr1
            attribute attr2 ?
        }
    }
    ::xml::parser p -validateCmd s    
    set result [list]
    foreach xml {
        {<doc attr1="foo" attr2="bar"/>}
        {<doc attr1="foo"/>}
        {<doc attr2="bar"/>}
        {<doc attr1="foo" attr2="bar" unknownAtt="grill"/>}
    } {
        lappend result [catch {p parse $xml} errMsg]
        p reset
        s reset
    }
    s delete
    p delete
    set result
} {0 0 1 1}

test schema-11.2 {attribute} {
    tdom::schema create s
    s define {
        defelement e {
            attribute attr1
            element e 1 {
                attribute attr3 ?
                attribute attr4 !
            }
            attribute attr2 ?
        }
    }
    set result [s validate {<e attr1="attr1" attr2="attr2"><e attr3="attr3" attr4="attr4"/></e>}]
    lappend result [s validate {<e attr1="attr1"><e attr3="attr3" attr4="attr4"/></e>}]
    lappend result [s validate {<e attr2="attr2"><e attr3="attr3" attr4="attr4"/></e>}]
    lappend result [s validate {<e attr1="attr1"><e attr4="attr4"/></e>}]
    lappend result [s validate {<e attr1="attr1"><e attr3="attr3"/></e>}]
    s delete
    set result
} {1 1 0 1 0}

test schema-11.2a {attribute} {
    tdom::schema create s
    s define {
        defelement e {
            attribute attr1
            element e 1 {
                attribute attr3 ?
                attribute attr4 !
            }
            attribute attr2 ?
        }
    }
    set result [list]
    foreach xml {
        {<e attr1="attr1" attr2="attr2"><e attr3="attr3" attr4="attr4"/></e>}
        {<e attr1="attr1"><e attr3="attr3" attr4="attr4"/></e>}
        {<e attr2="attr2"><e attr3="attr3" attr4="attr4"/></e>}
        {<e attr1="attr1"><e attr4="attr4"/></e>}
        {<e attr1="attr1"><e attr3="attr3"/></e>}
    } {
        lappend result [catch {set doc [dom parse -validateCmd s $xml]} errMsg]
        catch {$doc delete}
        s reset
    }
    s delete
    set result
} {0 0 1 0 1}

test schema-11.2b {attribute} {
    tdom::schema create s
    s define {
        defelement e {
            attribute attr1
            element e 1 {
                attribute attr3 ?
                attribute attr4 !
            }
            attribute attr2 ?
        }
    }
    ::xml::parser p -validateCmd s    
    set result [list]
    foreach xml {
        {<e attr1="attr1" attr2="attr2"><e attr3="attr3" attr4="attr4"/></e>}
        {<e attr1="attr1"><e attr3="attr3" attr4="attr4"/></e>}
        {<e attr2="attr2"><e attr3="attr3" attr4="attr4"/></e>}
        {<e attr1="attr1"><e attr4="attr4"/></e>}
        {<e attr1="attr1"><e attr3="attr3"/></e>}
    } {
        lappend result [catch {p parse $xml} errMsg]
        p reset
        s reset
    }
    p delete
    s delete
    set result
} {0 0 1 0 1}

test schema-11.3 {attribute} {
    tdom::schema create s
    s define {
        defelement e {
            attribute attr1
            attribute attr3 ?
            attribute attr4 !
            attribute attr2 ?
        }
    }
    set result [s validate <e/> errMsg]
    lappend result $errMsg
    s delete
    set result
} {0 {error "Missing mandatory attribute(s): attr1 attr4" at line 1 character 4}}

test schema-11.3a {attribute} {
    tdom::schema create s
    s define {
        defelement e {
            attribute attr1
            attribute attr3 ?
            attribute attr4 !
            attribute attr2 ?
        }
    }
    set result [catch {dom parse -validateCmd s <e/>} errMsg]
    lappend result $errMsg
    s delete
    set result
} {1 {Missing mandatory attribute(s): attr1 attr4, referenced at line 1 character 4}}

test schema-11.3b {attribute} {
    tdom::schema create s
    s define {
        defelement e {
            attribute attr1
            attribute attr3 ?
            attribute attr4 !
            attribute attr2 ?
        }
    }
    ::xml::parser p -validateCmd s    
    set result [catch {p parse <e/>} errMsg]
    lappend result $errMsg
    p delete
    s delete
    set result
} {1 {Missing mandatory attribute(s): attr1 attr4}}

test schema-11.4 {attribute} {
    tdom::schema create s
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang http://www.w3.org/XML/1998/namespace ?
            }
        }
    }
    set result [s validate {<doc><e foo="bar"/></doc>} errMsg]
    s delete
    lappend result $errMsg
} {1 {}}

test schema-11.4_1 {attribute} {
    tdom::schema create s
    s prefixns {1 http://www.w3.org/XML/1998/namespace}
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang 1 ?
            }
        }
    }
    set result [s validate {<doc><e foo="bar"/></doc>} errMsg]
    s delete
    lappend result $errMsg
} {1 {}}

test schema-11.4a {attribute} {
    tdom::schema create s
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang http://www.w3.org/XML/1998/namespace ?
            }
        }
    }
    set result [catch {set doc [dom parse -validateCmd s {<doc><e foo="bar"/></doc>}]}]
    s delete
    $doc delete
    set result
} 0

test schema-11.4b {attribute} {
    tdom::schema create s
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang http://www.w3.org/XML/1998/namespace
            }
        }
    }
    set result [s validate {<doc><e xml:lang="en" foo="bar"/></doc>} errMsg]
    s delete
    lappend result $errMsg
} {1 {}}

test schema-11.5 {nsattribute} {
    tdom::schema create s
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang http://www.w3.org/XML/1998/namespace ?
            }
        }
    }
    set result [catch {set doc [dom parse -validateCmd s {<doc><e xml:lang="en" foo="bar"/></doc>}]}]
    s delete
    $doc delete
    set result
} 0

test schema-11.5a {nsattribute} {
    tdom::schema create s
    s prefixns {ns1 http://www.w3.org/XML/1998/namespace}
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang ns1 ?
            }
        }
    }
    set result [catch {set doc [dom parse -validateCmd s {<doc><e xml:lang="en" foo="bar"/></doc>}]}]
    s delete
    $doc delete
    set result
} 0

test schema-11.6 {nsattribute} {
    tdom::schema create s
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang http://www.w3.org/XML/1998/namespace
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><e foo="bar"/></doc>}
        {<doc><e xml:lang="en"/></doc>}
        {<doc><e unknown="some"/></doc>}
        {<doc><e/></doc>}
    } {
        lappend result [catch {set doc [dom parse -validateCmd s $xml]} errMsg]
        lappend result $errMsg
        s reset
    }
    s delete
    set result
} {1 {Missing mandatory attribute(s): http://www.w3.org/XML/1998/namespace:lang, referenced at line 1 character 19} 1 {Missing mandatory attribute(s): foo, referenced at line 1 character 23} 1 {Unknown attribute "unknown", referenced at line 1 character 24} 1 {Missing mandatory attribute(s): foo http://www.w3.org/XML/1998/namespace:lang, referenced at line 1 character 9}}

test schema-11.6 {nsattribute} {
    tdom::schema create s
    s prefixns {ns1 http://www.w3.org/XML/1998/namespace}
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang ns1
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><e foo="bar"/></doc>}
        {<doc><e xml:lang="en"/></doc>}
        {<doc><e unknown="some"/></doc>}
        {<doc><e/></doc>}
    } {
        lappend result [catch {set doc [dom parse -validateCmd s $xml]} errMsg]
        lappend result $errMsg
        s reset
    }
    s delete
    set result
} {1 {Missing mandatory attribute(s): http://www.w3.org/XML/1998/namespace:lang, referenced at line 1 character 19} 1 {Missing mandatory attribute(s): foo, referenced at line 1 character 23} 1 {Unknown attribute "unknown", referenced at line 1 character 24} 1 {Missing mandatory attribute(s): foo http://www.w3.org/XML/1998/namespace:lang, referenced at line 1 character 9}}

test schema-11.7 {attribute} {
    set defs {
        {defelement doc {attribute foo}}
        {defelement doc {group {attribute foo}}}
        {defpattern some {attribute foo}}
        {defelement doc {element {attribute foo}}}
    }
    set result [list]
    foreach def $defs {
        tdom::schema create s
        lappend result [catch {s define $def}]
        s delete
    }
    set result
} {0 1 1 0}

test schema-11.8 {attribute} {
    tdom::schema s
    s define {
        defelement doc {
            element e ! {
                attribute abc
                attribute def
                attribute ghi
                attribute jkl
                attribute mno
                attribute pqr
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><e abc="" def="" ghi="" jkl="" mno="" pqr=""/></doc>}
        {<doc><e abc="" def="" ghi="" jkl="" pqr=""/></doc>}
        {<doc><e unknown="" abc="" def="" ghi="" jkl="" mno="" pqr=""/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 0 0}

test schema-11.8a {attribute} {
    tdom::schema s
    s define {
        defelement doc {
            element e ! {
                attribute abc
                attribute def
                attribute ghi
                attribute optional ?
                attribute jkl
                attribute mno
                attribute pqr
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><e abc="" def="" ghi="" jkl="" mno="" pqr=""/></doc>}
        {<doc><e abc="" def="" ghi="" jkl="" pqr=""/></doc>}
        {<doc><e unknown="" abc="" def="" ghi="" jkl="" mno="" pqr=""/></doc>}
        {<doc><e optional="foo" abc="" def="" ghi="" jkl="" mno="" pqr=""/></doc>}
        {<doc><e optional="foo" abc="" def="" ghi="" jkl="" pqr=""/></doc>}
        {<doc><e optional="foo" unknown="" abc="" def="" ghi="" jkl="" mno="" pqr=""/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 0 0 1 0 0}

proc schema-11.8b {scmd errType} {
    lappend ::result $errType
    lappend ::result [$scmd info vaction name]
    lappend ::result [$scmd info vaction namespace]
}

test schema-11.8b {attribute} {
    tdom::schema s
    s define {
        defelement doc {
            element e ! {
                attribute abc
                attribute def
                attribute ghi
                attribute optional ?
                attribute jkl
                attribute mno
                attribute pqr
            }
        }
    }
    s reportcmd schema-11.8b
    set result [list]
    foreach xml {
        {<doc><e abc="" def="" ghi="" jkl="" mno="" pqr=""/></doc>}
        {<doc><e abc="" def="" ghi="" jkl="" pqr=""/></doc>}
        {<doc><e unknown="" abc="" def="" ghi="" jkl="" mno="" pqr=""/></doc>}
        {<doc><e optional="foo" abc="" def="" ghi="" jkl="" mno="" pqr=""/></doc>}
        {<doc><e optional="foo" abc="" def="" ghi="" jkl="" pqr=""/></doc>}
        {<doc><e optional="foo" unknown="" abc="" def="" ghi="" jkl="" mno="" pqr=""/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 MISSING_ATTRIBUTE mno {} 1 UNKNOWN_ATTRIBUTE unknown {} 1 1 MISSING_ATTRIBUTE mno {} 1 UNKNOWN_ATTRIBUTE unknown {} 1}

test schema-11.9 {attribute} {
    tdom::schema s
    s define {
        prefixns {ns1 http://foo.bar ns2 http://foo.grill ns3 http://bar.grill}
        defelement doc {
            element e ! {
                nsattribute abc ns1
                nsattribute abc ns2
                attribute abc
                attribute def
                attribute optional ?
                nsattribute optional ns3 ?
                attribute ghi
                attribute jkl
                attribute mno
                attribute pqr
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e abc="" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill" xmlns:ns3="http://bar.grill"><e abc="" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc="" ns3:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e optional="this" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e optional="this" abc="" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill" xmlns:ns3="http://bar.grill"><e abc="" optional="this" ns3:optional="that" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc="" ns3:abc=""/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 0 0 1 0}

test schema-11.10 {attribute} {
    tdom::schema s
    s define {
        prefixns {ns1 http://foo.bar ns2 http://foo.grill}
        defelement doc {
            element e ! {
                nsattribute abc ns1
                nsattribute abc ns2
                attribute abc
                attribute def
                attribute ghi
                attribute jkl
                attribute mno
                attribute pqr
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e abc="" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill" xmlns:ns3="http://bar.grill"><e abc="" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc="" ns3:abc=""/></doc>}
    } {
        dom parse $xml doc
        lappend result [s domvalidate $doc]
        $doc delete
    }
    s delete
    set result
} {0 1 0}

test schema-11.10a {attribute} {
    tdom::schema s
    s define {
        prefixns {ns1 http://foo.bar ns2 http://foo.grill ns3 http://bar.grill}
        defelement doc {
            element e ! {
                nsattribute abc ns1
                nsattribute abc ns2
                attribute abc
                attribute def
                attribute optional ?
                nsattribute optional ns3 ?
                attribute ghi
                attribute jkl
                attribute mno
                attribute pqr
            }
        }
    }
    s reportcmd schema-11.8b
    set result [list]
    foreach xml {
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e abc="" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e abc="" def="" ghi="" jkl="" mno="" pqr="" ns2:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill" xmlns:ns3="http://bar.grill"><e abc="" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc="" ns3:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e optional="this" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill"><e optional="this" abc="" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc=""/></doc>}
        {<doc xmlns:ns1="http://foo.bar" xmlns:ns2="http://foo.grill" xmlns:ns3="http://bar.grill"><e abc="" optional="this" ns3:optional="that" def="" ghi="" jkl="" mno="" pqr="" ns2:abc="" ns1:abc="" ns3:abc=""/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {MISSING_ATTRIBUTE abc {} 1 1 MISSING_ATTRIBUTE abc http://foo.bar 1 UNKNOWN_ATTRIBUTE abc http://bar.grill 1 MISSING_ATTRIBUTE abc {} 1 1 UNKNOWN_ATTRIBUTE abc http://bar.grill 1}

proc schema-11.11 {scmd errType} {
    lappend ::result $errType
}
test schema-11.11 {attribute - required missing} {
    tdom::schema s
    s defelement doc {
        element a + {
            attribute mode
        }
    }
    s reportcmd schema-11.11
    set result ""
    set doc [dom parse <doc><a/></doc>]
    lappend result [s domvalidate $doc]
    $doc delete
    s delete
    set result
} {MISSING_ATTRIBUTE 1}

test schema-12.1 {domvalidate} {
    tdom::schema s 
    s define {
        defelement addressBook {
            element card *
        }
        defelement card {
            element name
            element email
        }
        foreach e {name email} {
            defelement $e {text}
        }
    }
    set doc [dom parse {
<addressBook>
  <card>
    <name>John Smith</name>
    <email>js@example.com</email>
  </card>
  <card>
    <name>Fred Bloggs</name>
    <email>fb@example.net</email>
  </card>
</addressBook>        
    }]
    set result [s domvalidate $doc]
    lappend result [s domvalidate [$doc documentElement]]
    lappend result [s domvalidate [[$doc documentElement] firstChild]]
    lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]]
    $doc delete
    s delete
    set result
} {1 1 1 1}

test schema-12.2 {domvalidate} {
    tdom::schema s 
    s define {
        defelement addressBook {
            element card *
        }
        defelement card {
            element name
            element email
        }
        foreach e {name email} {
            defelement $e {text}
        }
    }
    set doc [dom parse {
<addressBook>
  <card>
    <name>John Smith</name>
    <email>js@example.com</email>
  </card>
  <card>
    <name>Fred Bloggs</name>
    <email>fb@example.net</email>
    <some>John Smith</some>
  </card>
</addressBook>        
    }]
    set result [s domvalidate $doc errMsg]
    lappend result $errMsg
    $doc delete
    s delete
    set result
} {0 {Element "some" doesn't match}}

test schema-12.3 {domvalidate w/ attribute} {
    tdom::schema s
    s define {
        defelement doc {
            attribute type {fixed "1.2"}
            element a
            element b
        }
        foreach e {a b} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        {<doc type="1.2"><a/><b/></doc>}
        {<doc type="foo"><a/><b/></doc>}
        {<doc><a/><b/></doc>}
        {<doc type="1.2" another=""><a/><b/></doc>}
        {<doc type="1.2"><a something="else"/><b/></doc>}
    } {
        set doc [dom parse $xml]
        lappend result [s domvalidate [$doc documentElement]]
        lappend result [s validate $xml]
        $doc delete
    }
    s delete
    set result
} {1 1 0 0 0 0 0 0 0 0}

test schema-12.4 {domvalidate w/ text} {
    tdom::schema s
    s define {
        defelement doc {
            attribute type {fixed "1.2"}
            element a
            element b
        }
        foreach e {a b} {
            defelement $e text
        }
    }
    set result [list]
    foreach xml {
        {<doc type="1.2"><a/><b/></doc>}
        {<doc type="1.2"><a>content</a><b/></doc>}
        {<doc type="1.2"><a>content</a><b>some text</b></doc>}
        {<doc type="1.2">text<a>content</a><b>some text</b></doc>}
        {<doc type="1.2"><a><b/></a><b>some text</b></doc>}
    } {
        set doc [dom parse $xml]
        lappend result [s domvalidate [$doc documentElement]]
        lappend result [s validate $xml]
        $doc delete
    }
    s delete
    set result
} {1 1 1 1 1 1 0 0 0 0}

test schema-12.5 {domvalidate doch w/ xml namespace} {
    tdom::schema s 
    s define {
        defelement addressBook http://foo.bar {
            element card *
        }
        defelement card http://foo.bar {
            element name
            element email
        }
        foreach e {name email} {
            defelement $e http://foo.bar {text}
        }
    }
    set doc [dom parse {
<addressBook xmlns="http://foo.bar">
  <card>
    <name>John Smith</name>
    <email>js@example.com</email>
  </card>
  <card>
    <name>Fred Bloggs</name>
    <email>fb@example.net</email>
  </card>
</addressBook>        
    }]
    set result [s domvalidate $doc]
    lappend result [s domvalidate [$doc documentElement]]
    lappend result [s domvalidate [[$doc documentElement] firstChild]]
    lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]]
    $doc delete
    set doc [dom parse {
<ns1:addressBook xmlns:ns1="http://foo.bar">
  <ns1:card>
    <ns1:name>John Smith</ns1:name>
    <ns1:email>js@example.com</ns1:email>
  </ns1:card>
  <ns1:card>
    <ns1:name>Fred Bloggs</ns1:name>
    <ns1:email>fb@example.net</ns1:email>
  </ns1:card>
</ns1:addressBook>        
}]
    lappend result [s domvalidate $doc]
    lappend result [s domvalidate [$doc documentElement]]
    lappend result [s domvalidate [[$doc documentElement] firstChild]]
    lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]]
    $doc delete
    s delete
    set result
} {1 1 1 1 1 1 1 1}

test schema-12.5a {domvalidate doc w/ xml namespace} {
    tdom::schema s 
    s prefixns {fb http://foo.bar}
    s define {
        defelement addressBook fb {
            element card *
        }
        defelement card fb {
            element name
            element email
        }
        foreach e {name email} {
            defelement $e fb {text}
        }
    }
    set doc [dom parse {
<addressBook xmlns="http://foo.bar">
  <card>
    <name>John Smith</name>
    <email>js@example.com</email>
  </card>
  <card>
    <name>Fred Bloggs</name>
    <email>fb@example.net</email>
  </card>
</addressBook>        
    }]
    set result [s domvalidate $doc]
    lappend result [s domvalidate [$doc documentElement]]
    lappend result [s domvalidate [[$doc documentElement] firstChild]]
    lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]]
    $doc delete
    set doc [dom parse {
<ns1:addressBook xmlns:ns1="http://foo.bar">
  <ns1:card>
    <ns1:name>John Smith</ns1:name>
    <ns1:email>js@example.com</ns1:email>
  </ns1:card>
  <ns1:card>
    <ns1:name>Fred Bloggs</ns1:name>
    <ns1:email>fb@example.net</ns1:email>
  </ns1:card>
</ns1:addressBook>        
}]
    lappend result [s domvalidate $doc]
    lappend result [s domvalidate [$doc documentElement]]
    lappend result [s domvalidate [[$doc documentElement] firstChild]]
    lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]]
    $doc delete
    s delete
    set result
} {1 1 1 1 1 1 1 1}

test schema-12.6 {domvalidate only root} {
    tdom::schema s
    s reportcmd dummycallback
    s start doc
    set doc [dom parse <doc/>]
    set result [s domvalidate $doc]
    s defelement doc {}
    lappend result [s domvalidate $doc]
    s delete
    $doc delete
    set result
} {1 1}

test schema-12.7 {domvalidate invalid root} {
    tdom::schema s
    s start doc
    s reportcmd dummycallback
    set doc [dom parse <dos/>]
    set result [s domvalidate $doc]
    s delete
    $doc delete
    set result
} 1

test schema-13.1 {XML namespaces} {
    tdom::schema create s
    s defelement doc ns1 {
        # Forward defined element inherits child namespace
        element elm1
        element elm2
    }
    s defelement elm1 ns2 {}
    s defelement elm1 ns1 {
        choice {
            element fooElem
            element barElem +
        }
    }
    s defelement elm2 ns1 {}
    s defelement fooElem ns1 {}
    s defelement barElem ns1 {}
    set result [list]
    foreach xml {
        {<doc xmlns="ns1"><elm1><fooElem/></elm1></doc>}
        {<doc xmlns="ns1"><elm1><fooElem/></elm1><elm2/></doc>}
        {<n:doc xmlns:n="ns1"><n:elm1><n:fooElem/></n:elm1><n:elm2/></n:doc>}
        {<n:doc xmlns:n="ns1"><elm1 xmlns="ns1"><n:fooElem/></elm1><n:elm2/></n:doc>}
        {<n:doc xmlns:n="ns1"><elm1 xmlns="ns2"><n:fooElem/></elm1><n:elm2/></n:doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 0}

test schema-13.2 {XML namespaces} {
    tdom::schema create s
    s defelement doc ns1 {
        namespace ns2 {
            element elm1
        }
        # Forward defined element inherits child namespace
        element elm2
    }
    s defelement elm1 ns2 {}
    s defelement elm1 ns1 {
        choice {
            element fooElem
            element barElem +
        }
    }
    s defelement elm2 ns1 {}
    s defelement fooElem ns1 {}
    s defelement barElem ns1 {}
    set result [list]
    foreach xml {
        {<doc xmlns="ns1"><elm1><fooElem/></elm1></doc>}
        {<doc xmlns="ns1"><elm1><fooElem/></elm1><elm2/></doc>}
        {<n:doc xmlns:n="ns1"><n:elm1><n:fooElem/></n:elm1><n:elm2/></n:doc>}
        {<n:doc xmlns:n="ns1"><elm1 xmlns="ns1"><n:fooElem/></elm1><n:elm2/></n:doc>}
        {<n:doc xmlns:n="ns1"><elm1 xmlns="ns2"/><n:elm2/></n:doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 1}

test schema-13.3 {Not namespaced elements inside namespaced ones} {
    tdom::schema s
    s define {
        defelement doc ns1 {
            namespace "" {
                element e
            }
        }
        defelement e {text {fixed "here"}}
    }
    set result ""
    foreach xml {
        {<doc xmlns="ns1"><e xmlns="">here</e></doc>}
        {<a:doc xmlns:a="ns1"><e xmlns="">here</e></a:doc>}
        {<a:doc xmlns:a="ns1"><e>here</e></a:doc>}
        {<doc xmlns="ns1"><e>here</e></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0}

test schema-14.1 {text: integer} {
    tdom::schema s
    s defelement doc {
        text {
            integer
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>5</doc>
        <doc>eeee</doc>
        <doc>56666</doc>
        {<doc>   </doc>}
        {<doc>  97  </doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 1 0 0}

test schema-14.1.1 {text: integer} {
    tdom::schema s
    s defelement doc {
        text {
            integer tcl
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>5</doc>
        <doc>eeee</doc>
        <doc>56666</doc>
        {<doc>   </doc>}
        {<doc>  +34 </doc>}
        {<doc>034</doc>}
        {<doc>0034 </doc>}
        {<doc>0xAB</doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 1 0 1 1 1 1}

test schema-14.1.2 {text: integer} {
    tdom::schema s
    s defelement doc {
        text {
            integer xsd
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>5</doc>
        <doc>eeee</doc>
        <doc>56666</doc>
        {<doc>   </doc>}
        {<doc>  +34 </doc>}
        {<doc>034</doc>}
        {<doc>0034 </doc>}
        {<doc>0xAB</doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 1 0 0 1 0 0}


proc proc-14.2 {param text} {
    if {$text in {one two tree}} {
        return true
    }
    return false
}

test schema-14.2 {text: tcl} {8.5} {
    tdom::schema s
    s define {
        defelement doc {
            element a
            element b
        }
        defelement a {
            text {tcl string is lower -strict}
        }
        defelement b {
            text {tcl proc-14.2 foo}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b/></doc>
        <doc><a>abc</a><b>two</b></doc>
        <doc><a>aBc</a><b>two</b></doc>
        <doc><a>abc</a><b>four</b></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 0}

test schema-14.3 {attribute text: tcl} {8.5} {
    tdom::schema s
    s define {
        defelement doc {
            element e 1 {
                attribute a ! {tcl string is lower -strict}
                attribute b ? {tcl proc-14.2 foo}
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><e a="abc" b="tree"/></doc>}
        {<doc><e a="aAc" b="tree"/></doc>}
        {<doc><e a="aa2c" b="tree"/></doc>}
        {<doc><e a="aaoiu"/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 0 0 1}

test schema-14.4 {text: fixed} {
    tdom::schema s
    s define {
        defelement doc {
            element e *
        }
        defelement e {
            attribute a ! {fixed enabled}
            text {fixed something}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><e a="enabled">something</e></doc>}
        {<doc><e a="somehing">something</e></doc>}
        {<doc><e a="enabled">something else</e></doc>}
        {<doc><e a="enabled">something</e><e a="foo">something</e></doc>}
        {<doc><e a="enabled">something</e><e a="enabled">not</e></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 0 0 0 0}

test schema-14.5 {text: enumeration} {
    tdom::schema s
    s define {
        defelement doc {
            element e *
        }
        defelement e {
            attribute a {enumeration {enabled disabled}}
            text {enumeration {enabled disabled "a third"}}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><e a="enabled">disabled</e></doc>}
        {<doc><e a="enabled">disabled</e><e a="disabled">a third</e></doc>}
        {<doc><e a="disabled">something</e></doc>}
        {<doc><e a="enabled">something else</e></doc>}
        {<doc><e a="enabled">enabled disabled</e></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0 0 0}

test schema-14.6 {text: match (glob style)} {
    tdom::schema s
    s define {
        defelement doc {
            element e *
        }
        defelement e {
            text {match {[a-zA-Z]*1[_!]}}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><e>disabled1_</e></doc>}
        {<doc><e>dis able1_</e></doc>}
        {<doc><e>something</e></doc>}
        {<doc><e>a1!</e></doc>}
        {<doc><e>a1!/</e></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0 1 0}

test schema-14.6a {text: match (glob style) -nocase} {
    tdom::schema s
    s define {
        defelement doc {
            element e *
        }
        defelement e {
            text {match -nocase {[A-Z]*1[_!]}}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><e>disabled1_</e></doc>}
        {<doc><e>dis able1_</e></doc>}
        {<doc><e>something</e></doc>}
        {<doc><e>a1!</e></doc>}
        {<doc><e>a1!/</e></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0 1 0}

test schema-14.7 {text: regexp} {
    tdom::schema s
    s define {
        defelement doc {
            element e *
        }
        defelement e {
            text {regexp {^[a-zA-Z]*1[_!]$}}
        }
    }
    set result [list]
    foreach xml {
        {<doc><e>disabled1_</e></doc>}
        {<doc><e>dis able1_</e></doc>}
        {<doc><e>something</e></doc>}
        {<doc><e>a1!</e></doc>}
        {<doc><e>a1!/</e></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 0 0 1 0}

test schema-14.8 {text: nmtoken, nmtokens} {
    tdom::schema s
    s define {
        defelement doc {
            attribute a {nmtoken}
            attribute b {nmtokens}
            attribute c ?
        }
    }
    set result [list]
    foreach xml {
        {<doc a="foo" b="foo" c="something"/>}
        {<doc a="foo" b="foo bar"/>}
        {<doc a=".foo" b="f2o" c="something"/>}
        {<doc a=":foo" b="fo:o b2/ar"/>}
        {<doc b="foo bar"/>}
        {<doc a="foo" b="  foo    bar  "/>}
        {<doc a="  foo  " b="foo bar"/>}
        {<doc a="foo " b="foo bar"/>}
        {<doc a=" foo" b="foo bar"/>}
        {<doc a="foo" b=" foo bar"/>}
        {<doc a="foo" b="foo  bar"/>}
        {<doc a="foo" b="foo bar "/>}
        {<doc a="foo bar" b="foo bar"/>}
        {<doc a="f&#xd7;o" b="foo bar"/>}
        {<doc a="foo" b="foo b&#xf7;r"/>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0 0 1 1 1 1 1 1 1 0 0 0}

test schema-14.9 {text: date} {
    tdom::schema s
    s define {
        defelement doc {
            text date
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>foo</doc>
        <doc>1</doc>
        <doc>12</doc>
        <doc>1234-12-31</doc>
        <doc>1234-14-31</doc>
        <doc>1234-12-00</doc>
        <doc>1234-02-31</doc>
        <doc>2000-02-29</doc>
        <doc>2001-02-29</doc>
        <doc>2004-02-29</doc>
        <doc>-2004-02-29</doc>
        <doc>1900-02-29</doc>
        <doc>1234-02-01</doc>
        <doc>1234-08-10</doc>
        <doc>1234-08-222</doc>
        {<doc> 1234-08-22</doc>}
        {<doc>1234-08-22 </doc>}
        <doc>11234-08-22</doc>
        <doc>0000-02-01</doc>
        <doc>10000-08-22</doc>
        <doc>10000-02-29</doc>
        <doc>10000-02-29Z</doc>
        <doc>2012-03-07Z</doc>
        {<doc>2012-03-07Z </doc>}
        <doc>2012-03-07a</doc>
        <doc>2012-03-07+</doc>
        <doc>2012-03-07+00:00</doc>
        <doc>2012-03-07-00:00</doc>
        <doc>2012-03-07+02:00</doc>
        <doc>2012-03-07+02:70</doc>
        <doc>2012-03-07+12:30</doc>
        <doc>2012-03-07+14:30</doc>
        <doc>2012-03-07+14:00</doc>
        <doc>2012-03-07-14:00</doc>
        <doc>2012-03-07-14:01</doc>
        <doc>2012-03-07-2:30</doc>
        <doc>2012-03-07-02:30Z</doc>
        {<doc>2012-03-07-02:30 </doc>}
        <doc>02027-02-01</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 0 1 0 0 0 1 0 1 1 0 1 1 0 0 0 1 0 1 1 1 1 0 0 0 1 1 1 0 1 0 1 1 0 0 0 0 0}

test schema-14.10 {text: number tcl} {
    tdom::schema s
    s define {
        defelement doc {
            text {number tcl}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        {<doc> </doc>}
        <doc>foo</doc>
        <doc>1</doc>
        <doc>12</doc>
        <doc>1234-12-31</doc>
        <doc>-14.23</doc>
        <doc>.777</doc>
        <doc>-1.2e5</doc>
        {<doc> -1.2e5 </doc>}
        {<doc> -1.2e5 e</doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 1 1 0 1 1 1 1 0}

test schema-14.10a {text: number xsd} {
    tdom::schema s
    s define {
        defelement doc {
            text number
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        {<doc> </doc>}
        <doc>foo</doc>
        <doc>1</doc>
        {<doc> 1</doc>}
        {<doc>1 </doc>}
        {<doc> 1 </doc>}
        <doc>12</doc>
        <doc>1234-12-31</doc>
        <doc>-14.23</doc>
        <doc>.777</doc>
        <doc>-1.2e5</doc>
        {<doc> -1.2e5 </doc>}
        {<doc> -1.2e5 e</doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 1 0 0 0 1 0 1 1 0 0 0}

test schema-14.11 {text: maxLength} {
    tdom::schema s
    s define {
        defelement doc {
            text {
                maxLength 6
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>foo</doc>
        <doc>1</doc>
        <doc>12</doc>
        <doc>1234-12-31</doc>
        <doc>-14.23</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;&#x1234;</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;&#x1234;&#x1F46E;</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 1 1 0 1 1 0}

test schema-14.12 {text: maxLength} {
    tdom::schema s
    s define {
        defelement doc {
            text {minLength 6}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>foo</doc>
        <doc>1</doc>
        <doc>12</doc>
        <doc>1234-12-31</doc>
        <doc>-14.23</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;&#x1234;</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;&#x1234;&#x1F46E;</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 0 1 1 0 1 1}

test schema-14.13 {text: two constraints} {
    tdom::schema s
    s define {
        defelement doc {
            text {
                minLength 6
                maxLength 8
            }
        }
    }
    set result [list]
    foreach xml {
        <doc>foo</doc>
        <doc>1</doc>
        <doc>12</doc>
        <doc>1234-12-31</doc>
        <doc>-14.23</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;&#x1234;</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;&#x1234;&#x1F46E;</doc>
        <doc>1234567890</doc>
        <doc>12345678901234567890</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 1 0 1 1 0 0}

test schema-14.14 {text: one of two types} {
    tdom::schema s
    s define {
        defelement doc {
            choice {
                text {
                    minLength 1
                    maxLength 3
                }
                text {date}
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>foo</doc>
        <doc>1</doc>
        <doc>12</doc>
        <doc>1234-12-31</doc>
        <doc>-14.23</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;</doc>
        <doc>1234-12</doc>
        <doc>12345678901234567890</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 1 1 1 0 0 0 0}

test schema-14.15 {text: oneOf} {
    tdom::schema s
    s define {
        defelement doc {
            text {
                oneOf {
                    maxLength 3
                    date
                }
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>foo</doc>
        <doc>1</doc>
        <doc>12</doc>
        <doc>1234-12-31</doc>
        <doc>-14.23</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;</doc>
        <doc>1234-12</doc>
        <doc>12345678901234567890</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 1 1 1 0 0 0 0}

test schema-14.16 {text: oneOf} {
    tdom::schema s
    s define {
        defelement doc {
            text {
                minLength 1
                oneOf {
                    maxLength 3
                    date
                }
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>foo</doc>
        <doc>1</doc>
        <doc>12</doc>
        <doc>1234-12-31</doc>
        <doc>-14.23</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;</doc>
        <doc>1234-12</doc>
        <doc>12345678901234567890</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 1 1 1 0 0 0 0}

test schema-14.17 {text: oneOf w/ allOf} {
    tdom::schema s
    s define {
        defelement doc {
            text {
                minLength 1
                oneOf {
                    allOf {
                        maxLength 3
                        minLength 1
                    }
                    date                    
                }
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>foo</doc>
        <doc>1</doc>
        <doc>12</doc>
        <doc>1234-12-31</doc>
        <doc>-14.23</doc>
        <doc>&#x1F46E;&#x1234;&#x1234;&#x1234;&#x1234;</doc>
        <doc>1234-12</doc>
        <doc>12345678901234567890</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 1 1 1 0 0 0 0}

test schema-14.18 {deftexttype} {
    tdom::schema s
    s deftexttype len2-4 {
        minLength 2
        maxLength 4
    }
    s defelement doc {
         element e ! {text type len2-4}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><e/></doc>
        <doc><e></e></doc>
        {<doc><e> </e></doc>}
        {<doc><e>1</e></doc>}
        {<doc><e>12</e></doc>}
        {<doc><e>  </e></doc>}
        {<doc><e>123</e></doc>}
        {<doc><e>1234</e></doc>}
        {<doc><e>1234 </e></doc>}
        {<doc><e>12345</e></doc>}
        {<doc><e>123&#x1234;</e></doc>}
    } {
        lappend result [s validate $xml]
        set rc [catch {dom parse -validateCmd s $xml doc}]
        if {$rc == 0} {
            $doc delete
        }
        lappend result $rc
    }
    s delete
    set result
} {0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 0}

test schema-14.18a {deftexttype} {
    tdom::schema s
    s define {
        deftexttype len2-4 {
            minLength 2
            maxLength 4
        }
        defelement doc {
            element e ! {text type len2-4}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><e/></doc>
        <doc><e></e></doc>
        {<doc><e> </e></doc>}
        {<doc><e>1</e></doc>}
        {<doc><e>12</e></doc>}
        {<doc><e>  </e></doc>}
        {<doc><e>123</e></doc>}
        {<doc><e>1234</e></doc>}
        {<doc><e>1234 </e></doc>}
        {<doc><e>12345</e></doc>}
        {<doc><e>123&#x1234;</e></doc>}
    } {
        lappend result [s validate $xml]
        set rc [catch {dom parse -validateCmd s $xml doc}]
        if {$rc == 0} {
            $doc delete
        }
        lappend result $rc
    }
    s delete
    set result
} {0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 0}

test schema-14.18b {deftexttype} {
    tdom::schema s
    s define {
        deftexttype len2-4 {
            minLength 2
            maxLength 4
        }
        tdom::schema s1
        s1 define {
            deftexttype len2-4 {
                minLength 2
                maxLength 4
            }
            defelement doc {
                element e ! {text type len2-4}
            }
        }            
        defelement doc {
            element e ! {text type len2-4}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><e/></doc>
        <doc><e></e></doc>
        {<doc><e> </e></doc>}
        {<doc><e>1</e></doc>}
        {<doc><e>12</e></doc>}
        {<doc><e>  </e></doc>}
        {<doc><e>123</e></doc>}
        {<doc><e>1234</e></doc>}
        {<doc><e>1234 </e></doc>}
        {<doc><e>12345</e></doc>}
        {<doc><e>123&#x1234;</e></doc>}
    } {
        lappend result [s validate $xml]
        lappend result [s1 validate $xml]
        set rc [catch {dom parse -validateCmd s $xml doc}]
        if {$rc == 0} {
            $doc delete
        }
        lappend result $rc
        set rc [catch {dom parse -validateCmd s1 $xml doc}]
        if {$rc == 0} {
            $doc delete
        }
        lappend result $rc
    }
    s1 delete
    s delete
    set result
} {0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 1 1 0 0 1 1 1 1 0 0}


test schema-14.19 {deftexttype} {
    tdom::schema s
    s deftexttype len2-4 {
        minLength 2
        maxLength 4
    }
    s defelement doc {
        element e
    }
    s defelement e {
        attribute this type len2-4
        attribute foo ? type len2-4
    }
    set result [list]
    foreach xml {
        <doc><e/></doc>
        {<doc><e foo="bar"/></doc>}
        {<doc><e this="bar"/></doc>}
        {<doc><e this=""/></doc>}
        {<doc><e this="12" foo="bar"/></doc>}
        {<doc><e this="12" foo="b"/></doc>}
        {<doc><e this="1234"/></doc>}
        {<doc><e this="12345"/></doc>}
        {<doc><e this="12345alkajsdlfjkals" and="this"/></doc>}
        {<doc><e and="this" this="12345alkajsdlfjkals"/></doc>}
    } {
        lappend result [s validate $xml errMsg]
        set rc [catch {dom parse -validateCmd s $xml doc}]
        if {$rc == 0} {
            $doc delete
        }
        lappend result $rc
    }
    s delete
    set result
} {0 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 1}

test schema-14.19a {deftexttype} {
    tdom::schema s
    s deftexttype len2-4 {
        minLength 2
        maxLength 4
    }
    s defelement doc {
        element e ! {
            attribute this type len2-4
            attribute foo ? type len2-4
        }
    }
    set result [list]
    foreach xml {
        <doc><e/></doc>
        {<doc><e foo="bar"/></doc>}
        {<doc><e this="bar"/></doc>}
        {<doc><e this=""/></doc>}
        {<doc><e this="12" foo="bar"/></doc>}
        {<doc><e this="12" foo="b"/></doc>}
        {<doc><e this="1234"/></doc>}
        {<doc><e this="12345"/></doc>}
        {<doc><e this="12345alkajsdlfjkals" and="this"/></doc>}
        {<doc><e and="this" this="12345alkajsdlfjkals"/></doc>}
    } {
        lappend result [s validate $xml]
        set rc [catch {dom parse -validateCmd s $xml doc}]
        if {$rc == 0} {
            $doc delete
        }
        lappend result $rc
    }
    s delete
    set result
} {0 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 1}

test schema-14.20 {deftexttype} {
    tdom::schema s
    s deftexttype len2-4 {
        minLength 2
        maxLength 4
    }
    s defelement doc {
        element e ! {
            nsattribute this http://tdom.org/test {
                minLength 2
                maxLength 4
            }
            nsattribute foo http://tdom.org/test ? type len2-4
        }
    }
    set result [list]
    foreach xml {
        <doc><e/></doc>
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:foo="bar"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="bar"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this=""/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="12" ns1:foo="bar"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="12" ns1:foo="b"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="1234"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="12345"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="12345alkajsdlfjkals" ns1:and="this"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:and="this" ns1:this="12345alkajsdlfjkals"/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 1 0 1 0 0 0}

test schema-14.20a {deftexttype} {
    tdom::schema s
    s deftexttype len2-4 {
        minLength 2
        maxLength 4
    }
    s define {
        prefixns {
            ns2 http://tdom.org/test
            nsfoo http://foo.bar
            ns2 http://baz.boo
        }
        defelement doc {
            element e ! {
                nsattribute this ns2 {
                    minLength 2
                    maxLength 4
                }
                nsattribute foo ns2 ? type len2-4
            }
        }
    }
    set result [list]
    foreach xml {
        <doc><e/></doc>
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:foo="bar"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="bar"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this=""/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="12" ns1:foo="bar"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="12" ns1:foo="b"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="1234"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="12345"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:this="12345alkajsdlfjkals" ns1:and="this"/></doc>}
        {<doc xmlns:ns1="http://tdom.org/test"><e ns1:and="this" ns1:this="12345alkajsdlfjkals"/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 1 0 1 0 0 0}

test schema-14.21 {strip} {
    tdom::schema s
    s define {
        defelement a {
            text {
                strip {
                    minLength 3
                    maxLength 5
                }
            }
        }
    }
    set result [list]
    foreach xml {
        <a/>
        <a></a>
        {<a> </a>}
        {<a>  3  </a>}
        {<a>123</a>}
        {<a> 123    </a>}
        {<a>  123   </a>}
        {<a>1234</a>}
        {<a>12345</a>}
        {<a>123456</a>}
        {<a> 12 34 </a>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 1 1 1 1 1 0 1}

test schema-14.22 {split} {
    tdom::schema s
    s define {
        defelement doc {
            element a 1 {
                text {
                    split {
                        number
                    }
                }
            }
        }
    }
    set result [list]
    foreach xml {
        <doc><a/></doc>
        <doc><a></a></doc>
        {<doc><a>  </a></doc>}
        {<doc><a>1</a></doc>}
        {<doc><a>-2.1</a></doc>}
        {<doc><a> -2.1
            </a></doc>}
        {<doc><a>-a</a></doc>}
        {<doc><a>-a b c</a></doc>}
        {<doc><a> 1   2 3.5</a></doc>}
        {<doc><a>  1   a 3.5</a></doc>}
        {<doc><a>1 2 fooo</a></doc>}
        {<doc><a>1 2 fooo   </a></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 1 1 1 0 0 1 0 0 0}

proc schema-14.23 {text} {
    return [split $text]
}

test schema-14.23 {split} {
    tdom::schema s
    s define {
        defelement doc {
            element a 1 {
                text {
                    split tcl schema-14.23 {
                        number
                    }
                }
            }
        }
    }
    set result [list]
    foreach xml {
        <doc><a/></doc>
        <doc><a></a></doc>
        {<doc><a>  </a></doc>}
        {<doc><a>1</a></doc>}
        {<doc><a>-2.1</a></doc>}
        {<doc><a> -2.1
            </a></doc>}
        {<doc><a>-a</a></doc>}
        {<doc><a>-a b c</a></doc>}
        {<doc><a>1   2 3.5</a></doc>}
        {<doc><a> 1   a 3.5</a></doc>}
        {<doc><a>1 2 fooo</a></doc>}
        {<doc><a>1 2 3 -4.5</a></doc>}
    } {
        lappend result [s validate $xml errMsg]
    }
    s delete
    set result
} {0 0 0 1 1 0 0 0 0 0 0 1}

proc schema-14.24 {text} {
    global schema-14.24
    switch ${schema-14.24} {
        1 {return {1 2 3}}
        2 {return {-23.4 .5}}
        3 {return {0 a 5}}
        default {error "Unexpected value of the global var schema-14.24."}
    }
}

test schema-14.24 {split} {
    set schema-14.24 0
    tdom::schema s
    s define {
        defelement doc {
            element a 1 {
                text {
                    split tcl schema-14.24 {
                        number
                    }
                }
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><a>  </a></doc>}
        {<doc><a>-a</a></doc>}
        {<doc><a>1 2 3 -4.5</a></doc>}
    } {
        incr schema-14.24
        lappend result [s validate $xml errMsg]
    }
    s delete
    set result
} {1 1 0}

proc schema-14.24a {arg1 arg2 text} {
    global schema-14.24a
    if {$arg1 ne "foo" || $arg2 ne "bar"} {
        error "Unexpected args"
    }
    switch ${schema-14.24a} {
        1 {return {1 2 3}}
        2 {return {-23.4 .5}}
        3 {return {0 a 5}}
        default {error "Unexpected value of the global var schema-14.24."}
    }
}

test schema-14.24a {split} {
    set schema-14.24a 0
    tdom::schema s
    s define {
        defelement doc {
            element a 1 {
                text {
                    split tcl schema-14.24a foo bar {
                        number
                    }
                }
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><a>  </a></doc>}
        {<doc><a>-a</a></doc>}
        {<doc><a>1 2 3 -4.5</a></doc>}
    } {
        incr schema-14.24a
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 0}

test schema-14.25 {element content id/idref} {
    tdom::schema s
    s define {
        defelement doc {
            interleave {
                element id *
                element idref *
            }
        }
        defelement id {text id}
        defelement idref {text idref}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><id>abc</id></doc>
        <doc><idref>abc</idref></doc>
        <doc><id>abc</id><idref>abc</idref></doc>
        <doc><idref>abc</idref><id>abc</id></doc>
        <doc><idref>abc</idref><idref>abc</idref><id>abc</id></doc>
        <doc><id>abc</id><idref>abc</idref><idref>abc</idref></doc>
        {<doc><id>abc</id><idref>abc</idref><idref>ab c</idref></doc>}
        <doc><id>abc</id><idref>abc</idref><id>abc</id></doc>
        <doc><idref>abc</idref><idref>123</idref></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 0 1 1 1 1 0 0 0}

test schema-14.26 {attribute id/idref} {
    tdom::schema s
    s define {
        defelement doc {
            interleave {
                element id *
                element idref *
            }
        }
        defelement id {attribute id id}
        defelement idref {attribute idref idref}
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><id id="abc"/></doc>}
        {<doc><idref idref="abc"/></doc>}
        {<doc><id id="abc"/><idref idref="abc"/></doc>}
        {<doc><idref idref="abc"/><id id="abc"/></doc>}
        {<doc><idref idref="abc"/><idref idref="abc"/><id id="abc"/></doc>}
        {<doc><id id="abc"/><idref idref="abc"/><idref idref="abc"/></doc>}
        {<doc><id id="abc"/><idref idref="abc"/><idref idref="ab c"/></doc>}
        {<doc><id id="abc"/><idref idref="abc"/><id id="abc"/></doc>}
        {<doc><idref idref="abc"/><idref idref="123"/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 0 1 1 1 1 0 0 0}

test schema-14.27 {base64} {
    tdom::schema s
    s define {
        defelement doc {
            text base64
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc>ZVL1</doc>}        
        {<doc>zvL1</doc>}        
        {<doc>zvü1</doc>}        
        {<doc>0a BED   E+9</doc>}        
        {<doc>ub1sU3==</doc>}        
        {<doc>abc</doc>}        
        {<doc>===</doc>}        
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0 1 1 0 0}

test schema-14.28 {element content id/idref} {
    tdom::schema s
    s define {
        defelement doc {
            interleave {
                element id *
                element idref *
                element ida *
                element idrefa *
            }
        }
        defelement id {text id}
        defelement idref {text idref}
        defelement ida {text {id a}}
        defelement idrefa {text {idref a}}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><id>abc</id><ida>abc</ida></doc>
        <doc><idrefa>abc</idrefa></doc>
        <doc><idrefa>abc</idrefa><idref>abc</idref></doc>
        <doc><id>1</id><idrefa>abc</idrefa><idref>abc</idref><idrefa>foo</idrefa><idref>abc</idref></doc>
        <doc><id>abc</id><idref>abc</idref><ida>abc</ida><idrefa>abc</idrefa></doc>
        <doc><idref>abc</idref><id>abc</id><idrefa>abc</idrefa><ida>abc</ida></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 0 0 0 1 1}

test schema-14.29 {element content id/idref} {
    tdom::schema s
    s define {
        defelement doc {
            interleave {
                element id *
                element idref *
                element ida *
                element idrefa *
            }
        }
        defelement id {text {id b}}
        defelement idref {text {idref b}}
        defelement ida {text {id a}}
        defelement idrefa {text {idref a}}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><id>abc</id><ida>abc</ida></doc>
        <doc><idrefa>abc</idrefa></doc>
        <doc><idrefa>abc</idrefa><idref>abc</idref></doc>
        <doc><id>1</id><idrefa>abc</idrefa><idref>abc</idref><idrefa>foo</idrefa><idref>abc</idref></doc>
        <doc><id>abc</id><idref>abc</idref><ida>abc</ida><idrefa>abc</idrefa></doc>
        <doc><idref>abc</idref><id>abc</id><idrefa>abc</idrefa><ida>abc</ida></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 0 0 0 1 1}

test schema-14.30 {text: boolean (xsd)} {
    tdom::schema s
    s defelement doc {
        text boolean
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>5</doc>
        <doc>00</doc>
        <doc>01</doc>
        <doc>1</doc>
        <doc>11</doc>
        <doc>false</doc>
        {<doc>false </doc>}
        <doc>False</doc>
        <doc>FALSE</doc>
        <doc>true</doc>
        {<doc> true</doc>}
        <doc>TrUe</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 0 1 0 1 0 0 0 1 0 0}

test schema-14.30a {text: boolean (xsd)} {
    tdom::schema s
    s defelement doc {
        text {boolean xsd}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>5</doc>
        <doc>00</doc>
        <doc>01</doc>
        <doc>1</doc>
        <doc>11</doc>
        <doc>false</doc>
        {<doc>false </doc>}
        <doc>False</doc>
        <doc>FALSE</doc>
        <doc>true</doc>
        {<doc> true</doc>}
        <doc>TrUe</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 0 1 0 1 0 0 0 1 0 0}

test schema-14.31 {text: boolean (tcl)} {
    tdom::schema s
    s defelement doc {
        text {boolean tcl}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>5</doc>
        <doc>0</doc>
        <doc>01</doc>
        <doc>1</doc>
        <doc>11</doc>
        <doc>false</doc>
        <doc>f</doc>
        <doc>no</doc>
        {<doc>no </doc>}
        <doc>n</doc>
        {<doc> n </doc>}
        {<doc>false </doc>}
        <doc>False</doc>
        <doc>FALSE</doc>
        <doc>true</doc>
        {<doc> true</doc>}
        <doc>TrUe</doc>
        <doc>ON</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 1 0 1 0 1 1 1 0 1 0 0 1 1 1 0 1 1}

test schema-14.32 {text: negativeInteger} {
    tdom::schema s
    s defelement doc {
        text negativeInteger
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>5782</doc>
        <doc>3</doc>
        <doc>+2</doc>
        <doc>+002</doc>
        <doc>1</doc>
        <doc>01</doc>
        <doc>+0</doc>
        <doc>+000</doc>
        <doc>0</doc>
        <doc>-0</doc>
        <doc>-000</doc>
        <doc>-002</doc>
        <doc>-1</doc>
        <doc>-12345</doc>
        <doc>-</doc>
        <doc>+</doc>
        {<doc> </doc>}
        {<doc> -23 </doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0}

test schema-14.32.1 {text: negativeInteger tcl} {
    tdom::schema s
    s defelement doc {
        text {negativeInteger tcl}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>5782</doc>
        <doc>3</doc>
        <doc>+2</doc>
        <doc>+002</doc>
        <doc>1</doc>
        <doc>01</doc>
        <doc>+0</doc>
        <doc>+000</doc>
        <doc>0</doc>
        <doc>-0</doc>
        <doc>-000</doc>
        <doc>-002</doc>
        <doc>-1</doc>
        <doc>-12345</doc>
        <doc>-</doc>
        <doc>+</doc>
        {<doc> </doc>}
        {<doc> -23 </doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1}

test schema-14.33 {text: nonNegativeInteger} {
    tdom::schema s
    s defelement doc {
        text nonNegativeInteger
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>5782</doc>
        <doc>3</doc>
        <doc>+2</doc>
        <doc>+002</doc>
        <doc>1</doc>
        <doc>01</doc>
        <doc>+0</doc>
        <doc>+000</doc>
        <doc>0</doc>
        <doc>-0</doc>
        <doc>-000</doc>
        <doc>-002</doc>
        <doc>-1</doc>
        <doc>-12345</doc>
        <doc>-</doc>
        <doc>+</doc>
        {<doc> </doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0}

test schema-14.33.1 {text: nonNegativeInteger tcl} {
    tdom::schema s
    s defelement doc {
        text {nonNegativeInteger tcl}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>5782</doc>
        <doc>3</doc>
        <doc>+2</doc>
        <doc>+002</doc>
        <doc>1</doc>
        <doc>01</doc>
        <doc>+0</doc>
        <doc>+000</doc>
        <doc>0</doc>
        <doc>-0</doc>
        <doc>-000</doc>
        <doc>-002</doc>
        <doc>-1</doc>
        <doc>-12345</doc>
        <doc>-</doc>
        <doc>+</doc>
        {<doc> </doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0}

test schema-14.34 {text: nonPositiveInteger} {
    tdom::schema s
    s defelement doc {
        text nonPositiveInteger
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>5782</doc>
        <doc>3</doc>
        <doc>+2</doc>
        <doc>+002</doc>
        <doc>1</doc>
        <doc>01</doc>
        <doc>+0</doc>
        <doc>+000</doc>
        <doc>0</doc>
        <doc>-0</doc>
        <doc>-000</doc>
        <doc>-002</doc>
        <doc>-1</doc>
        <doc>-12345</doc>
        <doc>-</doc>
        <doc>+</doc>
        {<doc> </doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0}

test schema-14.34.1 {text: nonPositiveInteger tcl} {
    tdom::schema s
    s defelement doc {
        text {nonPositiveInteger tcl}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>5782</doc>
        <doc>3</doc>
        <doc>+2</doc>
        <doc>+002</doc>
        <doc>1</doc>
        <doc>01</doc>
        <doc>+0</doc>
        <doc>+000</doc>
        <doc>0</doc>
        <doc>-0</doc>
        <doc>-000</doc>
        <doc>-002</doc>
        <doc>-1</doc>
        <doc>-12345</doc>
        <doc>-</doc>
        <doc>+</doc>
        {<doc> </doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0}

test schema-14.35 {text: positiveInteger} {
    tdom::schema s
    s defelement doc {
        text positiveInteger
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>5782</doc>
        <doc>3</doc>
        <doc>+2</doc>
        <doc>+002</doc>
        <doc>1</doc>
        <doc>01</doc>
        <doc>+0</doc>
        <doc>+000</doc>
        <doc>0</doc>
        <doc>-0</doc>
        <doc>-000</doc>
        <doc>-002</doc>
        <doc>-1</doc>
        <doc>-12345</doc>
        <doc>-</doc>
        <doc>+</doc>
        {<doc> </doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0}

test schema-14.35.1 {text: positiveInteger tcl} {
    tdom::schema s
    s defelement doc {
        text {positiveInteger tcl}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>5782</doc>
        <doc>3</doc>
        <doc>+2</doc>
        <doc>+002</doc>
        <doc>1</doc>
        <doc>01</doc>
        <doc>+0</doc>
        <doc>+000</doc>
        <doc>0</doc>
        <doc>-0</doc>
        <doc>-000</doc>
        <doc>-002</doc>
        <doc>-1</doc>
        <doc>-12345</doc>
        <doc>-</doc>
        <doc>+</doc>
        {<doc> </doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0}

test schema-14.36 {text: hexBinary} {
    tdom::schema s
    s defelement doc {
        text {hexBinary}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>5782</doc>
        <doc>3ABCDEF0</doc>
        <doc>+2</doc>
        <doc>2</doc>
        <doc>abcd</doc>
        <doc>abcde</doc>
        <doc>abcdef</doc>
        <doc>abcdefg</doc>
        {<doc> a0123b</doc>}
        {<doc>a0123b </doc>}
        <doc>a0123b</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 0 0 1 0 1 0 0 0 1}

test schema-14.37 {text: unsignedByte} {
    tdom::schema s
    s defelement doc {
        text {unsignedByte}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>7</doc>
        <doc>+255</doc>
        <doc>-255</doc>
        <doc>-000255</doc>
        <doc>256</doc>
        <doc>65535</doc>
        <doc>000000000000000065535</doc>
        <doc>65536</doc>
        <doc>4294967295</doc>
        <doc>00000000000000004294967295</doc>
        <doc>4294967296</doc>
        <doc>18446744073709551615</doc>
        <doc>018446744073709551615</doc>
        <doc>18446744073709551616</doc>
        <doc>28446744073709551614</doc>
        <doc>3ABCDEF0</doc>
        {<doc> a0123b</doc>}
        {<doc>a0123b </doc>}
        <doc>a0123b</doc>
        <doc>1.2</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}

test schema-14.38 {text: unsignedShort} {
    tdom::schema s
    s defelement doc {
        text {unsignedShort}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>7</doc>
        <doc>+255</doc>
        <doc>-255</doc>
        <doc>-000255</doc>
        <doc>256</doc>
        <doc>65535</doc>
        <doc>000000000000000065535</doc>
        <doc>65536</doc>
        <doc>4294967295</doc>
        <doc>00000000000000004294967295</doc>
        <doc>4294967296</doc>
        <doc>18446744073709551615</doc>
        <doc>018446744073709551615</doc>
        <doc>18446744073709551616</doc>
        <doc>28446744073709551614</doc>
        <doc>3ABCDEF0</doc>
        {<doc> a0123b</doc>}
        {<doc>a0123b </doc>}
        <doc>a0123b</doc>
        <doc>1.2</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0}

test schema-14.39 {text: unsignedInt} {
    tdom::schema s
    s defelement doc {
        text {unsignedInt}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>7</doc>
        <doc>+255</doc>
        <doc>-255</doc>
        <doc>-000255</doc>
        <doc>256</doc>
        <doc>65535</doc>
        <doc>000000000000000065535</doc>
        <doc>65536</doc>
        <doc>4294967295</doc>
        <doc>00000000000000004294967295</doc>
        <doc>4294967296</doc>
        <doc>18446744073709551615</doc>
        <doc>018446744073709551615</doc>
        <doc>18446744073709551616</doc>
        <doc>28446744073709551614</doc>
        <doc>3ABCDEF0</doc>
        {<doc> a0123b</doc>}
        {<doc>a0123b </doc>}
        <doc>a0123b</doc>
        <doc>1.2</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0}

test schema-14.40 {text: unsignedLong} {
    tdom::schema s
    s defelement doc {
        text {unsignedLong}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc>7</doc>
        <doc>+255</doc>
        <doc>-255</doc>
        <doc>-000255</doc>
        <doc>256</doc>
        <doc>65535</doc>
        <doc>000000000000000065535</doc>
        <doc>65536</doc>
        <doc>4294967295</doc>
        <doc>00000000000000004294967295</doc>
        <doc>4294967296</doc>
        <doc>18446744073709551615</doc>
        <doc>018446744073709551615</doc>
        <doc>18446744073709551616</doc>
        <doc>28446744073709551614</doc>
        <doc>3ABCDEF0</doc>
        {<doc> a0123b</doc>}
        {<doc>a0123b </doc>}
        <doc>a0123b</doc>
        <doc>1.2</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0}

test schema-14.41 {text constrains commands outside text constraint} {8.5} {
    set cmds [info command tdom::schema::text::*]
    set result {}
    tdom::schema s
    foreach cmd $cmds {
        lappend result [catch {$cmd "some text"}]
        lappend result [catch {
            s define [subst "{$cmd}"]
        } errMsg]
        lappend result [catch {
            s define [subst {
                start doc
                $cmd
            }]
        } errMsg]
        lappend result [catch {
            s define [subst {
                start doc
                defelement doc {
                    $cmd
                }
            }]
        } errMsg]
    }
    if {$result eq [lrepeat [expr {[llength $cmds] * 4}] 1]} {
        set result 1
    } else {
        set result 0
    }
    set result
} 1

test schema-14.43 {text constraint setvar} {
    tdom::schema s
    namespace eval ::schema-14.43 { }
    s defelement doc {
        text {
            setvar from_schema-14.43
            setvar ::schema-14.43::foo
        }
    }
    s validate "<doc>this</doc>"
    s delete
    list ${::schema-14.43::foo} ${from_schema-14.43}
} {this this}

test schema-14.44 {text constraint setvar} {
    tdom::schema s
    namespace eval ::schema-14.43 { }
    s defelement doc {
        element a ! {text {setvar from_schema-14.44}}
        element b ! {text {setvar from_schema-14.44}}
    }
    set result [s validate "<doc><a>a</a><b>b</b></doc>"]
    s delete
    lappend result ${from_schema-14.44}
} {1 b}

test schema-14.45 {text constraint whitespace} {
    tdom::schema s
    s defelement doc {
        text {
            whitespace preserve {
                oneOf {
                    fixed foo
                    allOf {
                        minLength 5
                        integer
                    }
                }
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>foo</doc>
        <doc>12345</doc>
        <doc>1234</doc>
        <doc>1234a</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 1 0 0}

test schema-14.46 {text constraint whitespace} {
    tdom::schema s
    s defelement doc {
        text {
            whitespace replace {
                fixed "foo bar"
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        {<doc>foo bar</doc>}
        {<doc>foo
bar</doc>}
        {<doc>foo	bar</doc>}
        {<doc>foo	 bar</doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 1 1 0}

test schema-14.47 {text constraint whitespace} {
    tdom::schema s
    s defelement doc {
        text {
            whitespace collapse {
                fixed "foo bar"
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        {<doc>foo bar</doc>}
        {<doc>foo
bar</doc>}
        {<doc>foo	bar</doc>}
        {<doc>foo	 bar</doc>}
        {<doc>  foo  bar  </doc>}
        {<doc>  foo  bar  rr</doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 1 1 1 1 0}

test schema-14.48 {text constraint whitespace} {
    tdom::schema s
    s defelement doc {
        text {
            whitespace preserve {
                fixed "foo[string repeat " " 300]bar"
            }
        }
    }
    set xmls {
        <doc/>
    }
    lappend xmls "<doc>foo[string repeat " " 300]bar</doc>"
    set result [list]
    foreach xml $xmls {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1}

test schema-14.49 {text constraint whitespace} {
    tdom::schema s
    s defelement doc {
        text {
            whitespace collapse {
                fixed "foo [string repeat "x" 1200]bar"
            }
        }
    }
    set xmls {
        <doc/>
    }
    lappend xmls "<doc>[string repeat " " 300]foo[string repeat " " 300][string repeat "x" 1200]bar[string repeat " " 300]</doc>"
    set result [list]
    foreach xml $xmls {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1}

test schema-14.50 {text constraint whitespace} {
    tdom::schema s
    s defelement doc {
        element b ! {
            text {
                whitespace replace {
                    fixed "foo[string repeat " " 400]bar"
                }
            }
        }
    }
    set xml <doc> 
    append xml <b> foo [string repeat "&#xA; \t&#xD;" 100] bar </b>
    append xml </doc>
    set result [s validate $xml]
    s delete
    set result
} 1

test schema-14.51 {text constraint whitespace} {
    tdom::schema s
    s defelement doc {
        element a ! {
            text {
                whitespace collapse {
                    fixed "foo [string repeat "x" 1200]bar"
                }
            }
        }
        element b ! {
            text {
                whitespace replace {
                    fixed "foo[string repeat " " 8000]bar"
                }
            }
        }
    }
    set xml <doc> 
    append xml <a> [string repeat " " 20] foo " " [string repeat x 1200] bar \
        [string repeat " " 8000] </a>
    append xml <b> foo [string repeat "&#xA; \t&#xD;" 2000] bar </b>
    append xml </doc>
    set result [s validate $xml]
    s delete
    set result
} 1

test schema-14.52 {text constraint whitespace} {
    tdom::schema s
    s defelement doc {
        element a + {
            text {
                not {
                    fixed foo
                    fixed bar
                }
            }
        }
    }
    set result ""
    foreach xml {
        <doc><a>foo</a></doc>
        <doc><a>bar</a></doc>
        <doc><a>grill</a></doc>
        <doc><a/></doc>
        <doc><a/><a>grill</a></doc>
        <doc><a/><a>bar</a></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 1 1 0}

test schema-14.54 {text constraint dateTime} {
    tdom::schema s
    s define {
        defelement doc {
            text dateTime
        }
    }
    set result ""
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>foo</doc>
        <doc>1</doc>
        <doc>2020-07-08T15:58:17</doc>
        <doc>2020-07-08T15:20:00</doc>
        <doc>2020-07-08T15:20:17.7</doc>
        <doc>2020-07-08T15:58:17+02:00</doc>
        <doc>2020-07-08T15:20:17.789</doc>
        <doc>2020-07-08T15:20:17.7890</doc>
        <doc>2020-07-08T15:20:17.0</doc>
        <doc>2020-07-08T15:20:17.</doc>
        <doc>2020-07-08T15:20:17.+02:00</doc>
        <doc>2020-07-08T15:20:17.Z</doc>
        <doc>2020-07-08T15:20:17+Z</doc>
        <doc>2020-07-08T00:20</doc>
        <doc>2020-07-08T00:60:00</doc>
        <doc>2020-07-08T24:00:00</doc>
        <doc>2020-07-08T24:00:00.1</doc>
        <doc>2020-07-08T24:01:00</doc>
        <doc>2020-07-08T24:00:01</doc>
        <doc>2020-12-2215:20:00</doc>
        <doc>2020-12-22</doc>
        <doc>2020-07-08T15:20:17.789+02:00</doc>
        <doc>2020-07-08T15:20:17-02:00</doc>
        <doc>2020-07-08T15:20:17-02:00.0</doc>
        <doc>2020-07-08T15:20:17.0-02:00</doc>
        "<doc> 2020-07-08T15:20:17.0-02:00</doc>"
        "<doc>2020-07-08T15:20:17.0-02:00 </doc>"
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0}

test schema-14.55 {text constraint time} {
    tdom::schema s
    s define {
        defelement doc {
            text time
        }
    }
    set result ""
    foreach xml {
        <doc/>
        <doc></doc>
        <doc>foo</doc>
        <doc>1</doc>
        <doc>15:58:17</doc>
        <doc>15:20:00</doc>
        <doc>15:20:17.7</doc>
        <doc>15:58:17+02:00</doc>
        <doc>15:20:17.789</doc>
        <doc>15:20:17.7890</doc>
        <doc>15:20:17.0</doc>
        <doc>15:20:17.</doc>
        <doc>15:20:17.+02:00</doc>
        <doc>15:20:17.Z</doc>
        <doc>15:20:17+Z</doc>
        <doc>00:20</doc>
        <doc>00:60:00</doc>
        <doc>24:00:00</doc>
        <doc>24:00:00.1</doc>
        <doc>24:01:00</doc>
        <doc>24:00:01</doc>
        <doc>15:20:17.789+02:00</doc>
        <doc>15:20:17-02:00</doc>
        <doc>15:20:17-02:00.0</doc>
        <doc>15:20:17.0-02:00</doc>
        "<doc> 15:20:17.0-02:00</doc>"
        "<doc>T15:20:17.0-02:00 </doc>"
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 1 1 0 1 0 0}

test schema-14.56 {length} {
    tdom::schema s
    s defelement doc {
        element e ! {
            text {length 2}
        }
    }
    set result [list]
    foreach xml {
        <doc><e/></doc>
        <doc><e></e></doc>
        {<doc><e>1</e></doc>}
        {<doc><e>12</e></doc>}
        {<doc><e>  </e></doc>}
        {<doc><e>123</e></doc>}
        {<doc><e>1&#x1234;</e></doc>}
    } {
        lappend result [s validate $xml]
        set rc [catch {dom parse -validateCmd s $xml doc}]
        if {$rc == 0} {
            $doc delete
        }
        lappend result $rc
    }
    s delete
    set result
} {0 1 0 1 0 1 1 0 1 0 0 1 1 0}

test schema-14.57 {length} {
    tdom::schema s
    s defelement doc {
        element e ! {
            text {length 0}
        }
    }
    set result [list]
    foreach xml {
        <doc><e/></doc>
        <doc><e></e></doc>
        {<doc><e>1</e></doc>}
        {<doc><e>12</e></doc>}
        {<doc><e>  </e></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 0 0 0}

test schema-14.58 {text constraint command syntax} {
    tdom::schema s
    s deftexttype len2-4 {
        minLength 2
        maxLength 4
    }
    set result [catch {s defelement doc {
        element e ! {text typs len2-4}
    }}]
    s delete
    set result
} 1

test schema-14.59 {Tcl error in text constraint script} {
    tdom::schema s
    s defelement doc {
        element a
    }
    set result [catch {
        s defelement a {
            text {error "triggered"}
        }
    }]
    s delete
    set result
} 1

test schema-14.60 {Empty element} {
    tdom::schema s
    s defelement doc {
        element a
    }
    s defelement a {
        attribute att ?
    }
    ::xml::parser p -validateCmd s
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        {<doc> <a/></doc>}
        {<doc> <a att="some"/></doc>}
        {<doc> <a att="some"></a> </doc>}
        {<doc> <a att="some"> </a> </doc>}
    } {
        lappend result [s validate $xml]
        lappend result [catch {p parse $xml}]
        set doc ""
        lappend result [catch {set doc [dom parse -validateCmd s $xml]}]
        if {$doc ne ""} {
            $doc delete
        }
    }
    s delete
    p delete
    set result
} {0 1 1 1 0 0 1 0 0 1 0 0 1 0 0 0 1 1}

test schema-14.61 {Empty element} {
    tdom::schema s
    s defelement doc {
        element a
    }
    s defelement a {
        attribute att ?
        text
    }
    ::xml::parser p -validateCmd s
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        {<doc> <a/></doc>}
        {<doc> <a att="some"/></doc>}
        {<doc> <a att="some"></a> </doc>}
        {<doc> <a att="some"> </a> </doc>}
    } {
        lappend result [s validate $xml]
        lappend result [catch {p parse $xml}]
        set doc ""
        lappend result [catch {set doc [dom parse -validateCmd s $xml]}]
        if {$doc ne ""} {
            $doc delete
        }
    }
    s delete
    p delete
    set result
} {0 1 1 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0}

test schema-14.62 {Empty element} {
    tdom::schema s
    s defelement doc {
        element a
    }
    ::xml::parser p -validateCmd s
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        {<doc> <a/></doc>}
        {<doc> <a></a></doc>}
        {<doc> <a att="some"></a> </doc>}
        {<doc> <a> </a> </doc>}
    } {
        lappend result [s validate $xml]
        lappend result [catch {p parse $xml}]
        set doc ""
        lappend result [catch {set doc [dom parse -validateCmd s $xml]}]
        if {$doc ne ""} {
            $doc delete
        }
    }
    s delete
    p delete
    set result
} {0 1 1 1 0 0 1 0 0 1 0 0 0 1 1 0 1 1}

test schema-15.1 {constraint cmd tcl} {
    tdom::schema s
    s define {
        defelement a {
            tcl append ::schema-15.1 [self]
            element b
            tcl append ::schema-15.1 [self]
        }
    }
    set ::schema-15.1 ""
    set result [s validate {<a><b/></a>} msg]
    s delete
    lappend result $msg ${::schema-15.1}
    set result
} {1 {} ss}

proc schema-15.2-astart {args} {
    append ::schema-15.2 astart
}

proc schema-15.2-aend {args} {
    append ::schema-15.2 aend
}

test schema-15.2 {constraint cmd tcl} {
    tdom::schema s
    s define {
        defelement doc {
            element a *
        }
        defelement a {
            tcl schema-15.2-astart
            element b ! text
            element c ! text
            tcl schema-15.2-aend
        }
    }
    set schema-15.2 ""
    set result [s validate {<doc><a><b>foo</b><c/></a><a><b></b><c>bar</c></a></doc>} msg]
    s delete
    lappend result $msg ${schema-15.2}
    set result
} {1 {} astartaendastartaend}

proc schema-15.3 {type cmd} {
    lappend ::schema-15.3 $type [$cmd info stack top]
}

test schema-15.3 {constraint cmd tcl} {8.5} {
    tdom::schema s
    s define {
        defelement doc {
            element a *
        }
        defelement a {
            tcl schema-15.3 astart [self]
            element b ! text
            element c ! text
            tcl schema-15.3 aend [self]
        }
    }
    set schema-15.3 ""
    set result [s validate {<doc><a><b>foo</b><c/></a><a><b></b><c>bar</c></a></doc>} msg]
    s delete
    lappend result $msg {*}${schema-15.3}
    set result
} {1 {} astart a aend a astart a aend a}

proc schema-15.4 {text cmd} {
    if {$text ne "in docContent"} {error "unexpected text argument"}
    set ::schema-15.4 [$cmd info stack inside]
}
test schema-15.4 {constraint cmd tcl} {
    tdom::schema s
    s define {
        defelement doc {
            ref docContent
        }
        defpattern docContent {
            element a
            tcl schema-15.4 "in docContent" [self]
            text
            element b
        }
    }
    set schema-15.4 ""
    set result [s validate {<doc><a/>foo<b/></doc>}]
    s delete
    lappend result [set schema-15.4]
    set result
} {1 doc}

test schema-16.1 {interleave} {
    tdom::schema s
    s define {
        defelement doc {
            interleave {
                element a
                element b
                element c
            }
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b/><c/></doc>
        <doc><b/><a/><c/></doc>
        <doc><c/><b/><a/></doc>
        <doc><a/><b/><a/></doc>
        <doc><a/><b/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 0 0 0}

# It's in fact a missing feature: handling ambiguity.
# test schema-16.2 {interleave} {knownBug} {
#     tdom::schema s
#     s define {
#         defelement doc {
#             interleave {
#                 element a 1 {
#                     attribute type {fixed foo}
#                 }
#                 element a 1 {
#                     attribute type {fixed bar}
#                 }
#                 element a 1 {
#                     attribute type {fixed grill}
#                 }
#             }
#         }
#         foreach e {a b c} {
#             defelement $e {}
#         }
#     }
#     set result [list]
#     foreach xml {
#         <doc/>
#         {<doc><a type="foo"/><a type="bar"/><a type="grill"/></doc>}
#         {<doc><a type="grill"/><a type="bar"/><a type="foo"/></doc>}
#         {<doc><a type="grill"/><a type="foo"/><a type="bar"/></doc>}
#         {<doc><a type="bar"/><a type="foo"/><a type="bar"/></doc>}
#         {<doc><a type="bar"/><a type="foo"/><a/></doc>}
#         <doc>12</doc>
#     } {
#         lappend result [s validate $xml]
#     }
#     s delete
#     set result
# } {0 1 1 1 0 0}

test schema-16.3 {interleave} {
    tdom::schema s
    s define {
        defelement doc {
            interleave {
                element a
                element b +
                element c
            }
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b/><c/></doc>
        <doc><b/><a/><c/></doc>
        <doc><c/><b/><a/></doc>
        <doc><b/><a/><b/><c/><b/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 0 0}

test schema-16.4 {interleave} {
    tdom::schema s
    s define {
        defelement doc {
            interleave {
                element a
                element b ?
                element c
            }
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b/><c/></doc>
        <doc><b/><a/><c/></doc>
        <doc><c/><b/><a/></doc>
        <doc><b/><a/><b/><c/><b/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 0 1 0}

test schema-16.5 {interleave} {
    tdom::schema s
    s define {
        defelement doc {
            interleave {
                element a
                element b *
                element c
            }
        }
        foreach e {a b c} {
            defelement $e {}
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b/><c/></doc>
        <doc><b/><a/><c/></doc>
        <doc><c/><b/><a/></doc>
        <doc><b/><a/><b/><c/><b/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 1 0}

test schema-16.6 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b2 c} {
            defelement $e {}
        }
        defelement doc {
            interleave {
                element a
                group * {
                    element b1
                    element b2
                }
                element c
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b1/><b2/><c/></doc>
        <doc><b1/><b2/><a/><c/></doc>
        <doc><c/><b1/><b2/><a/></doc>
        <doc><c/><b1/><a/><b2/></doc>
        <doc><b1/><b2/><a/><b1/><b2/><c/><b1/><b2/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 0 1 1 0}

test schema-16.7 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b2 c} {
            defelement $e {}
        }
        defelement doc {
            interleave {
                element a
                group {
                    element b1
                    element b2
                }
                element c
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b1/><b2/><c/></doc>
        <doc><b1/><b2/><a/><c/></doc>
        <doc><c/><b1/><b2/><a/></doc>
        <doc><c/><b1/><a/><b2/></doc>
        <doc><b1/><b2/><a/><b1/><b2/><c/><b1/><b2/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 0 0 0 0}

test schema-16.8 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b2 c} {
            defelement $e {}
        }
        defelement doc {
            interleave {
                element a
                group ? {
                    element b1
                    element b2
                }
                element c
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b1/><b2/><c/></doc>
        <doc><b1/><b2/><a/><c/></doc>
        <doc><c/><b1/><b2/><a/></doc>
        <doc><c/><b1/><a/><b2/></doc>
        <doc><b1/><b2/><a/><b1/><b2/><c/><b1/><b2/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 0 0 1 0}

test schema-16.9 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b2 c} {
            defelement $e {}
        }
        defelement doc {
            interleave {
                element a
                group + {
                    element b1
                    element b2
                }
                element c
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b1/><b2/><c/></doc>
        <doc><b1/><b2/><a/><c/></doc>
        <doc><c/><b1/><b2/><a/></doc>
        <doc><c/><b1/><a/><b2/></doc>
        <doc><b1/><b2/><a/><b1/><b2/><c/><b1/><b2/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 0 1 0 0}

test schema-16.10 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b2 c} {
            defelement $e {}
        }
        defelement doc {
            interleave {
                element a
                group ? {
                    element b1
                    element b2
                }
                element c
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b1/><b2/><c/></doc>
        <doc><b1/><b2/><a/><c/></doc>
        <doc><c/><b1/><b2/><a/></doc>
        <doc><c/><b1/><a/><b2/></doc>
        <doc><b1/><b2/><a/><b1/><b2/><c/><b1/><b2/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 0 0 1 0}

test schema-16.11 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b2 c} {
            defelement $e {}
        }
        defelement doc {
            interleave {
                element a
                choice {
                    element b1
                    element b2
                }
                element c
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b1/><c/></doc>
        <doc><b2/><a/><c/></doc>
        <doc><c/><b1/><a/></doc>
        <doc><c/><b1/><a/><b2/></doc>
        <doc><b1/><b2/><a/><b1/><b2/><c/><b1/><b2/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 0 0 0 0}

test schema-16.12 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b2 c} {
            defelement $e {}
        }
        defelement doc {
            interleave {
                element a
                choice ? {
                    element b1
                    element b2
                }
                element c
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b1/><c/></doc>
        <doc><b2/><a/><c/></doc>
        <doc><c/><b1/><a/></doc>
        <doc><c/><b1/><a/><b2/></doc>
        <doc><b1/><b2/><a/><b1/><b2/><c/><b1/><b2/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 0 0 1 0}

test schema-16.13 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b2 c} {
            defelement $e {}
        }
        defelement doc {
            interleave {
                element a
                choice + {
                    element b1
                    element b2
                }
                element c
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b1/><c/></doc>
        <doc><b2/><a/><c/></doc>
        <doc><c/><b1/><a/></doc>
        <doc><c/><b1/><a/><b2/></doc>
        <doc><b1/><b2/><a/><b1/><b2/><c/><b1/><b2/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 1 0 0}

test schema-16.14 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b2 c} {
            defelement $e {}
        }
        defelement doc {
            interleave {
                element a
                choice * {
                    element b1
                    element b2
                }
                element c
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b1/><c/></doc>
        <doc><b2/><a/><c/></doc>
        <doc><c/><b1/><a/></doc>
        <doc><c/><b1/><a/><b2/></doc>
        <doc><b1/><b2/><a/><b1/><b2/><c/><b1/><b2/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 1 1 0}

test schema-16.15 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b11 b2 c} {
            defelement $e {}
        }
        defelement doc {
            interleave {
                element a
                choice * {
                    element b1
                    group {
                        element b11
                        element b2
                    }
                }
                element c
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><b1/><c/></doc>
        <doc><b2/><a/><c/></doc>
        <doc><c/><b1/><a/></doc>
        <doc><c/><b1/><a/><b2/></doc>
        <doc><b11/><b2/><a/><b11/><b2/><c/><b11/><b2/></doc>
        <doc><a/><c/></doc>
        <doc>12</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 0 1 0 1 1 0}


test schema-16.16 {interleave} {
    tdom::schema s
    s define {
        foreach e {a b1 b11 b2 c} {
            defelement $e {}
        }
        defelement items {
            interleave {
                element a
                element b ?
            }
            element c
        }
        defelement doc {
            element items +
        }
    }
    set result [list]
    foreach xml {
        {<doc><items><b/><a/><c/></items></doc>}
        {<doc><items><b/><a/><c/></items><items><a/><b/><c/></items></doc>}
        {<doc><items><b/><b/><c/></items><items><a/><c/></items><items><b/><a/><c/></items></doc>}
    } {
        lappend result [s validate $xml errMsg]
    }
    s delete
    set result
} {1 1 0}

test schema-16.17 {interleave with all child cp optional} {
    tdom::schema s
    s defelement doc {
        interleave {
            element a ?
            element b ?
            element c ?
        }
        element d
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><d/></doc>
        <doc><b/><d/></doc>
        <doc><c/><d/></doc>
        <doc><a/><c/><d/></doc>
        <doc><b/><c/><d/></doc>
        <doc><c/><a/><d/></doc>
        <doc><c/><a/><b/><d/></doc>
        <doc><c/><a/><b/></doc>
        <doc><d/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 1 1 1 0 1}

test schema-16.18 {interleave with all content cp optional} {
    tdom::schema s
    s defelement doc {
        interleave {
            element a ?
            element b ?
            choice {
                element c ?
                element c1 ?
                element c2 ?
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><b/></doc>
        <doc><c/></doc>
        <doc><a/><c/></doc>
        <doc><b/><c/></doc>
        <doc><c/><a/></doc>
        <doc><c/><a/><b/><d/></doc>
        <doc><c/><a/><b/></doc>
        <doc><c2/><a/><b/></doc>
        <doc><c/><b/><a/><c1/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 1 1 1 1 0 1 1 0}

test schema-16.19 {interleave with all child cp optional} {
    tdom::schema s
    s defelement doc {
        interleave {
            element a ?
            element b ?
            choice {
                element c ?
                element c1 ?
                element c2 ?
            }
        }
        element d
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><d/></doc>
        <doc><b/><d/></doc>
        <doc><c/><d/></doc>
        <doc><a/><c/><d/></doc>
        <doc><b/><c/><d/></doc>
        <doc><c/><a/><d/></doc>
        <doc><c/><a/><b/><d/></doc>
        <doc><c/><a/><b/></doc>
        <doc><d/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 1 1 1 0 1}

test schema-16.20 {interleave with all child cp optional} {
    tdom::schema s
    s defelement doc {
        interleave {
            element a ?
            element b ?
            group {
                element c ?
                element c1 ?
                element c2 ?
            }
        }
        element d
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/><d/></doc>
        <doc><b/><d/></doc>
        <doc><c/><d/></doc>
        <doc><a/><c/><d/></doc>
        <doc><b/><c/><d/></doc>
        <doc><c/><a/><d/></doc>
        <doc><c/><a/><b/><d/></doc>
        <doc><c/><a/><b/></doc>
        <doc><d/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 1 1 1 0 1}

test schema-16.21 {interleave with all child cp optional} {
    tdom::schema s
    s defelement doc {
        interleave {
            element a ?
            element b ?
            group {
                element c ?
                element c1 ?
                element c2 ?
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><b/></doc>
        <doc><c/></doc>
        <doc><a/><c/></doc>
        <doc><b/><c/></doc>
        <doc><c/><a/></doc>
        <doc><c/><a/><b/><d/></doc>
        <doc><c/><a/><b/></doc>
        <doc><c2/><a/><b/></doc>
        <doc><c/><b/><a/><c1/></doc>
        <doc><b/><c/><c2/><a/></doc>
        <doc><b/><c/><c2/><a/><c1/></doc>
        <doc><b/><c/><c1/><c2/><a/></doc>
        <doc><b/><c/><c2/><c1/><a/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 1 1 1 1 0 1 1 0 1 0 1 0}

test schema-16.22 {interleave} {
    tdom::schema s
    s defelement doc {
        interleave {
            element a 
            element b *
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><b/></doc>
        <doc><a/><b/><b/><b/></doc>
        <doc><b/><a/><b/><b/></doc>
        <doc><b/><b/><a/><b/></doc>
        <doc><b/><b/><b/><a/></doc>
        <doc><a/><c/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 0 1 1 1 1 0}

test schema-17.1 {info} {
    tdom::schema s
    s define {
        foreach e {a b1 b11 b2 c} {
            defelement $e {}
        }
    }
    set result [lsort [s info definedElements]]
    s delete
    set result
} {a b1 b11 b2 c}

test schema-17.2 {info} {
    tdom::schema s
    s define {
        defelement b {
            element b1
            element b2
        }
        defelement a {
            element a1
            element a2
        }
    }
    set result [lsort [s info definedElements]]
    s delete
    set result
} {a b}

test schema-17.3 {info} {
    tdom::schema s
    s define {
        defelement b {
            element b1 1 text
            element a
            element b2
        }
        defelement a {
            element a1
            element a2
        }
    }
    set result [lsort [s info definedElements]]
    s delete
    set result
} {a b}

test schema-17.3a {info definedElements} {
    tdom::schema s
    s define {
        prefixns {ns1 http://ns1.foo ns2 http://ns2.foo}
        defelement b ns1 {
            element b1 1 text
            element a
            element b2
        }
        defelement b ns2 {
            element b1 1 text
            element a
            element b2
        }
        defelement b {
            element b1 1 text
            element a
            element b2
        }
        defelement a {
            element a1
            element a2
        }
    }
    set result [lsort -command sortcps [s info definedElements]]
    s delete
    set result
} {a b {b http://ns1.foo} {b http://ns2.foo}}

test schema-17.4 {info} {
    tdom::schema s
    s define {
        defelement b {
            element b1 1 text
            element a
            element b2
        }
        defelement a {
            element a1
            element a2
        }
    }
    set result [s info definition b]
    s delete
    set result
} {defelement b {
            element b1 1 text
            element a
            element b2
        }}

test schema-17.5 {info expected} {
    tdom::schema s
    s define {
        defelement doc {
            choice ? {
                element a
                element c
                element b
            }
            element toplevel ?
            element musthave
            element aftermust
        }
    }
    s event start doc
    set result [s info expected]
    s delete
    lsort $result
} {a b c musthave toplevel}

test schema-17.5a {info expected -ignorematched} {
    tdom::schema s
    s define {
        defelement doc {
            choice ? {
                element a
                element c
                element b
            }
            element toplevel ?
            element musthave
            element aftermust
        }
    }
    s event start doc
    set result [s info expected -ignorematched]
    s delete
    lsort $result
} {a b c musthave toplevel}

test schema-17.5b {info expected} {
    tdom::schema s
    s define {
        defelement doc {
            choice ? {
                element a
                element c
                element b
            }
            element toplevel ?
            element musthave
            element aftermust
        }
    }
    s event start doc
    set result [s info expected -onlymandatory]
    s delete
    lsort $result
} {musthave}

test schema-17.6 {info expected} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            choice ? {
                element a
                element c
                element b
            }
            element toplevel ?
            namespace foo {
                element musthave
            }
            element aftermust
        }
    }
    s event start doc
    set result [s info expected]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel}

test schema-17.6a {info expected -ignorematched} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            choice ? {
                element a
                element c
                element b
            }
            element toplevel ?
            namespace foo {
                element musthave
            }
            element aftermust
        }
    }
    s event start doc
    set result [s info expected -ignorematched]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel}

test schema-17.6b {info expected -onlymandatory} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            choice ? {
                element a
                element c
                element b
            }
            element toplevel ?
            namespace foo {
                element musthave
            }
            element aftermust
        }
    }
    s event start doc
    set result [s info expected -onlymandatory]
    s delete
    lsort $result
} {{musthave http://foo.bar}}

test schema-17.7 {info expected} {listformat} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            mixed {
                element a
                element c
                element b
            }
            element toplevel ?
            namespace foo {
                element musthave
            }
            element aftermust
        }
    }
    s event start doc
    set result [s info expected]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel {{#text} {}}}

test schema-17.7a {info expected -ignorematched} {listformat} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            mixed {
                element a
                element c
                element b
            }
            element toplevel ?
            namespace foo {
                element musthave
            }
            element aftermust
        }
    }
    s event start doc
    set result [s info expected -ignorematched]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel {{#text} {}}}

test schema-17.7b {info expected -onlymandatory} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            mixed {
                element a
                element c
                element b
            }
            element toplevel ?
            namespace foo {
                element musthave
            }
            element aftermust
        }
    }
    s event start doc
    set result [s info expected -onlymandatory]
    s delete
    lsort $result
} {{musthave http://foo.bar}}

test schema-17.8 {info expected} {8.5} {
    tdom::schema s
    s defelement doc {
        choice ? {
            element a
            element c
            element b
        }
        element toplevel ?
        element musthave
        element aftermust
    }
    set result [s info expected]
    s define {
        foreach elm {a b c} {
            defelement $elm {}
        }
    }
    lappend result {*}[lsort [s info expected]]
    s event start doc
    lappend result {*}[lsort [s info expected]]
    s event start c
    s event end
    lappend result {*}[lsort [s info expected]]
    s delete
    set result
} {doc a b c doc a b c musthave toplevel musthave toplevel}

test schema-17.8a {info expected -ignorematched} {8.5} {
    tdom::schema s
    s defelement doc {
        choice ? {
            element a
            element c
            element b
        }
        element toplevel ?
        element musthave
        element aftermust
    }
    set result [s info expected -ignorematched]
    s define {
        foreach elm {a b c} {
            defelement $elm {}
        }
    }
    lappend result {*}[lsort [s info expected -ignorematched]]
    s event start doc
    lappend result {*}[lsort [s info expected -ignorematched]]
    s event start c
    s event end
    lappend result {*}[lsort [s info expected -ignorematched]]
    s delete
    set result
} {doc a b c doc a b c musthave toplevel musthave toplevel}

test schema-17.8b {info expected -onlymandatory} {8.5} {
    tdom::schema s
    s defelement doc {
        choice ? {
            element a
            element c
            element b
        }
        element toplevel ?
        element musthave
        element aftermust
    }
    set result [s info expected -ignorematched]
    s define {
        foreach elm {a b c} {
            defelement $elm {}
        }
    }
    lappend result {*}[lsort [s info expected -onlymandatory]]
    s event start doc
    lappend result {*}[lsort [s info expected -onlymandatory]]
    s event start c
    s event end
    lappend result {*}[lsort [s info expected -onlymandatory]]
    s delete
    set result
} {doc a b c doc musthave musthave}

proc schema-17.9 {scmd} {
    global result
    foreach e [lsort [$scmd info expected]] {
        lappend result $e
    }
}
test schema-17.9 {info expected from scripted constrain} {
    tdom::schema s
    s define {
        defpattern some {
            element a ?
            group ? {
                element b ?
                tcl schema-17.9 [self]
            }
            element c
        }
        defelement doc {
            ref some ?
            element may ?
            element must
        }
    }
    set result ""
    lappend result [s validate {<doc><must/></doc>}]
    s delete
    set result
} {a b c may must 1}

test schema-17.9.1 {info expected from scripted constrain} {
    tdom::schema s
    s define {
        defpattern some {
            element a ?
            group ? {
                element b ?
                tcl schema-17.9 [self]
            }
            element c
        }
        defelement doc {
            element othermay ?
            ref some ?
            element may ?
            element must
        }
    }
    set result ""
    lappend result [s validate {<doc><must/></doc>}]
    s delete
    set result
} {a b c may must othermay 1}

proc schema-17.9a {scmd} {
    global result
    foreach e [lsort [$scmd info expected -onlymandatory]] {
        lappend result $e
    }
}
test schema-17.9a {info expected from scripted constrain} {
    tdom::schema s
    s define {
        defpattern some {
            element a ?
            group ? {
                element b ?
                tcl schema-17.9a [self]
            }
            element c
        }
        defelement doc {
            ref some ?
            element may ?
            element must
        }
    }
    set result ""
    lappend result [s validate {<doc><must/></doc>}]
    s delete
    set result
} {must 1}

test schema-17.9a.1 {info expected from scripted constrain} {
    tdom::schema s
    s define {
        defpattern some {
            element a ?
            group ? {
                element b ?
                tcl schema-17.9a [self]
            }
            choice ! {
                element c1 
                ref some ?
            }
        }
        defelement doc {
            ref some ?
            element may ?
            element must
        }
    }
    set result ""
    lappend result [s validate {<doc><must/></doc>}]
    s delete
    set result
} {must 1}

test schema-17.10 {info expected interleave} {8.5} {
    set defs {
        {
            interleave {
                element a ?
                element b
                element c ?
            }
            element d
        }
        {
            interleave {
                element a ?
                element b ?
                element c ?
            }
            element d
        }
        {
            interleave ? {
                element a ?
                element b
                element c ?
            }
            element d
        }
    }
    set result [list]
    foreach def $defs {
        tdom::schema s
        s defelement doc $def
        s event start doc
        lappend result {*}[lsort [s info expected]]
        s delete
    }
    set result
} {a b c a b c d a b c d}

test schema-17.10a {info expected interleave} {8.5} {
    set defs {
        {
            interleave {
                element a ?
                element b
                element c ?
            }
            element d
        }
        {
            interleave {
                element a ?
                element b ?
                element c ?
            }
            element d
        }
        {
            interleave ? {
                element a ?
                element b
                element c ?
            }
            element d
        }
    }
    set result [list]
    foreach def $defs {
        tdom::schema s
        s defelement doc $def
        s event start doc
        lappend result {*}[lsort [s info expected -ignorematched]]
        s delete
    }
    set result
} {a b c a b c d a b c d}

test schema-17.11 {info expected} {
    set defs {
        {
            group + {
                element c ?
                element a ?
                element b ?
            }
            element d
        }
    }
    set result [list]
    foreach def $defs {
        tdom::schema s
        s defelement doc $def
        s event start doc
        s event start b
        s event end
        set result [lsort [s info expected]]
        s delete
    }
    set result
} {a b c d}

test schema-17.11a {info expected} {
    set defs {
        {
            group + {
                element c ?
                element a ?
                element b ?
            }
            element d
        }
    }
    set result [list]
    foreach def $defs {
        tdom::schema s
        s defelement doc $def
        s event start doc
        s event start b
        s event end
        set result [lsort [s info expected -ignorematched]]
        s delete
    }
    set result
} {d}

test schema-17.12 {info expected} {8.5} {
    tdom::schema s
    s define {
        prefixns {ns1 http://foo.bar}
        defelement doc {
            element a
            any
            any ns1 ?
            element b ?
        }
    }
    s event start doc
    s event start a
    s event end
    set result [lsort [s info expected]]
    s event start something
    s event end
    lappend result {*}[lsort [s info expected]]
    s delete
    set result
} {{<any> {}} {<any> http://foo.bar} {<elementend> {}} b}

test schema-17.12a {info expected} {8.5} {
    tdom::schema s
    s define {
        prefixns {ns1 http://foo.bar}
        defelement doc {
            element a
            any
            any ns1 ?
            element b ?
        }
    }
    s event start doc
    s event start a
    s event end
    set result [lsort [s info expected -ignorematched]]
    s event start something
    s event end
    lappend result {*}[lsort [s info expected -ignorematched]]
    s delete
    set result
} {{<any> {}} {<any> http://foo.bar} {<elementend> {}} b}

proc schema-17.13 {scmd args} {
    global fromReportCmd
    set fromReportCmd [lsort [$scmd info expected]]
}

test schema-17.13 {info expected} {8.5} {
    set defs {
        {
            element a
            element b ?
        }
        {
            element a ?
            element b
        }
        {
            element a ?
            element b ?
        }
    }
    set xmlinput {
        <doc/>
        <doc><a/></doc>
        <doc><b/></doc>
        <doc><a/><b/></doc>
        <doc><unknown/></doc>
        <doc><a/><unknown/></doc>
    }
    set result [list]
    set defnr 0
    foreach def $defs {
        tdom::schema s
        s defelement doc $def
        s reportcmd schema-17.13
        set xmlnr 0
        foreach xml $xmlinput {
            set fromReportCmd ""
            lappend result $defnr/$xmlnr: [s validate $xml errMsg]
            lappend result {*}$fromReportCmd
            incr xmlnr
        }
        s delete
        incr defnr
    }
    set result
} {0/0: 1 a 0/1: 1 0/2: 1 a 0/3: 1 0/4: 1 a 0/5: 1 {<elementend> {}} b 1/0: 1 a b 1/1: 1 b 1/2: 1 1/3: 1 1/4: 1 a b 1/5: 1 b 2/0: 1 2/1: 1 2/2: 1 2/3: 1 2/4: 1 {<elementend> {}} a b 2/5: 1 {<elementend> {}} b}

proc schema-17.13a {scmd args} {
    global fromReportCmd
    set fromReportCmd [lsort [$scmd info expected -ignorematched]]
}
test schema-17.13a {info expected} {8.5} {
    set defs {
        {
            element a
            element b ?
        }
        {
            element a ?
            element b
        }
        {
            element a ?
            element b ?
        }
    }
    set xmlinput {
        <doc/>
        <doc><a/></doc>
        <doc><b/></doc>
        <doc><a/><b/></doc>
        <doc><unknown/></doc>
        <doc><a/><unknown/></doc>
    }
    set result [list]
    set defnr 0
    foreach def $defs {
        tdom::schema s
        s defelement doc $def
        s reportcmd schema-17.13a
        set xmlnr 0
        foreach xml $xmlinput {
            set fromReportCmd ""
            lappend result $defnr/$xmlnr: [s validate $xml errMsg]
            lappend result {*}$fromReportCmd
            incr xmlnr
        }
        s delete
        incr defnr
    }
    set result
} {0/0: 1 a 0/1: 1 0/2: 1 a 0/3: 1 0/4: 1 a 0/5: 1 {<elementend> {}} b 1/0: 1 a b 1/1: 1 b 1/2: 1 1/3: 1 1/4: 1 a b 1/5: 1 b 2/0: 1 2/1: 1 2/2: 1 2/3: 1 2/4: 1 {<elementend> {}} a b 2/5: 1 {<elementend> {}} b}

proc schema-17.14 {scmd args} {
    global result
    foreach e [lsort [$scmd info expected]] {
        lappend result $e
    }
}
test schema-17.14 {info expected} {
    set defs {
        {
            group + {
                element c ?
                element a ?
                element b ?
            }
            tcl schema-17.14 [self]
            element d
        }
    }
    set result [list]
    foreach def $defs {
        tdom::schema s
        s reportcmd schema-17.14
        s defelement doc $def
        s event start doc
        s event start unknownElement
        s delete
    }
    set result
} {a b c d a b c d}

proc schema-17.14a {scmd args} {
    global result
    foreach e [lsort [$scmd info expected -ignorematched]] {
        lappend result $e
    }
}
test schema-17.14a {info expected} {
    set defs {
        {
            group + {
                element c ?
                element a ?
                element b ?
            }
            tcl schema-17.14 [self]
            element d
        }
    }
    set result [list]
    foreach def $defs {
        tdom::schema s
        s reportcmd schema-17.14
        s defelement doc $def
        s event start doc
        s event start unknownElement
        s delete
    }
    set result
} {a b c d a b c d}

proc schema-17.15 {type cmd} {
    lappend ::result $type [$cmd info stack inside]
}

test schema-17.15 {info inside} {
    tdom::schema s
    s define {
        defelement doc {
            element a *
        }
        defelement a {
            tcl schema-17.15 astart [self]
            element b ! text
            element c ! text
            tcl schema-17.15 aend [self]
        }
    }
    set result {}
    s validate {<doc><a><b>foo</b><c/></a><a><b></b><c>bar</c></a></doc>}
    s delete
    set result
} {astart {a doc} aend {a doc} astart {a doc} aend {a doc}}

test schema-17.16 {info expected} {8.5} {
    tdom::schema s
    s defelement doc {
        element a
        group {
            group {
                group {
                    element aaaa
                    element bbbb ?
                }
                element bbb ?
            }
            element bb ?
        }
        element b
    }
    set result [list]
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s reportcmd schema-17.13
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        set fromReportCmd ""
        lappend result [s validate $xml]
        lappend result {*}$fromReportCmd
    }
    s delete
    set result
} {0 0 1 1 aaaa 1 b bb bbb bbbb 1}

test schema-17.16_1{info expected} {8.5} {
    tdom::schema s
    s defelement doc {
        element a
        group {
            group {
                group {
                    element aaaa
                    element bbbb ?
                }
                element bbb ?
            }
            element bb ?
        }
        element b
    }
    set result [list]
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s reportcmd schema-17.13
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        set fromReportCmd ""
        lappend result [s validate $xml]
        lappend result {*}$fromReportCmd
    }
    s delete
    set result
} {0 0 1 1 aaaa 1 b bb bbb bbbb 1}

test schema-17.16a {info expected} {8.5} {
    tdom::schema s
    s defelement doc {
        element a
        group {
            group {
                group {
                    element aaaa *
                    element bbbb ?
                }
                element bbb ?
            }
            element bb ?
        }
        element b
    }
    set result [list]
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s reportcmd schema-17.13a
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        set fromReportCmd ""
        lappend result [s validate $xml]
        lappend result {*}$fromReportCmd
    }
    s delete
    set result
} {0 0 1 1 aaaa b bb bbb bbbb 1 b bb bbb bbbb 1}

test schema-17.16a_1 {info expected} {8.5} {
    tdom::schema s
    s defelement doc {
        element a
        group {
            group {
                group {
                    element aaaa *
                    element bbbb ?
                }
                element bbb ?
            }
            element bb ?
        }
        element b
    }
    set result [list]
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s reportcmd schema-17.13a
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        set fromReportCmd ""
        lappend result [s validate $xml]
        lappend result {*}$fromReportCmd
    }
    s delete
    set result
} {0 0 1 1 aaaa b bb bbb bbbb 1 b bb bbb bbbb 1}

test schema-17.16b {info expected} {8.5} {
    tdom::schema s
    s defelement doc {
        element a
        group {
            group {
                group {
                    element aaaa ?
                    element bbbb ?
                }
                element bbb ?
            }
            element bb ?
        }
        element b
    }
    set result [list]
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s reportcmd schema-17.13
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        set fromReportCmd ""
        lappend result [s validate $xml]
        lappend result {*}$fromReportCmd
    }
    s delete
    set result
} {0 0 1 1 aaaa b bb bbb bbbb 1 b bb bbb bbbb 1}

test schema-17.16c {info expected} {8.5} {
    tdom::schema s
    s defelement doc {
        element a
        group {
            group {
                group {
                    element aaaa +
                    element bbbb ?
                }
                element bbb ?
            }
            element bb ?
        }
        element b
    }
    set result [list]
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s reportcmd schema-17.13
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        set fromReportCmd ""
        lappend result [s validate $xml]
        lappend result {*}$fromReportCmd
    }
    s delete
    set result
} {0 0 1 1 aaaa 1 aaaa b bb bbb bbbb 1}

proc schema-17.17 {scmd args} {
    global fromReportCmd
    set fromReportCmd [list [$scmd info line] [$scmd info column]]
}
test schema-17.17 {info expected} {8.5} {
    tdom::schema s
    s defelement doc {
        element a
        group {
            group {
                group {
                    element aaaa +
                    element bbbb ?
                }
                element bbb ?
            }
            element bb ?
        }
        element b
    }
    set result [list]
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s reportcmd schema-17.17
    foreach xml {
        <doc><a/></doc>
        <doc><a/><aaaa/></doc>
        <doc><a/><aaaa/><b/></doc>
    } {
        set fromReportCmd ""
        lappend result [s validate $xml]
        lappend result {*}$fromReportCmd
    }
    s delete
    set result
} {0 0 1 1 1 9 1 1 16 1}

test schema-17.18 {info typedefinition} {
    tdom::schema s
    s prefixns {ns http://my.foo}
    s defelementtype a b ns {
        elementtype a
        elementtype a2
    }
    set result [s info typedefinition a ns]
    s delete
    set result
} {defelementtype a b http://my.foo {
        elementtype a
        elementtype a2
    }}

proc schema-17.19 {schemacmd} {
    lappend ::result [$schemacmd info stack associated]
}
test schema-17.19 {info stack associated} {
    tdom::schema s
    s defelement doc {
        element a +
    }
    s defelement a {
        associate "fo bar baz"
        tcl schema-17.19 [self]
    }
    set result [list]
    foreach xml {
        <doc><a/></doc>
        <doc><a/><a/></doc>
    } {
        lappend result [s validate $xml]
        
    }
    s delete
    set result
} {{fo bar baz} 1 {fo bar baz} {fo bar baz} 1}

test schema-17.19a {info stack associated} {
    tdom::schema s
    s defelement doc {
        element a +
    }
    s defelement a {
        associate "fo bar baz"
        tcl schema-17.19 [self]
        element b
    }
    set result [list]
    foreach xml {
        <doc><a><b/></a></doc>
        <doc><a><b/></a><a><b/></a></doc>
    } {
        lappend result [s validate $xml]
        
    }
    s delete
    set result
} {{fo bar baz} 1 {fo bar baz} {fo bar baz} 1}

proc schema-17.20 {schemacmd args} {
    lappend ::result [$schemacmd info stack associated]
}
test schema-17.20 {info stack associated} {
    tdom::schema s
    s defelement doc {
        element a +
    }
    s defelement a {
        associate "fo bar baz"
        # Only local defined
        element b ?
    }
    s reportcmd schema-17.20
    set result [list]
    foreach xml {
        <doc></doc>
        <doc><a/></doc>
        <doc><a><b/></a></doc>
        <doc><a><c/></a></doc>
        <doc><a/><b/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {{} 1 1 1 {fo bar baz} 1 {} 1}

proc schema-17.21 {scmd errorInfo} {
    lappend ::result [$scmd info expected]
}
test schema-17.21 {info expected} {
    tdom::schema s
    s defelement doc {
        element a + {}
        element b ! {}
    }
    s reportcmd schema-17.21
    set result ""
    lappend result [s validate {<doc><a/><unexpected/></doc>}]
    s delete
    set result
} {{a b} 1}

proc schema-17.21a {scmd errorInfo} {
    lappend ::result [$scmd info expected -ignorematched]
}
test schema-17.21a {info expected} {
    tdom::schema s
    s defelement doc {
        element a + {}
        element b ! {}
    }
    s reportcmd schema-17.21a
    set result ""
    lappend result [s validate {<doc><a/><unexpected/></doc>}]
    s delete
    set result
} {b 1}

proc schema-17.22 {scmd errorInfo} {
    global fromReportCmd
    if {[$scmd info vaction] eq "MATCH_ELEMENT_START"} {
        lappend fromReportCmd "matching [$scmd info vaction name]" "expecting [lsort [$scmd info expected]]"
        if {$errorInfo eq "MISSING_ELEMENT"} {
            return ignore
        }
    } else {
        lappend fromReportCmd "END_EVENT expecting [$scmd info expected]"
    }
}
test schema-17.22 {return "ignore" from recover script for MISSING_ELEMENT_MATCH_START} {8.5} {
    set defs {
        {
            element a
            element b
            element c
        }
    }
    set xmlinput {
        <doc/>
        <doc><a/></doc>
        <doc><b/></doc>
        <doc><c/></doc>
        <doc><a/><b/></doc>
        <doc><a/><c/></doc>
        <doc><b/><c/></doc>
        <doc><unknown/></doc>
        <doc><a/><unknown/></doc>
    }
    set result [list]
    set defnr 0
    foreach def $defs {
        tdom::schema s
        s defelement doc $def
        s reportcmd schema-17.22
        set xmlnr 0
        foreach xml $xmlinput {
            set fromReportCmd ""
            lappend result $defnr/$xmlnr: [s validate $xml errMsg]
            lappend result {*}$fromReportCmd
            incr xmlnr
        }
        s delete
        incr defnr
    }
    set result
} {0/0: 1 {END_EVENT expecting a} 0/1: 1 {END_EVENT expecting b} 0/2: 1 {matching b} {expecting a} {END_EVENT expecting c} 0/3: 1 {matching c} {expecting a} {matching c} {expecting b} 0/4: 1 {END_EVENT expecting c} 0/5: 1 {matching c} {expecting b} 0/6: 1 {matching b} {expecting a} 0/7: 1 {matching unknown} {expecting a} {matching unknown} {expecting b} {matching unknown} {expecting c} {matching unknown} {expecting {<elementend> {}}} 0/8: 1 {matching unknown} {expecting b} {matching unknown} {expecting c} {matching unknown} {expecting {<elementend> {}}}}

proc schema-17.23 {scmd errorInfo} {
    global fromReportCmd
    if {[$scmd info vaction] eq "MATCH_ELEMENT_START"} {
        lappend fromReportCmd "matching [$scmd info vaction name]" "expecting [lsort [$scmd info expected]]"
        if {$errorInfo in {"MISSING_ELEMENT" "UNEXPECTED_ELEMENT"}} {
            return vanish
        }
    } else {
        lappend fromReportCmd "END_EVENT expecting [$scmd info expected]"
    }
}
test schema-17.23 {return "vanish" from recover handler} {8.5} {
    set def {
        defelement doc {
            element a
            ref b
            element d ?
        }
        defpattern b {
            element b
            ref c
        }
        defpattern c {
            element c +
        }
    }
    set xmlinput {
        <doc/>
        <doc><a/></doc>
        <doc><b/></doc>
        <doc><c/></doc>
        <doc><a/><b/></doc>
        <doc><a/><c/></doc>
        <doc><b/><c/></doc>
        <doc><unknown/></doc>
        <doc><a/><unknown/></doc>
        <doc><a/><unknown/><b/><c/></doc>
        <doc><a/><unknown/><b/><c/><d/></doc>
        <doc><a/><b/><unknown/><c/></doc>
        <doc><a/><b/><unknown/><c/><d/></doc>
        <doc><a/><b/><c/><unknown/></doc>
        <doc><a/><b/><c/><unknown/><d/></doc>
        <doc><a/><b/><unknown/><c/><unknown1/><c/><d/><unknown2/><unknown3/></doc>
        <doc><a/><unknown><some>foo<unknown>content</unknown></some></unknown><b/><unknown><some>foo<unknown>content</unknown></some></unknown><c/></doc>
        <doc><a/><b/><unknown1/><unknown2/><c/><d/></doc>
    }
    set result [list]
    tdom::schema s
    s define $def
    s reportcmd schema-17.23
    set xmlnr 0
    foreach xml $xmlinput {
        set fromReportCmd ""
        lappend result $xmlnr: [s validate $xml errMsg]
        lappend result {*}$fromReportCmd
        incr xmlnr
    }
    s delete
    set result
} {0: 1 {END_EVENT expecting a} 1: 1 {END_EVENT expecting b} 2: 1 {matching b} {expecting a} {END_EVENT expecting a} 3: 1 {matching c} {expecting a} {END_EVENT expecting a} 4: 1 {END_EVENT expecting c} 5: 1 {matching c} {expecting b} {END_EVENT expecting b} 6: 1 {matching b} {expecting a} {matching c} {expecting a} {END_EVENT expecting a} 7: 1 {matching unknown} {expecting a} {END_EVENT expecting a} 8: 1 {matching unknown} {expecting b} {END_EVENT expecting b} 9: 1 {matching unknown} {expecting b} 10: 1 {matching unknown} {expecting b} 11: 1 {matching unknown} {expecting c} 12: 1 {matching unknown} {expecting c} 13: 1 {matching unknown} {expecting {<elementend> {}} c d} 14: 1 {matching unknown} {expecting {<elementend> {}} c d} 15: 1 {matching unknown} {expecting c} {matching unknown1} {expecting {<elementend> {}} c d} {matching unknown2} {expecting {<elementend> {}}} {matching unknown3} {expecting {<elementend> {}}} 16: 1 {matching unknown} {expecting b} {matching unknown} {expecting c} 17: 1 {matching unknown1} {expecting c} {matching unknown2} {expecting c}}

test schema-17.24 {info patterndefinition} {
    tdom::schema s
    set result ""
    s defpattern foo {element bar; element baz}
    lappend result [s info patterndefinition foo]
    s defpattern foo someNamespace {element e1; element e2}
    lappend result [s info patterndefinition foo someNamespace]
    lappend result [catch {s info patterndefinition dontexists} errMsg]
    lappend result $errMsg
    lappend result [catch {s info patterndefinition foo wrongNamespace} errMsg]
    lappend result $errMsg
    s delete
    set result
} {{defpattern foo {element bar; element baz}} {defpattern foo someNamespace {element e1; element e2}} 1 {Unknown pattern definition} 1 {Unknown pattern definition}}


test schema-17.25 {info definedPatterns} {
    tdom::schema create grammar
    grammar defpattern thisPattern {
        element a
        element b
    }
    grammar defpattern thatPattern someNamespace {
        element c
        element d
    }
    grammar defelement doc {
        ref thisPattern
        ref thatPattern ?
    }
    set result [lsort -index 0 [grammar info definedPatterns]]
    grammar delete
    set result
} {{thatPattern someNamespace} thisPattern}

proc schema-17.26 {scmd errorInfo} {
    global fromReportCmd
    if {$errorInfo eq "MISSING_ELEMENT" && [$scmd info vaction] eq "MATCH_ELEMENT_END"} {
        lappend fromReportCmd "END_EVENT [$scmd info vaction name]" "expecting [lsort [$scmd info expected]]"
        return "ignore"
    } else {
        lappend fromReportCmd "[$scmd info vaction] expecting [$scmd info expected]"
    }
}

test schema-17.26 {return "ignore" from recover handler for element end event} {8.5} {
    tdom::schema s
    s define {
        defelement doc {
            element a
            ref bpat
            element d
        }
        defpattern bpat {
            element b
            ref c
        }
        defpattern c {
            element c +
        }
    }
    s reportcmd schema-17.26
    set result ""
    set xmlnr 0
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><b/></doc>
        <doc><a/><b/><d/></doc>
        <doc><a/><b/><c/><d/></doc>
        <doc><a/><b/><c/><c/><c/><d/></doc>
    } {
        set ::fromReportCmd ""
        lappend result $xmlnr: [s validate $xml errMsg]
        lappend result {*}$fromReportCmd
        incr xmlnr
    }
    s delete
    set result
} {0: 1 {END_EVENT doc} {expecting a} {END_EVENT doc} {expecting b} {END_EVENT doc} {expecting d} 1: 1 {END_EVENT doc} {expecting b} {END_EVENT doc} {expecting d} 2: 1 {END_EVENT doc} {expecting c} {END_EVENT doc} {expecting d} 3: 1 {MATCH_ELEMENT_START expecting c} 4: 1 5: 1}

test schema-17.27 {return "ignore" from recover handler for element end event} {8.5} {
    tdom::schema s
    s define {
        defelement doc {
            element a
            element b
            element c
            element d
        }
    }
    s reportcmd schema-17.26
    set result ""
    set xmlnr 0
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a/><b/></doc>
        <doc><a/><b/><d/></doc>
        <doc><a/><b/><c/><d/></doc>
        <doc><a/><b/><c/><c/><c/><d/></doc>
    } {
        set ::fromReportCmd ""
        lappend result $xmlnr: [s validate $xml errMsg]
        lappend result {*}$fromReportCmd
        incr xmlnr
    }
    s delete
    set result
} {0: 1 {END_EVENT doc} {expecting a} {END_EVENT doc} {expecting b} {END_EVENT doc} {expecting c} {END_EVENT doc} {expecting d} 1: 1 {END_EVENT doc} {expecting b} {END_EVENT doc} {expecting c} {END_EVENT doc} {expecting d} 2: 1 {END_EVENT doc} {expecting c} {END_EVENT doc} {expecting d} 3: 1 {MATCH_ELEMENT_START expecting c} 4: 1 5: 1 {MATCH_ELEMENT_START expecting d}}

proc schema-17.28 {userarg scmd errType} {
    append ::result $userarg $scmd $errType
}

test schema-17.28 {reportcmd with additional args} {
    tdom::schema s
    s defelement doc {
        element a
    }
    s reportcmd "schema-17.28 foo"
    set result ""
    s validate <doc><wrong/></doc
    s delete
    set result
} foosMISSING_ELEMENT

proc schema-17.29 {args} {
    error "triggered"
}

test schema-17.29 {error in reportcmd} {
    tdom::schema s
    s defelement doc {
        element a
    }
    s reportcmd schema-17.29
    set result [catch {s validate <doc><wrong/></doc} errMsg]
    s delete
    append result $errMsg
} {1error "triggered" at line 1 character 13}

proc schema-18 {args} {
    foreach arg $args {
        lappend ::result $arg
    }
}
test schema-18.1 {reportcmd} {
    tdom::schema s
    s define {
        defelement doc {
            element e
            text {minLength 1}
            element e
        }
    }
    s reportcmd schema-18
    set result ""
    set rc [s validate {<doc><e/></doc>}]
    lappend result $rc
    s delete
    set result
} {s MISSING_TEXT 1}

test schema-18.1a {reportcmd} {
    tdom::schema s
    s define {
        defelement doc {
            element e
            text {minLength 1}
            element e
        }
    }
    s reportcmd schema-18
    set result ""
    set rc [s validate {<doc><e/><e/></doc>}]
    lappend result $rc
    s delete
    set result
} {s MISSING_TEXT 1}

test schema-18.2 {reportcmd} {
    tdom::schema s
    s define {
        defelement doc {
            element a
            element b
            element c
        }
    }
    s reportcmd schema-18
    set result ""
    set rc [s validate {<doc><a/><c/></doc>}]
    lappend result $rc
    s delete
    set result
} {s MISSING_ELEMENT 1}

test schema-18.3 {reportcmd} {
    tdom::schema s
    s define {
        defelement doc {
            element a
        }
    }
    s reportcmd schema-18
    set result ""
    foreach xml {
        <foo/>
        <bar>baz</bar>
        <bar>baz<a/>grill</bar>
        <bar><a><b/></a></bar>
    } {
        set rc [s validate $xml]
        lappend result $rc
    }
    s delete
    set result
} {s UNKNOWN_ROOT_ELEMENT 1 s UNKNOWN_ROOT_ELEMENT 1 s UNKNOWN_ROOT_ELEMENT 1 s UNKNOWN_ROOT_ELEMENT 1}

test schema-18.4 {reportcmd} {
    tdom::schema s
    s define {
        defelement doc {
            element items * {
                element item * {
                    attribute ref {integer}
                }
            }
        }
    }
    s reportcmd schema-18
    set result [list]
    foreach xml {
        {<doc><items><item ref="1"/><item ref="1"/></items><items><item ref="1"/><item ref="1"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="a"/></items><items><item ref="b"/><item ref="1"/></items></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 s INVALID_ATTRIBUTE_VALUE s INVALID_ATTRIBUTE_VALUE 1}

test schema-18.5 {reportcmd} {
    tdom::schema s
    s define {
        defelement doc {
            element items * {
                element item * {
                    text {minLength 2}
                }
            }
        }
    }
    s reportcmd schema-18
    set result [list]
    foreach xml {
        {<doc><items><item>1</item></items></doc>}
        {<doc><items><item>1</item><item/></items></doc>}
        {<doc><items><item>>12</item><item>ab</item></items></doc>}

    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {s INVALID_VALUE 1 s INVALID_VALUE s MISSING_TEXT 1 1}

test schema-18.6 {reportcmd} {
    tdom::schema s
    s define {
        defelement item {
            text {
                key lang
                minLength 2
            }
        }
        defelement items {
            keyspace lang {
                element item +
            }
        }
        defelement doc {
            element items + 
        }
    }
    s reportcmd schema-18
    set result [list]
    foreach xml {
        {<doc><items><item>12</item><item>ab</item></items></doc>}
        {<doc><items><item>12</item><item>12</item></items></doc>}
        {<doc><items><item>12</item><item>12</item></items><items><item>ab</item><item>cd</item></items></doc>}
        {<doc><items><item>12</item><item>12</item></items><items><item>ab</item><item>cd</item></items><items><item>12</item><item>12</item></items></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 s INVALID_VALUE 1 s INVALID_VALUE 1 s INVALID_VALUE s INVALID_VALUE 1}

proc schema-18.7 {args} {
    global result
    lappend result "tclcallback"
}

test schema-18.7 {reportcmd} {
    tdom::schema s
    s define {
        defelement a {}
        defelement b {}
        defelement c {}
        defelement items {
            interleave {
                element a
                element b
            }
            tcl schema-18.7
            element c
        }
        defelement doc {
            element items +
        }
    }
    s reportcmd schema-18
    set result [list]
    foreach xml {
        {<doc><items><b/><a/><c/></items></doc>}
        {<doc><items><b/><a/><c/></items><items><a/><b/><c/></items></doc>}
        {<doc><items><b/><a/><c/></items><items><b/><c/></items><items><a/><b/><c/></items></doc>}
        {<doc><items><b/><a/><c/></items><items><a/><c/></items><items><b/><a/></items></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {tclcallback 1 tclcallback tclcallback 1 tclcallback s MISSING_ELEMENT tclcallback 1 tclcallback s MISSING_ELEMENT tclcallback s MISSING_ELEMENT 1}

test schema-18.8 {reportcmd} {
    tdom::schema s
    s define {
        defelement a {}
        defelement b {}
        defelement c {}
        defelement items {
            element a
            element b
            element c
        }
        defelement doc {
            element items +
        }
    }
    s reportcmd schema-18
    set result [list]
    foreach xml {
        {<doc><items><a/><b/><c/></items><items><a/><c/></items><items><b/><a/></items></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {s MISSING_ELEMENT s MISSING_ELEMENT 1}

test schema-18.9 {reportcmd} {
    tdom::schema s
    s define {
        defelement a {}
        defelement b {}
        defelement c {}
        defelement doc {
            group + {
                element a
                element b
                element c
            }
        }
    }
    s reportcmd schema-18
    set result [list]
    foreach xml {
        {<doc><a/><b/><c/><a/><c/><b/><a/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {s MISSING_ELEMENT 1}

test schema-18.10 {reportcmd} {
    tdom::schema s
    s define {
        defelement a {}
        defelement b {}
        defelement c {}
        defelement doc {
            group + {
                element a
                element b
                group + {
                    element c
                }
            }
        }
    }
    s reportcmd schema-18
    set result [list]
    foreach xml {
        {<doc><a/><b/><c/><a/><b/><a/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {s MISSING_ELEMENT 1}

test schema-18.11 {reportcmd} {
    tdom::schema s
    s define {
        defelement a {}
        defelement b {}
        defelement c {}
        defelement doc {
            element a
            element b
            element c
        }
    }
    s reportcmd schema-18
    set result [list]
    foreach xml {
        <doc><a/><b/><c/></doc>
        <doc><a/><c/></doc>
        <doc><b/><c/></doc>
        <doc><a/><a/><b/><c/></doc>
        <doc><a/><b/><b/><c/></doc>
        <doc><a/><b/><c/><e/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 s MISSING_ELEMENT 1 s MISSING_ELEMENT 1 s MISSING_ELEMENT 1 s MISSING_ELEMENT 1 s UNEXPECTED_ELEMENT 1}

test schema-18.12 {non existing reportcmd cmd} {
    tdom::schema s
    s defelement doc {
        element a
    }
    s reportcmd ::tdom::_dontExists_
    set result [catch {s validate <doc/>} errMsg]
    lappend result $errMsg
    s delete
    set result
} {1 {error "invalid command name "::tdom::_dontExists_"" at line 1 character 6}}

proc 18-13 {scmd errType} {
    global result
    lappend result {reportcmd called}
}

test schema-18.13 {reportcmd} {
    tdom::schema s
    s define {
        defelement header {
            group {
                choice {
                    group  {
                        element prevlocs 
                        element latestloc ?
                    }
                    group  {
                        element latestloc 
                        element prevlocs ?
                    }
                }
            }
        }
    }
    s reportcmd 18-13
    set result [list]
    foreach xml {
        <header/>
        <header><prevlocs/></header>
        <header><latestloc/></header>
        <header><prevlocs/><latestloc/></header>
        <header><latestloc/><prevlocs/></header>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {{reportcmd called} 1 1 1 1 1}

proc schema-18.14 {scmd errortype} {
    lappend ::result $errortype
    lappend ::result [$scmd info expected]
    lappend ::result [$scmd info vaction]
    lappend ::result [$scmd info vaction name]
    lappend ::result [$scmd info vaction namespace]
    lappend ::result [$scmd info vaction text]
}
test schema-18.14 {info vaction in reportcmd} {listformat} {
    tdom::schema s
    s reportcmd schema-18.14
    s define {
        defelement doc {
            element e + {
                attribute attr1 {
                    fixed on
                }
                text {
                    minLength 4
                }
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><b/></doc>
        <doc><e>123</e></doc>
        {<doc><e attr1="off">1234</e></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {MISSING_ELEMENT e MATCH_ELEMENT_END doc {} {} 1 MISSING_ELEMENT e MATCH_ELEMENT_START b {} {} 1 MISSING_ATTRIBUTE {{{#text} {}}} MATCH_ELEMENT_START attr1 {} {} INVALID_VALUE {{{#text} {}}} MATCH_TEXT e {} 123 1 INVALID_ATTRIBUTE_VALUE {{{#text} {}}} MATCH_ATTRIBUTE_TEXT attr1 {} off 1}

test schema-18.15 {info vaction in reportcmd} {
    tdom::schema s
    s reportcmd schema-18.14
    s define {
        defelement doc {
            element e + {
                attribute attr1
                attribute attr2 ? {
                    minLength 3
                }
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><e attr1=""/></doc>}
        {<doc><e attr2="a"/></doc>}
        {<doc><e attr2="123" foo=""/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 INVALID_ATTRIBUTE_VALUE {{<elementend> {}}} MATCH_ATTRIBUTE_TEXT attr2 {} a MISSING_ATTRIBUTE {{<elementend> {}}} MATCH_ELEMENT_START attr1 {} {} 1 UNKNOWN_ATTRIBUTE {{<elementend> {}}} MATCH_ELEMENT_START foo {} {} MISSING_ATTRIBUTE {{<elementend> {}}} MATCH_ELEMENT_START attr1 {} {} 1}

proc appendtoresult {scmd errortype} {
    lappend ::result $errortype
}
test schema-18.16 {unexpected text} {
    set defs {
        {
            defelement doc {
                ref r1
            }
            defpattern r1 {
                element e ? {}
            }
        }
        {
            defelement doc {
                element e ? {}
            }
        }
    }
    set result [list]
    foreach def $defs {
        tdom::schema s
        s reportcmd appendtoresult
        s define $def
        lappend result [s validate {<doc>unexpected text<e/></doc>}]
        s delete
    }
    set result
} {UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1}

test schema-18.17 {unexpected text} {
    tdom::schema s
    s reportcmd appendtoresult
    s define {
        defelement doc {
            ref r1
            element c ! {}
        }
        defpattern r1 {
            element a ! {}
            element b ! {}
        }
    }
    set result [list]
    foreach xml {
        <doc>unexpected_text</doc>
        <doc><a/>unexpected_text</doc>
        <doc><a/><b/>unexpected_text</doc>
        <doc><a/><b/><c/>unexpected_text</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT 1}

proc schema-18.18 {scmd errortype} {
    lappend ::result $errortype
    lappend ::result [$scmd info expected]
}
test schema-18.18 {missing element at MATCH_ELEMENT_END} {
    set defs {
        {
            defelement doc {
                ref r1
            }
            defpattern r1 {
                element a ! {}
                element b ! {}
            }
        }
        {
            defelement doc {
                element a 1 {}
                element b 1 {}
            }
        }
        {
            defelement doc {
                element a0 ! {}
                ref r1
            }
            defpattern r1 {
                element a ! {}
                element b ! {}
            }
        }
        {
            defelement doc {
                element a0 ! {}
                ref r1
                element b0 ! {}
            }
            defpattern r1 {
                element a ! {}
                element b ! {}
            }
        }
    }
    set result [list]
    foreach def $defs {
        tdom::schema s
        s reportcmd schema-18.18
        s define $def
        lappend result [s validate {<doc/>}]
        s delete
    }
    set result
} {MISSING_ELEMENT a 1 MISSING_ELEMENT a 1 MISSING_ELEMENT a0 1 MISSING_ELEMENT a0 1}

test schema-18.19 {unexpected text} {
    tdom::schema s
    s reportcmd appendtoresult
    s define {
        defelement doc {
            ref r1 ?
            element c ? {}
        }
        defpattern r1 {
            element a ? {}
            element b ? {}
        }
    }
    set result [list]
    foreach xml {
        <doc>unexpected_text<c/></doc>
        <doc>unexpected_text<a/><c/></doc>
        <doc><a/>unexpected_text<c/></doc>
        <doc><a/>unexpected_text<b/><c/></doc>
        <doc><a/><b/>unexpected_text<c/></doc>
        <doc><a/><b/><c/>unexpected_text</doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1}

test schema-18.20 {Missing element on element end} {
    tdom::schema s
    s reportcmd appendtoresult
    s define {
        defelement doc {
            element a * {
                element b ! {}
                element c ! {}
            }
        }
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc></doc>
        <doc><a/></doc>
        <doc><a>unexpected_text</a></doc>
        <doc><a><b/>unexpected_text</a></doc>
        <doc><a><b/></a></doc>
        <doc><a><b/></a><a/></doc>
        <doc><a><b/></a><a><b/><c/></a><a><b/><c/>unexpected</a></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 MISSING_ELEMENT 1 MISSING_ELEMENT MISSING_ELEMENT 1 MISSING_ELEMENT UNEXPECTED_TEXT 1}

test schema-18.21 {reportcmd argument handling} {
    tdom::schema s
    set result ""
    lappend result [s reportcmd]
    s reportcmd ""
    lappend result [s reportcmd]
    s reportcmd dummycallback
    lappend result [s reportcmd]
    s reportcmd ""
    s reportcmd ""
    lappend result [s reportcmd]
    s reportcmd dummycallback
    lappend result [s reportcmd]
    s delete
    set result
} {{} {} dummycallback {} dummycallback}

proc schema-18.22 {that scmd errorType} {
    lappend ::result $that $errorType
}  
test schema-18.22 {reportcmd with arguments} {
    tdom::schema s 
    s reportcmd "schema-18.22 this"
    s defelement doc {
        element a
        element b
    }
    set result ""
    lappend result [s validate {<doc><a/></doc>}]
    s delete
    set result
} {this MISSING_ELEMENT 1}

proc validatedSAX {g xml {keepEmpties 1}} {
    set args [list -validateCmd $g]
    if {!$keepEmpties} {
        lappend args -ignorewhitespace 1
    }
    xml::parser p {*}$args
    set rc [catch {p parse $xml} errMsg]
    p delete
    return $rc
}

proc validatedDOM {g xml {keepEmpties 0}} {
    set args [list -validateCmd $g]
    if {$keepEmpties} {
        lappend args -keepEmpties
    }
    set rc [catch {
        set doc [dom parse {*}$args $xml]
    } errMsg]
    if {$doc ne ""} {
        $doc delete
    }
    return $rc
}

proc postValidation {g xml} {
    set doc [dom parse $xml]
    set rc [$g domvalidate $doc errMsg]
    #puts "error  : $errMsg"
    $doc delete
    return $rc
}

test schema-19.1 {keyspace} {
    tdom::schema s
    s define {
        defelement doc {
            element items * {
                keyspace ref {
                    element item * {
                        attribute ref ? {
                            key ref
                        }
                    }
                }
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><items><item ref="1"/><item ref="foo"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="1"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="1"/><item ref="foo"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="1"/><item ref="bar"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="2"/><item ref="bar"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="bar"/><item ref="bar"/></items></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 0 1 1 1 0}

test schema-19.2 {keyspace} {
    tdom::schema s
    s define {
        defelement doc {
            element items * {
                keyspace ref {
                    element item * {
                        attribute ref ? {
                            key ref
                        }
                    }
                }
            }
        }
    }
    s reportcmd schema-18
    set result [list]
    foreach xml {
        {<doc><items><item ref="1"/><item ref="1"/></items><items><item ref="1"/><item ref="1"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="a"/></items><items><item ref="c"/><item ref="d"/></items></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {s INVALID_ATTRIBUTE_VALUE s INVALID_ATTRIBUTE_VALUE 1 1}

test schema-19.3 {keyspace} {
    tdom::schema s
    s define {
        defelement doc {
            element items *
        }
        defelement items {
            keyspace my {
                element item *
            }
        }
        defelement item {
            attribute id ? {
                key my
            }
            attribute ref ? {
                keyref my
            }
        }
    }
    s reportcmd schema-18
    set result [list]
    foreach xml {
        {<doc><items><item ref="1"/><item id="1"/></items></doc>}
        {<doc><items><item ref="1" id="1"/></items></doc>}
        {<doc><items><item ref="a" id="1"/></items></doc>}
        {<doc><items><item ref="1"/><item id="1"/></items><items><item ref="1"/><item ref="1"/></items></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 s INVALID_KEYREF 1 s INVALID_KEYREF 1}

proc log19.4 {msg} {
    lappend ::result $msg
}
proc report19.4 {scmd errortype} {
    lappend ::result $errortype
}
test schema-19.4 {keyspace w/ recover} {
    tdom::schema s
    s define {
        defelement doc {
            element m * {
                tcl log19.4 "before a"
                element a ? {
                    keyspace lang {
                        element a1 ? {
                            attribute lang ? {key lang}
                        }
                    }
                    keyspace lang {
                        element a2 ? {text {key lang}}
                    }
                }
                tcl log19.4 "before b"
                element b ? {
                    keyspace lang {
                        element b1 ? {
                            attribute lang ? {key lang}
                        }
                    }
                }
            }
        }
    }
    s reportcmd report19.4
    set result [list]
    foreach xml {
        {<doc><m><a><a1 lang="en"/><a1/><a1/></a></m><m><b><b1 lang="de"/><b1/><b1/></b></m></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {{before a} UNEXPECTED_ELEMENT {before b} {before a} {before b} UNEXPECTED_ELEMENT 1}

test schema-20.1 {domunique} {
    set schema {
        prefixns {ns1 http://tdom.org/test}
        defelement doc {
            domunique ${::schema-20.1} @ref
        }
    }
    set result [list]
    foreach ::schema-20.1 {
        a
        ./../a
        /foo
        a/b
        {a | b}
        a|b
        (a|b)
        {a/b/c | b/c/d | c/d/e}
        .//a
        //a
        a/@ref
        a/b/c
        {a//b[1]/c}
        (.//b|a)/c
        ns1:a
        a/.//b/c
        {}
        {    }
        "
                "
    } {
        tdom::schema s
        lappend result [catch {s define $schema} errMsg]
        #puts $errMsg
        s delete
    }
    set result
} {0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1}

test schema-20.2 {domunique} {
    tdom::schema s
    s define {
        defelement doc {
            domunique item @ref
            element item * {
                attribute ref ?
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><item ref="1"/><item ref="foo"/></doc>}
        {<doc><item ref="1"/><item ref="1"/></doc>}
        {<doc><item/><item ref="1"/></doc>}
        {<doc><item/><item/></doc>}
    } {
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {1 0 1 0}

test schema-20.2a {domunique} {
    tdom::schema s
    s define {
        defelement doc {
            domunique item @ref itemrefkey IGNORE_EMPTY_FIELD_SET
            element item * {
                attribute ref ?
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><item ref="1"/><item ref="foo"/></doc>}
        {<doc><item ref="1"/><item ref="1"/></doc>}
        {<doc><item/><item ref="1"/></doc>}
        {<doc><item/><item/></doc>}
    } {
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {1 0 1 1}

test schema-20.2b {domunique} {
    tdom::schema s
    s define {
        defelement doc {
            domunique item @ref itemrefkey EMPTY_FIELD_SET_VALUE abc
            element item * {
                attribute ref ?
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><item ref="abc"/><item ref="foo"/></doc>}
        {<doc><item ref="abc"/><item ref="abc"/></doc>}
        {<doc><item/><item ref="abc"/></doc>}
        {<doc><item/><item/></doc>}
    } {
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {1 0 0 0}

test schema-20.3 {domunique} {
    tdom::schema s
    s define {
        defelement doc {
            element items * {
                element item * {
                    attribute ref ?
                }
                domunique item @ref
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><items><item ref="1"/><item ref="foo"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="1"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="1"/><item ref="foo"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="1"/><item ref="bar"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="2"/><item ref="bar"/></items></doc>}
        {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="bar"/><item ref="bar"/></items></doc>}
    } {
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {1 0 1 1 1 0}

test schema-20.4 {domunique} {
    tdom::schema s
    s define {
        defelement doc {
            domunique item {@ref @id}
            element item * {
                attribute ref ?
                attribute id ?
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><item ref="1"/><item ref="foo"/></doc>}
        {<doc><item ref="1"/><item ref="1"/></doc>}
        {<doc><item ref="1" id="a"/><item ref="foo" id="a"/></doc>}
        {<doc><item ref="1" id="a"/><item ref="1" id="a"/></doc>}
        {<doc><item ref="1" id="a"/><item ref="1" id="b"/></doc>}
    } {
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {1 0 1 0 1}

test schema-20.5 {domunique} {
    tdom::schema s
    s define {
        defelement doc {
            domunique item ref
            element item * {
                element ref ! text
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><item><ref>1</ref></item><item><ref>foo</ref></item></doc>}
        {<doc><item><ref>1</ref></item><item><ref>1</ref></item></doc>}
    } {
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {1 0}

proc schema-20.6 {scmd errortype} {
    lappend ::result $errortype \
        [$scmd info vaction name] \
        [$scmd info vaction text] \
        [[$scmd info domNode] nodeName]
}

test schema-20.6 {domunique} {
    tdom::schema s
    s define {
        defelement doc {
            domunique item ref itemunique
            element item * {
                element ref ! text
            }
        }
    }
    s reportcmd schema-20.6
    set result [list]
    foreach xml {
        {<doc><item><ref>1</ref></item><item><ref>foo</ref></item></doc>}
        {<doc><item><ref>foo</ref></item><item><ref>foo</ref></item></doc>}
    } {
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {1 DOM_KEYCONSTRAINT itemunique foo doc 1}

test schema-20.7 {domunique} {
    tdom::schema s
    set result [catch {s define {
        defelement doc {
            domunique item {}
            element item * {
                attribute ref ?
            }
        }
    }}]
    s delete
    set result
} {1}

test schema-21.1 {CONTENT_ARRAY_SIZE_INIT} {
    tdom::schema s
    s defelement doc {
        for {set i 1} {$i <= 30} {incr i} {
            element e ?
        }
    }
    set result [list]
    foreach xml [list <doc/> \
                     <doc>[string repeat <e/> 9]</doc> \
                     <doc>[string repeat <e/> 27]</doc>  \
                     <doc>[string repeat <e/> 37]</doc>] {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0}

test schema-22.1 {defelementtype} {
    tdom::schema s
    s defelementtype a_type a {
        element e1
    }
    s defelement doc {
        elementtype a_type
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a><e1/></a></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1}

test schema-22.2 {defelementtype} {
    tdom::schema s
    s defelement doc {
        elementtype a_type
    }
    s defelementtype a_type a {
        element e1
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a><e1/></a></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1}

test schema-22.3 {defelementtype} {
    tdom::schema s
    s defelement doc {
        elementtype a
        elementtype a2
    }
    s defelementtype a a {
        element e1
    }
    s defelementtype a2 a {
        element e2
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a><e1/></a></doc>
        <doc><a><e1/></a><a><e2/></a></doc>
        <doc><a><e1/></a><a><e1/></a></doc>
        <doc><a><e2/></a><a><e1/></a></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 1 0 0}

test schema-22.4 {defelementtype} {
    tdom::schema s
    catch {s defelement doc {
        elementtype a
        elementtype a2
        error "my"
    }}
    s defelement doc {
        elementtype a
        elementtype a2
    }
    catch {s defelementtype a a {
        element e1
        error my
    }}
    s defelementtype a a {
        element e1
    }
    catch {s defelementtype a2 a {
        element e2
        error my
    }}
    s defelementtype a2 a {
        element e2
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><a/></doc>
        <doc><a><e1/></a></doc>
        <doc><a><e1/></a><a><e2/></a></doc>
        <doc><a><e1/></a><a><e1/></a></doc>
        <doc><a><e2/></a><a><e1/></a></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 1 0 0}

test schema-22.5 {defelementtype} {
    tdom::schema s
    s prefixns {ns http://my.foo}
    s defelement doc ns {
        elementtype a
        elementtype a2
    }
    s defelementtype a a ns {
        element e1
    }
    s defelementtype a2 a ns {
        element e2
    }
    set result [list]
    foreach xml {
        {<doc xmlns='http://my.foo'/>}
        {<doc xmlns='http://my.foo'><a/></doc>}
        {<doc xmlns='http://my.foo'><a><e1/></a></doc>}
        {<doc xmlns='http://my.foo'><a><e1/></a><a><e2/></a></doc>}
        {<doc xmlns='http://my.foo'><a><e1/></a><a><e1/></a></doc>}
        {<doc xmlns='http://my.foo'><a><e2/></a><a><e1/></a></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 1 0 0}

test schema-22.6 {defelementtype} {
    tdom::schema s
    s prefixns {ns http://my.foo}
    s defelement doc ns {
        elementtype a
        elementtype a2
    }
    s defelementtype a a ns {
        elementtype e1
    }
    s defelementtype a2 a ns {
        elementtype e2
    }
    set result [lsort -index 0 [s info definedElementtypes]]
    s delete
    set result
} {{a http://my.foo} {a2 http://my.foo}}

test schema-22.6 {info definedElementtypes} {
    tdom::schema s
    s prefixns {ns1 http://ns1.foo ns2 http://ns2.foo}
    s defelementtype a a ns1 {
        elementtype e1
    }
    s defelementtype a a ns2 {
        elementtype e2
    }
    set result [lsort -command sortcps [s info definedElementtypes]]
    s delete
    set result
} {{a http://ns1.foo} {a http://ns2.foo}}

test schema-22.7 {defelementtype} {
    tdom::schema s
    s defelement doc {
        elementtype e1type
        elementtype e2type *
    }
    foreach e {e1 e2} {
        s defelementtype ${e}type $e {}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><e1/></doc>
        <doc><e1/><e2/></doc>
        <doc><e1/><e2/><e2/></doc>
        <doc><e1/><e2/><e2/><e2/></doc>
        <doc><e1/><e2/><e2/><e2/><e1/></doc>
        <doc><e2/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 1 1 1 1 0 0}

test schema-22.8 {defelementtype} {
    tdom::schema s
    s defelementtype doctype doc {
        elementtype e1type
        elementtype e2type *
    }
    foreach e {e1 e2} {
        s defelementtype ${e}type $e {}
    }
    set result [list]
    foreach xml {
        <doc/>
        <doc><e1/></doc>
        <doc><e1/><e2/></doc>
        <doc><e1/><e2/><e2/></doc>
        <doc><e1/><e2/><e2/><e2/></doc>
        <doc><e1/><e2/><e2/><e2/><e1/></doc>
        <doc><e2/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 0 0 0 0 0}

test schema-22.9 {defelementtype} {
    tdom::schema s
    s defelement doc {
        elementtype e1type
        elementtype e2type *
    }
    set result [list]
    foreach xml {
        <doc/>
        {<doc><e1 foo="bar"/></doc>}
        <doc><a/><b/></doc>
        <doc><e1/><e2>grill</e2><e2/></doc>
        <doc><e1/><e2/><e2/><e2/></doc>
        <doc><e1/><e2/><e2/><e2/><e1/></doc>
        <doc><e2/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {0 0 1 0 1 1 1}

test schema-23.1 {validatefile} {
    tdom::schema s
    s define {
        set fd [open [file join [file dir [info script]] ../doc/tmml.schema] r]
        eval [read $fd]
        close $fd
    }
    set result [s validatefile [file join [file dir [info script]] ../doc/schema.xml]]
    s delete
    set result
} 1

test schema-24.1 {validatechannel} {
    tdom::schema s
    s define {
        set fd [open [file join [file dir [info script]] ../doc/tmml.schema] r]
        eval [read $fd]
        close $fd
    }
    set fd [open [file join [file dir [info script]] ../doc/schema.xml] r]
    set result [s validatechannel $fd]
    close $fd
    s delete
    set result
} 1

test schema-25.1 {domxpathboolean} {
    tdom::schema s
    s define {
        defelement doc {
            element width ! text
            element length ! text
            element height ! text
            domxpathboolean "width * length * height <= 20000"  volumeconstraint
        }
    }
    set result [list]
    foreach xml {
        <doc><width>1</width><length>3</length><height>5</height></doc>
        <doc><width>2000.0</width><length>100.0</length><height>2.0</height></doc>
        <doc><width>2000.0</width><length>100.0</length><height>-2</height></doc>
        <doc><width>2.3</width><length>3.5</length><height>7.6</height></doc>
        <doc><width>1</width><length>1</length><height>foo</height></doc>
        <doc><width>1</width><length>1</length><height>2000-01-01</height></doc>
        <doc><width></width><length></length><height></height></doc>
    } {
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {1 0 1 1 0 0 0}

test schema-25.2 {domxpathboolean} {
    tdom::schema s
    s prefixns {
        this http://that.org
        other http://this.org
    }
        
    s define {
        defelement doc this {
            element width ! text
            namespace other {
                element length ! text
            }
            element height ! text
            domxpathboolean "this:width * other:length * this:height <= 20000"  volumeconstraint
        }
    }
    set result [list]
    foreach xml {
        {<doc xmlns="http://that.org" xmlns:foo="http://this.org"><width>1</width><foo:length>3</foo:length><height>5</height></doc>}
        {<doc xmlns="http://that.org" xmlns:foo="http://this.org"><width>2000.0</width><foo:length>100.0</foo:length><height>2.0</height></doc>}
        {<doc xmlns="http://that.org" xmlns:foo="http://this.org"><width>2000.0</width><foo:length>100.0</foo:length><height>-2</height></doc>}
        {<doc xmlns="http://that.org" xmlns:foo="http://this.org"><width>2.3</width><foo:length>3.5</foo:length><height>7.6</height></doc>}
        {<doc xmlns="http://that.org" xmlns:foo="http://this.org"><width>1</width><foo:length>1</foo:length><height>foo</height></doc>}
        {<doc xmlns="http://that.org" xmlns:foo="http://this.org"><width>1</width><foo:length>1</foo:length><height>2000-01-01</height></doc>}
        {<doc xmlns="http://that.org" xmlns:foo="http://this.org"><width></width><foo:length></foo:length><height></height></doc>}
    } {
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {1 0 1 1 0 0 0}

proc schema-25.3 {scmd errortype} {
    lappend ::result $errortype [$scmd info vaction name]
}
test schema-25.3 {domxpathboolean} {
    tdom::schema s
    s define {
        defelement doc {
            element width ! text
            element length ! text
            element height ! text
            domxpathboolean "width * length * height <= 20000"  volumeconstraint
        }
    }
    s reportcmd schema-25.3
    set result [list]
    foreach xml {
        <doc><width>1</width><length>3</length><height>5</height></doc>
        <doc><width>2000.0</width><length>100.0</length><height>2.0</height></doc>
        <doc><width>2000.0</width><length>100.0</length><height>-2</height></doc>
        <doc><width>2.3</width><length>3.5</length><height>7.6</height></doc>
        <doc><width>1</width><length>1</length><height>foo</height></doc>
        <doc><width>1</width><length>1</length><height>2000-01-01</height></doc>
        <doc><width></width><length></length><height></height></doc>
    } {
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {1 DOM_XPATH_BOOLEAN volumeconstraint 1 1 1 DOM_XPATH_BOOLEAN volumeconstraint 1 DOM_XPATH_BOOLEAN volumeconstraint 1 DOM_XPATH_BOOLEAN volumeconstraint 1}

test schema-25.4 {domxpathboolean} {
    tdom::schema s
    s define {
        defelement doc {
            element width ! text
            element length ! text
            element height ! text
            domxpathboolean "width * length * height <= 20000"  volume
            domunique width|length|height . unique
            domxpathboolean "width < length and length < height"  sequence
        }
    }
    s reportcmd schema-25.3
    set result [list]
    set nr 1
    foreach xml {
        <doc><width>1</width><length>3</length><height>5</height></doc>
        <doc><width>2000.0</width><length>100.0</length><height>2.0</height></doc>
        <doc><width>2000.0</width><length>100.0</length><height>-2</height></doc>
        <doc><width>2.3</width><length>3.5</length><height>7.6</height></doc>
        <doc><width>1</width><length>1</length><height>foo</height></doc>
        <doc><width>1</width><length>1</length><height>2000-01-01</height></doc>
        <doc><width></width><length></length><height></height></doc>
    } {
        lappend result "Nr$nr:"
        incr nr
        lappend result [postValidation s $xml]
    }
    s delete
    set result
} {Nr1: 1 Nr2: DOM_XPATH_BOOLEAN volume DOM_XPATH_BOOLEAN sequence 1 Nr3: DOM_XPATH_BOOLEAN sequence 1 Nr4: 1 Nr5: DOM_XPATH_BOOLEAN volume DOM_KEYCONSTRAINT unique DOM_XPATH_BOOLEAN sequence 1 Nr6: DOM_XPATH_BOOLEAN volume DOM_KEYCONSTRAINT unique DOM_XPATH_BOOLEAN sequence 1 Nr7: DOM_XPATH_BOOLEAN volume DOM_KEYCONSTRAINT unique DOM_XPATH_BOOLEAN sequence 1}

test schema-25.5 {domxpathboolean - xpath argument invalid} {
    tdom::schema s
    set result [catch {
        s defelement doc {
            domxpathboolean "a + + b"
        }
    } errMsg]
    lappend result $errMsg
    s delete
    set result
} {1 {Error in selector xpath: 'NodeTest: Expected "WCARDNAME" for 'a + + b' 

Parsed symbols:
     0 WCARDNAME        0 000000000     0  a
     1 PLUS             0 000000000     2  
     2 PLUS             0 000000000     4  
     3 WCARDNAME        0 000000000     6  b}}

proc ::dom::xpathFunc::compare {ctxNode pos nodeListType nodeList args} {
    if {[llength $args] != 4} {
        error "XPath function date: Expected two arguments but got
               [expr {[llength $args] / 2}]"
    }
    lassign $args arg1Typ arg1Value arg2Typ arg2Value
    set arg1 [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value]
    set arg2 [::dom::xpathFuncHelper::coerce2string $arg2Typ $arg2Value]
    return [list number [string compare $arg1 $arg2]]
}

proc schema-25.6 {scmd errorType} {
    lappend ::result $errorType [$scmd info vaction name]
}
test schema-25.6 {domxpathboolean - scripted XPath function} {8.5} {
    tdom::schema s
    s reportcmd schema-25.6
    s define {
        defelement doc {
            element a ! {
                text
                domxpathboolean {compare('foo','bar') > 0} first
                domxpathboolean {compare('foo','bar') < 0} second
            }
        }
    }
    set doc [dom parse {<doc><a>2020-07-30</a></doc>}]
    set result ""
    lappend result [s domvalidate $doc]
    set result
} {DOM_XPATH_BOOLEAN second 1}

proc schema-26.1 {scmd} {
    lappend ::result "fromtcl: [[$scmd info domNode] nodeName]"
}

test schema-26.1 {info domNode} {
    tdom::schema s
    s defelement doc {
        tcl schema-26.1 [self]
        element e ?
    }
    set result ""
    lappend result [s info domNode]
    foreach xml {
        <doc/>
        <doc><e/></doc>
        {<doc>unexpected text</doc>}
        {<doc>unexpected text<e/></doc>}
        {<doc>unexpected text<unknown/></doc>}
        <doc><unknown/></doc>
    } {
        dom parse $xml doc
        lappend result [s domvalidate $doc]
        $doc delete
    }
    s delete
    set result
} {{} {fromtcl: doc} 1 {fromtcl: doc} 1 {fromtcl: doc} 0 {fromtcl: doc} 0 {fromtcl: doc} 0 {fromtcl: doc} 0}


proc schema-26.2 {scmd errortype} {
    lappend ::result $errortype [[$scmd info domNode] nodeName]
}
test schema-26.2 {info domNode} {
    tdom::schema s
    s defelement doc {
        tcl schema-26.1 [self]
        element e ?
    }
    s reportcmd schema-26.2
    set result ""
    lappend result [s info domNode]
    foreach xml {
        <doc/>
        <doc><e/></doc>
        {<doc>unexpected text</doc>}
        {<doc>unexpected text<e/></doc>}
        {<doc>unexpected text<unknown/></doc>}
        <doc><unknown/></doc>
    } {
        dom parse $xml doc
        lappend result [s domvalidate $doc]
        $doc delete
    }
    s delete
    set result
} {{} {fromtcl: doc} 1 {fromtcl: doc} 1 {fromtcl: doc} UNEXPECTED_TEXT doc {fromtcl: doc} 1 {fromtcl: doc} UNEXPECTED_TEXT doc {fromtcl: doc} 1 {fromtcl: doc} UNEXPECTED_TEXT doc {fromtcl: doc} UNEXPECTED_ELEMENT unknown 1 {fromtcl: doc} UNEXPECTED_ELEMENT unknown 1}

proc schema-26.3 {scmd errortype} {
    lappend ::result $errortype [$scmd info domNode]
}
test schema-26.3 {info domNode} {
    tdom::schema s
    s defelement doc {
        tcl schema-26.3 [self] "fromTcl"
        element e ?
    }
    s reportcmd schema-26.3
    set result ""
    lappend result [s info domNode]
    foreach xml {
        <doc/>
        <doc><e/></doc>
        {<doc>unexpected text</doc>}
        {<doc>unexpected text<e/></doc>}
        {<doc>unexpected text<unknown/></doc>}
        <doc><unknown/></doc>
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {{} fromTcl {} 1 fromTcl {} 1 fromTcl {} UNEXPECTED_TEXT {} fromTcl {} 1 fromTcl {} UNEXPECTED_TEXT {} fromTcl {} 1 fromTcl {} UNEXPECTED_TEXT {} fromTcl {} UNEXPECTED_ELEMENT {} 1 fromTcl {} UNEXPECTED_ELEMENT {} 1}

proc schema-27.1 {args} {
    lappend ::result [::tdom::type::time 23:24:45]
}

test schema-27.1 {Called from evaluated code} {
    tdom::schema s
    s defelement doc {
        tcl schema-27.1
        element e 1
    }
    set result ""
    lappend result [s validate <doc><e/></doc>]
    s delete
    set result
} {1 1}

test schema-27.2 {Called from evaluated code} {
    tdom::schema s
    s defelement doc {
        text {
            tcl schema-27.1
        }
    }
    set result ""
    lappend result [s validate <doc>foo</doc>]
    s delete
    set result
} {1 1}

test schema-27.3 {Called from recover script} {
    tdom::schema s
    s defelement doc {
        element e 1
    }
    s reportcmd schema-27.1
    set result ""
    lappend result [s validate <doc/>]
    s delete
    set result
} {1 1}

test schema-27.4 {Called as part of validation} {
    tdom::schema s
    s defelement doc {
        tcl schema-27.1
        element e 1
    }
    set result ""
    lappend result [s validate <doc><e/></doc>]
    s delete
    set result
} {1 1}

test schema-27.5 {Called during schema script evaluation} {
    tdom::schema s
    set result ""
    s defelement doc {
        set ::result [::tdom::type::time 12:20:00]
        element e 1
    }
    s delete
    set result
} 1


test schema-27.6 {date outside schema context} {
    set result {}
    foreach txt {
        ""
        foo
        1
        12
        1234-12-31
        1234-14-31
        1234-12-00
        1234-02-31
        2000-02-29
        2001-02-29
        2004-02-29
        -2004-02-29
        1900-02-29
        1234-02-01
        1234-08-10
        1234-08-222
        " 1234-08-22"
        "1234-08-22 "
        11234-08-22
        0000-02-01
        10000-08-22
        10000-02-29
        10000-02-29Z
        2012-03-07Z
        "2012-03-07Z "
        2012-03-07a
        2012-03-07+
        2012-03-07+00:00
        2012-03-07-00:00
        2012-03-07+02:00
        2012-03-07+02:70
        2012-03-07+12:30
        2012-03-07+14:30
        2012-03-07+14:00
        2012-03-07-14:00
        2012-03-07-14:01
        2012-03-07-2:30
        2012-03-07-02:30Z
        "2012-03-07-02:30 "
        02027-02-01
    } {
        lappend result [tdom::type::date $txt]
    }
    set result
} {0 0 0 0 1 0 0 0 1 0 1 1 0 1 1 0 0 0 1 0 1 1 1 1 0 0 0 1 1 1 0 1 0 1 1 0 0 0 0 0}


test schema-27.7 {dateTime outside schema context} {
    set result ""
    foreach txt {
        ""
        foo
        1
        2020-07-08T15:58:17
        2020-07-08T15:20:00
        2020-07-08T15:20:17.7
        2020-07-08T15:58:17+02:00
        2020-07-08T15:20:17.789
        2020-07-08T15:20:17.7890
        2020-07-08T15:20:17.0
        2020-07-08T15:20:17.
        2020-07-08T15:20:17.+02:00
        2020-07-08T15:20:17.Z
        2020-07-08T15:20:17+Z
        2020-07-08T00:20
        2020-07-08T00:60:00
        2020-07-08T24:00:00
        2020-07-08T24:00:00.1
        2020-07-08T24:01:00
        2020-07-08T24:00:01
        2020-12-2215:20:00
        2020-12-22
        2020-07-08T15:20:17.789+02:00
        2020-07-08T15:20:17-02:00
        2020-07-08T15:20:17-02:00.0
        2020-07-08T15:20:17.0-02:00
        " 2020-07-08T15:20:17.0-02:00"
        "2020-07-08T15:20:17.0-02:00 "
    } {
        lappend result [tdom::type::dateTime $txt]
    }
    set result
} {0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0}

test schema-27.8 {time outside schema context} {
    set result ""
    foreach txt {
        ""
        foo
        1
        07:15:00
        07:15:00.023
        07:15:00+05:00
        07:15:00Z
        00:00:00
        24:00:00
        7:15:00
        07:15
        07:15.4:23
        12:60:12
        12:61:12
        12:71:12
        24:31:12
        25:31:12
        55:31:12
        12:31:60
        12:31:61
        12:31:77
    } {
        lappend result [tdom::type::time $txt]
    }
    set result
} {0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0}

test schema-27.9 {duration outside schema context} {
    set result ""
    foreach txt {
        ""
        foo
        1
        P2Y6M5DT12H35M30S
        P1DT2H        
        P20M
        PT20M
        P0Y20M0D
        P0Y
        -P60D
        PT1M30.5S
        P-20M
        P20MT
        P1YM5D
        P15.5Y
        P1D2H
        1Y2M
        P2M1Y
        P
        PT15.S
        PT.5S
    } {
        lappend result [tdom::type::duration $txt]
    }
    set result
} {0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0}

}
