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

Overview
Comment:Fixed content constrain command "any": respect prefix/ns mapping. More work on info nextexpected.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wip
Files: files | file ages | folders
SHA3-256: 223307a111729607a6042997d9b390128f79643494e436cbc9d52d1060e1cb8d
User & Date: rolf 2019-10-08 06:22:11
Original Comment: Fixed any content constrain command: respect prefix/ns mapping. More work on info nextexpected.
Context
2019-10-09
16:25
Settled for a list of unique possible next content (which special entries for any and text) in unspecific order as result of the nextexpected subcommand of the info method. Closed-Leaf check-in: 35c7ad95de user: rolf tags: wip
2019-10-08
06:22
Fixed content constrain command "any": respect prefix/ns mapping. More work on info nextexpected. check-in: 223307a111 user: rolf tags: wip
2019-10-07
09:33
Renamed the info method subcommand frontexpected of the validation commands to the hopefully better name nextexpected. check-in: d889feb189 user: rolf tags: wip
Changes

Changes to generic/schema.c.

2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813

2814
2815
2816
2817
2818
2819
2820
....
2825
2826
2827
2828
2829
2830
2831

2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842

2843
2844
2845
2846
2847







2848
2849

2850
2851
2852
2853
2854



2855
2856
2857
2858
2859
2860
2861
....
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
....
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932

2933

2934
2935
2936
2937
2938
2939
2940
....
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
        if (cp->flags & FORWARD_PATTERN_DEF
            || cp->flags & PLACEHOLDER_PATTERN_DEF) continue;
        elmObj = serializeElementName (interp, cp);
        Tcl_ListObjAppendElement (interp, rObj, elmObj);
    }
}

static void
getNextExpected (
    SchemaData *sdata,
    SchemaValidationStack *se,
    Tcl_Interp *interp,
    Tcl_HashTable *seenCPs,
    Tcl_Obj *rObj
    )
{
    int ac, hm, i, hnew, mustMatch;
    SchemaCP *cp, *ic, *jc;
    SchemaValidationStack *se1;


    getContext (cp, ac, hm);
    if (hm && maxOne(cp->quants[ac])) ac++;
    switch (cp->type) {
    case SCHEMA_CTYPE_INTERLEAVE:
        ac = 0;
        mustMatch = 0;
................................................................................
            if (se->interleaveState
                && se->interleaveState[ac]
                && maxOne (cp->quants[ac])) {
                ac++;
                continue;
            }
            ic = cp->content[ac];

            switch (ic->type) {
            case SCHEMA_CTYPE_NAME:
                Tcl_ListObjAppendElement (interp, rObj,
                                          serializeElementName (interp, ic));
                break;
            case SCHEMA_CTYPE_INTERLEAVE:
            case SCHEMA_CTYPE_PATTERN:
                Tcl_CreateHashEntry (seenCPs, ic, &hnew);
                if (hnew) {
                    se1 = getStackElement (sdata, ic);
                    getNextExpected (sdata, se1, interp, seenCPs, rObj);

                    repoolStackElement (sdata, se1);
                }
                break;

            case SCHEMA_CTYPE_ANY:







                Tcl_ListObjAppendElement (interp, rObj,
                                          Tcl_NewStringObj ("<any>", 5));

                break;

            case SCHEMA_CTYPE_TEXT:
                Tcl_ListObjAppendElement (interp, rObj,
                                          Tcl_NewStringObj ("#text", 5));



                break;
                
            case SCHEMA_CTYPE_CHOICE:
                if (ic->flags & MIXED_CONTENT) {
                    Tcl_ListObjAppendElement (interp, rObj,
                                              Tcl_NewStringObj ("#text", 5));
                }
................................................................................
                            );
                        break;
                    case SCHEMA_CTYPE_INTERLEAVE:
                    case SCHEMA_CTYPE_PATTERN:
                        Tcl_CreateHashEntry (seenCPs, jc, &hnew);
                        if (hnew) {
                            se1 = getStackElement (sdata, ic);
                            getNextExpected (sdata, se1, interp, seenCPs,
                                              rObj);
                            repoolStackElement (sdata, se1);
                        }
                        break;
                    case SCHEMA_CTYPE_ANY:
                        Tcl_ListObjAppendElement (
                            interp, rObj, Tcl_NewStringObj ("<any>", 5)
                            );
................................................................................
                break;

            case SCHEMA_CTYPE_VIRTUAL:
            case SCHEMA_CTYPE_KEYSPACE:
            case SCHEMA_CTYPE_KEYSPACE_END:
                break;
            }
            if (minOne (cp->quants[ac])) {
                if (cp->type == SCHEMA_CTYPE_INTERLEAVE) mustMatch = 1;
                else break;
            }
            ac++;
        }
        break;
        
    case SCHEMA_CTYPE_ANY:
    case SCHEMA_CTYPE_CHOICE:
    case SCHEMA_CTYPE_TEXT:
    case SCHEMA_CTYPE_VIRTUAL:
    case SCHEMA_CTYPE_KEYSPACE:
    case SCHEMA_CTYPE_KEYSPACE_END:
        Tcl_Panic ("Invalid CTYPE onto the validation stack!");
    }
    if (cp->type == SCHEMA_CTYPE_NAME) {
        return;
    }
    if (cp->type == SCHEMA_CTYPE_INTERLEAVE && mustMatch) {
        return;
    }
    if (se->down) {
        hm = se->down->hasMatched;
        se->down->hasMatched = 1;
        getNextExpected (sdata, se->down, interp, seenCPs, rObj);
        se->down->hasMatched = hm;

    }

}

