tDOM

Check-in [cb70253aed]
Login

Check-in [cb70253aed]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added schema command method validatefile.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | schema
Files: files | file ages | folders
SHA3-256: cb70253aedffaacebbef8b03e399ae2c42cde5c3eeede2f2070a9c87e0e325c5
User & Date: rolf 2019-12-31 02:06:43.761
Context
2019-12-31
02:37
Added documentation for the schema command methods defelementtype and validatefile. check-in: c9e4b5af68 user: rolf tags: schema
02:06
Added schema command method validatefile. check-in: cb70253aed user: rolf tags: schema
02:05
Added test for validatefile. Closed-Leaf check-in: 747de9fb71 user: rolf tags: validatefile
00:49
Merged from trunk check-in: f212d3b0ba user: rolf tags: schema
Changes
Unified Diff Ignore Whitespace Patch
Changes to generic/schema.c.
24
25
26
27
28
29
30


















31
32
33
34
35
36
37
#ifndef TDOM_NO_SCHEMA

#include <tdom.h>
#include <tcldom.h>
#include <domxpath.h>
#include <schema.h>
#include <stdint.h>



















/* #define DEBUG */
/* #define DDEBUG */
/*----------------------------------------------------------------------------
|   Debug Macros
|
\---------------------------------------------------------------------------*/







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#ifndef TDOM_NO_SCHEMA

#include <tdom.h>
#include <tcldom.h>
#include <domxpath.h>
#include <schema.h>
#include <stdint.h>
#include <fcntl.h>

#ifdef _MSC_VER
#include <io.h>
#else
#include <unistd.h>
#endif

#ifndef TDOM_EXPAT_READ_SIZE
# define TDOM_EXPAT_READ_SIZE (1024*8)
#endif
#ifndef O_BINARY
#ifdef _O_BINARY
#define O_BINARY _O_BINARY
#else
#define O_BINARY 0
#endif
#endif

/* #define DEBUG */
/* #define DDEBUG */
/*----------------------------------------------------------------------------
|   Debug Macros
|
\---------------------------------------------------------------------------*/
2656
2657
2658
2659
2660
2661
2662



























































































2663
2664
2665
2666
2667
2668
2669
    sdata->parser = NULL;
    XML_ParserFree (parser);
    Tcl_DStringFree (&cdata);
    FREE (vdata.uri);
    while (sdata->stack) popStack (sdata);
    return result;
}




























































































static void
schemaxpathRSFree (
    xpathResultSet *rs
    )
{
    if (rs->type == StringResult) FREE (rs->string);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
    sdata->parser = NULL;
    XML_ParserFree (parser);
    Tcl_DStringFree (&cdata);
    FREE (vdata.uri);
    while (sdata->stack) popStack (sdata);
    return result;
}

static int
validateFile (
    Tcl_Interp *interp,
    SchemaData *sdata,
    char *filename
    )
{
    XML_Parser parser;
    char sep = '\xFF';
    ValidateMethodData vdata;
    Tcl_DString cdata;
    Tcl_Obj *resultObj;
    char sl[50], sc[50];
    int result, fd;

    parser = XML_ParserCreate_MM (NULL, MEM_SUITE, &sep);
    vdata.interp = interp;
    vdata.sdata = sdata;
    vdata.parser = parser;
    sdata->parser = parser;
    Tcl_DStringInit (&cdata);
    vdata.cdata = &cdata;
    vdata.onlyWhiteSpace = 1;
    vdata.uri = (char *) MALLOC (URI_BUFFER_LEN_INIT);
    vdata.maxUriLen = URI_BUFFER_LEN_INIT;
    XML_SetUserData (parser, &vdata);
    XML_SetElementHandler (parser, startElement, endElement);
    XML_SetCharacterDataHandler (parser, characterDataHandler);

    fd = open(filename, O_BINARY|O_RDONLY);
    if (fd < 0) {
        Tcl_ResetResult (interp);
        Tcl_AppendResult (interp, "error opening file \"",
                          filename, "\"", (char *) NULL);
        result = TCL_ERROR;
        goto cleanup;
    }
    for (;;) {
        int nread;
        char *fbuf = XML_GetBuffer (parser, TDOM_EXPAT_READ_SIZE);
        if (!fbuf) {
            close (fd);
            Tcl_ResetResult (interp);
            Tcl_SetResult (interp, "Out of memory\n", NULL);
            result = TCL_ERROR;
            goto cleanup;
        }
        nread = read(fd, fbuf, TDOM_EXPAT_READ_SIZE);
        if (nread < 0) {
            close (fd);
            Tcl_ResetResult (interp);
            Tcl_AppendResult (interp, "error reading from file \"",
                              filename, "\"", (char *) NULL);
            result = TCL_ERROR;
            goto cleanup;
        }
        result = XML_ParseBuffer (parser, nread, nread == 0);
        if (result != XML_STATUS_OK || !nread
            || sdata->validationState == VALIDATION_ERROR) {
            close (fd);
            break;
        }
    }
    if (result != XML_STATUS_OK
        || sdata->validationState == VALIDATION_ERROR) {
        resultObj = Tcl_NewObj ();
        sprintf(sl, "%ld", XML_GetCurrentLineNumber(parser));
        sprintf(sc, "%ld", XML_GetCurrentColumnNumber(parser));
        if (sdata->validationState == VALIDATION_ERROR) {
            Tcl_AppendStringsToObj (resultObj, "error \"",
                                    Tcl_GetStringResult (interp),
                                    "\" at line ", sl, " character ", sc, NULL);
        } else {
            Tcl_AppendStringsToObj (resultObj, "error \"",
                                    XML_ErrorString(XML_GetErrorCode(parser)),
                                    "\" at line ", sl, " character ", sc, NULL);
        }
        Tcl_SetObjResult (interp, resultObj);
        result = TCL_ERROR;
    } else {
        result = TCL_OK;
    }
cleanup:
    sdata->parser = NULL;
    XML_ParserFree (parser);
    Tcl_DStringFree (&cdata);
    FREE (vdata.uri);
    while (sdata->stack) popStack (sdata);
    return result;
}