static int
schemaInstanceInfoCmd (
    SchemaData *sdata,
    Tcl_Interp *interp,
    int objc,
................................................................................
    Tcl_Obj *const objv[]
    )
{
    SchemaData *sdata = GETASI;
    SchemaCP *pattern;
    SchemaQuant quant;
    char *ns = NULL;
    int n, m, hnew;
    Tcl_HashEntry *h;

    CHECK_SI
    CHECK_TOPLEVEL
    checkNrArgs (1,3,"?namespace? ?quant?");
    if (objc == 1) {
        quant = SCHEMA_CQUANT_ONE;
    } else if (objc == 2) {    
        quant = getQuant (interp, sdata, objv[1], &n, &m);
        if (quant == SCHEMA_CQUANT_ERROR) {
            h = Tcl_CreateHashEntry (&sdata->namespace,
                                     Tcl_GetString (objv[1]), &hnew);
            ns = Tcl_GetHashKey (&sdata->namespace, h);
            quant = SCHEMA_CQUANT_ONE;
        }
    } else {
        h = Tcl_CreateHashEntry (&sdata->namespace,
                                 Tcl_GetString (objv[1]), &hnew);
        ns = Tcl_GetHashKey (&sdata->namespace, h);
        quant = getQuant (interp, sdata, objv[2], &n, &m);
        if (quant == SCHEMA_CQUANT_ERROR) {
            return TCL_ERROR;
        }
    }
    pattern = initSchemaCP (SCHEMA_CTYPE_ANY, ns, NULL);
    REMEMBER_PATTERN (pattern)







|








|


>







 







>










|
>





>
>
>
>
>
>
>
|
|
>





>
>
>







 







|
|







 







|
|
|
<













|


|




|

>

>







 







|
<









<
|
<



<
|
<







2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
....
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
....
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
....
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922

2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
....
3727
3728
3729
3730
3731
3732
3733
3734

3735
3736
3737
3738
3739
3740
3741
3742
3743

3744

3745
3746
3747

3748

3749
3750
3751
3752
3753
3754
3755
        if (cp->flags & FORWARD_PATTERN_DEF
            || cp->flags & PLACEHOLDER_PATTERN_DEF) continue;
        elmObj = serializeElementName (interp, cp);
        Tcl_ListObjAppendElement (interp, rObj, elmObj);
    }
}

static int
getNextExpected (
    SchemaData *sdata,
    SchemaValidationStack *se,
    Tcl_Interp *interp,
    Tcl_HashTable *seenCPs,
    Tcl_Obj *rObj
    )
{
    int ac, hm, i, hnew, mustMatch, mayskip, rc;
    SchemaCP *cp, *ic, *jc;
    SchemaValidationStack *se1;
    Tcl_Obj *thisObj;

    getContext (cp, ac, hm);
    if (hm && maxOne(cp->quants[ac])) ac++;
    switch (cp->type) {
    case SCHEMA_CTYPE_INTERLEAVE:
        ac = 0;
        mustMatch = 0;
................................................................................
            if (se->interleaveState
                && se->interleaveState[ac]
                && maxOne (cp->quants[ac])) {
                ac++;
                continue;
            }
            ic = cp->content[ac];
            mayskip = 0;
            switch (ic->type) {
            case SCHEMA_CTYPE_NAME:
                Tcl_ListObjAppendElement (interp, rObj,
                                          serializeElementName (interp, ic));
                break;
            case SCHEMA_CTYPE_INTERLEAVE:
            case SCHEMA_CTYPE_PATTERN:
                Tcl_CreateHashEntry (seenCPs, ic, &hnew);
                if (hnew) {
                    se1 = getStackElement (sdata, ic);
                    mayskip = getNextExpected (sdata, se1, interp, seenCPs,
                                               rObj);
                    repoolStackElement (sdata, se1);
                }
                break;

            case SCHEMA_CTYPE_ANY:
                if (ic->namespace) {
                    thisObj = Tcl_NewObj();
                    Tcl_AppendStringsToObj (thisObj, ic->namespace,
                                            ":<any>", NULL);
                        
                    Tcl_ListObjAppendElement (interp, rObj, thisObj);
                } else {
                    Tcl_ListObjAppendElement (interp, rObj,
                                              Tcl_NewStringObj ("<any>", 5));
                }
                break;

            case SCHEMA_CTYPE_TEXT:
                Tcl_ListObjAppendElement (interp, rObj,
                                          Tcl_NewStringObj ("#text", 5));
                if (ic->nc == 0 || checkText (interp, ic, "")) {
                    mayskip = 1;
                }
                break;
                
            case SCHEMA_CTYPE_CHOICE:
                if (ic->flags & MIXED_CONTENT) {
                    Tcl_ListObjAppendElement (interp, rObj,
                                              Tcl_NewStringObj ("#text", 5));
                }
................................................................................
                            );
                        break;
                    case SCHEMA_CTYPE_INTERLEAVE:
                    case SCHEMA_CTYPE_PATTERN:
                        Tcl_CreateHashEntry (seenCPs, jc, &hnew);
                        if (hnew) {
                            se1 = getStackElement (sdata, ic);
                            mayskip = getNextExpected (sdata, se1, interp,
                                                       seenCPs, rObj);
                            repoolStackElement (sdata, se1);
                        }
                        break;
                    case SCHEMA_CTYPE_ANY:
                        Tcl_ListObjAppendElement (
                            interp, rObj, Tcl_NewStringObj ("<any>", 5)
                            );
................................................................................
                break;

            case SCHEMA_CTYPE_VIRTUAL:
            case SCHEMA_CTYPE_KEYSPACE:
            case SCHEMA_CTYPE_KEYSPACE_END:
                break;
            }
            if (cp->type == SCHEMA_CTYPE_INTERLEAVE && minOne(cp->quants[ac]))
                mustMatch = 1;
            else if (!mayskip && minOne (cp->quants[ac])) break;

            ac++;
        }
        break;
        
    case SCHEMA_CTYPE_ANY:
    case SCHEMA_CTYPE_CHOICE:
    case SCHEMA_CTYPE_TEXT:
    case SCHEMA_CTYPE_VIRTUAL:
    case SCHEMA_CTYPE_KEYSPACE:
    case SCHEMA_CTYPE_KEYSPACE_END:
        Tcl_Panic ("Invalid CTYPE onto the validation stack!");
    }
    if (cp->type == SCHEMA_CTYPE_NAME) {
        return 0;
    }
    if (cp->type == SCHEMA_CTYPE_INTERLEAVE && mustMatch) {
        return 0;
    }
    if (se->down) {
        hm = se->down->hasMatched;
        se->down->hasMatched = 1;
        rc = getNextExpected (sdata, se->down, interp, seenCPs, rObj);
        se->down->hasMatched = hm;
        return rc;
    }
    return 1;
}