static void
schemaxpathRSFree (
    xpathResultSet *rs
    )
{
    if (rs->type == StringResult) FREE (rs->string);
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700

3701
3702
3703
3704
3705

3706
3707
3708
3709
3710
3711
3712
    void          *namespacePtr, *savedNamespacePtr;
    char          *xmlstr, *errMsg;
    domDocument   *doc;
    domNode       *node;
    Tcl_Obj       *attData;

    static const char *schemaInstanceMethods[] = {
        "defelement", "defpattern", "start",    "event",       "delete",
        "reset",      "define",     "validate", "domvalidate", "deftext",
        "info",       "reportcmd",  "prefixns", "defelementtype", NULL

    };
    enum schemaInstanceMethod {
        m_defelement, m_defpattern, m_start,    m_event,       m_delete,
        m_reset,      m_define,     m_validate, m_domvalidate, m_deftext,
        m_info,       m_reportcmd,  m_prefixns, m_defelementtype

    };

    static const char *eventKeywords[] = {
        "start", "end", "text", NULL
    };

    enum eventKeyword







|
|
|
>


|
|
|
>







3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
    void          *namespacePtr, *savedNamespacePtr;
    char          *xmlstr, *errMsg;
    domDocument   *doc;
    domNode       *node;
    Tcl_Obj       *attData;

    static const char *schemaInstanceMethods[] = {
        "defelement", "defpattern", "start",    "event",        "delete",
        "reset",      "define",     "validate", "domvalidate",  "deftext",
        "info",       "reportcmd",  "prefixns", "validatefile",
        "defelementtype", NULL
    };
    enum schemaInstanceMethod {
        m_defelement, m_defpattern, m_start,    m_event,        m_delete,
        m_reset,      m_define,     m_validate, m_domvalidate,  m_deftext,
        m_info,       m_reportcmd,  m_prefixns, m_validatefile,
        m_defelementtype
    };

    static const char *eventKeywords[] = {
        "start", "end", "text", NULL
    };

    enum eventKeyword
4039
4040
4041
4042
4043
4044
4045






























4046
4047
4048
4049
4050
4051
4052
            } else {
                SetBooleanResult (0);
            }
        }
        schemaReset (sdata);
        break;































    case m_domvalidate:
        CHECK_EVAL
        if (objc < 3 || objc > 4) {
            Tcl_WrongNumArgs (interp, 2, objv, "<xml> ?resultVarName?");
            return TCL_ERROR;
        }
        doc = tcldom_getDocumentFromName (interp, Tcl_GetString (objv[2]),







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
            } else {
                SetBooleanResult (0);
            }
        }
        schemaReset (sdata);
        break;

    case m_validatefile:
        CHECK_EVAL
        if (objc < 3 || objc > 4) {
            Tcl_WrongNumArgs (interp, 2, objv, "<filename> ?resultVarName?");
            return TCL_ERROR;
        }
        if (sdata->validationState != VALIDATION_READY) {
            SetResult ("The schema command is busy");
            return TCL_ERROR;
        }
        xmlstr = Tcl_GetString (objv[2]);
        if (validateFile (interp, sdata, xmlstr) == TCL_OK) {
            SetBooleanResult (1);
            if (objc == 4) {
                Tcl_SetVar (interp, Tcl_GetString (objv[3]), "", 0);
            }
        } else {
            if (objc == 4) {
                Tcl_SetVar (interp, Tcl_GetString (objv[3]),
                            Tcl_GetStringResult (interp), 0);
            }
            if (sdata->evalError) {
                 result = TCL_ERROR;
            } else {
                SetBooleanResult (0);
            }
        }
        schemaReset (sdata);
        break;
        
    case m_domvalidate:
        CHECK_EVAL
        if (objc < 3 || objc > 4) {
            Tcl_WrongNumArgs (interp, 2, objv, "<xml> ?resultVarName?");
            return TCL_ERROR;
        }
        doc = tcldom_getDocumentFromName (interp, Tcl_GetString (objv[2]),
Changes to tests/schema.test.
19
20
21
22
23
24
25

26
27
28
29
30
31
32
#    schema-16.*: interleave
#    schema-17.*: info
#    schema-18.*: reportcmd
#    schema-19.*: keyspace
#    schema-20.*: domunique
#    schema-21.*: internal: buffers
#    schema-22.*: defelementtype, elementtype

#
# Copyright (c) 2018-2019 Rolf Ade.

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

if {[dom featureinfo schema]} {








>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#    schema-16.*: interleave
#    schema-17.*: info
#    schema-18.*: reportcmd
#    schema-19.*: keyspace
#    schema-20.*: domunique
#    schema-21.*: internal: buffers
#    schema-22.*: defelementtype, elementtype
#    schema-23.*: validatefile
#
# Copyright (c) 2018-2019 Rolf Ade.

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

if {[dom featureinfo schema]} {

7165
7166
7167
7168
7169
7170
7171
7172






7173







        {<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}







}















>
>
>
>
>
>
|
>
>
>
>
>
>
>
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
        {<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-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] errMsg]
    puts $errMsg
    s delete
    set result
} 1

}