static int
schemaInstanceInfoCmd (
    SchemaData *sdata,
    Tcl_Interp *interp,
    int objc,
................................................................................
    Tcl_Obj *const objv[]
    )
{
    SchemaData *sdata = GETASI;
    SchemaCP *pattern;
    SchemaQuant quant;
    char *ns = NULL;
    int n, m;


    CHECK_SI
    CHECK_TOPLEVEL
    checkNrArgs (1,3,"?namespace? ?quant?");
    if (objc == 1) {
        quant = SCHEMA_CQUANT_ONE;
    } else if (objc == 2) {    
        quant = getQuant (interp, sdata, objv[1], &n, &m);
        if (quant == SCHEMA_CQUANT_ERROR) {

            ns = getNamespacePtr (sdata, Tcl_GetString (objv[1]));

            quant = SCHEMA_CQUANT_ONE;
        }
    } else {

        ns = getNamespacePtr (sdata, Tcl_GetString (objv[1]));

        quant = getQuant (interp, sdata, objv[2], &n, &m);
        if (quant == SCHEMA_CQUANT_ERROR) {
            return TCL_ERROR;
        }
    }
    pattern = initSchemaCP (SCHEMA_CTYPE_ANY, ns, NULL);
    REMEMBER_PATTERN (pattern)

Changes to tests/schema.test.

2128
2129
2130
2131
2132
2133
2134




























2135
2136
2137
2138
2139
2140
2141
....
4947
4948
4949
4950
4951
4952
4953














































4954
4955
4956
4957
4958
4959
4960
        {<doc><e4></doc>}
    } {
        lappend result [grammar validate $xml]
    }
    grammar delete
    set result
} {0 1 0 1 1 1 0}





























test schema-10.1 {any} {
    tdom::schema create s
    s define {
        defelement doc {
            element a
            any
................................................................................
        s defelement doc $def
        s event start doc
        lappend result {*}[s info nextexpected]
        s delete
    }
    set result
} {a b c a b c d a b c d}















































proc schema-18 {args} {
    lappend ::result {*}$args
}
test schema-18.1 {reportcmd} {
    tdom::schema s
    s define {







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







 







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







2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
....
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
        {<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-10.1 {any} {
    tdom::schema create s
    s define {
        defelement doc {
            element a
            any
................................................................................
        s defelement doc $def
        s event start doc
        lappend result {*}[s info nextexpected]
        s delete
    }
    set result
} {a b c a b c d a b c d}

test schema-17.11 {info nextexpected interleave} {
    set defs {
        {
            group + {
                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
        s event start b
        s event end
        set result [s info nextexpected]
        s delete
    }
    set result
} {c a b c d}

test schema-17.12 {info nextexpected interleave} {
    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 [s info nextexpected]
    s event start something
    s event end
    lappend result {*}[s info nextexpected]
    s delete
    set result
} {<any> http://foo.bar:<any> b}

proc schema-18 {args} {
    lappend ::result {*}$args
}
test schema-18.1 {reportcmd} {
    tdom::schema s
    s define {