This file is indexed.

/usr/lib/ocaml/pxp-engine/pxp_dtd.mli is in libpxp-ocaml-dev 1.2.4-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 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
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
(* $Id: pxp_dtd.mli 738 2009-02-02 03:27:35Z gerd $
 * ----------------------------------------------------------------------
 * PXP: The polymorphic XML parser for Objective Caml.
 * Copyright by Gerd Stolpmann. See LICENSE for details.
 *)

(** DTD objects 

    The DTD object is a separate container for the formal requirements
    of a document. The DTD object is always present in a document,
    even when validation is turned off. See {!classtype: Pxp_dtd.dtd}
    for details about the DTD object.

    There are a number of accompanying objects also defined in this
    module (e.g. [namespace_manager] or [dtd_element]). 
 *)

(** {fixpxpcoretypes true} *) (* Set back to false at the end of the file *)

(**/**)
type validation_record =
    { content_model   : Pxp_core_types.I.content_model_type;
      content_dfa     : Pxp_dfa.dfa_definition option Lazy.t;
      id_att_name     : string option;
      idref_att_names : string list;
      att_lookup      : int Pxp_aux.Str_hashtbl.t;
      init_att_vals   : (string * Pxp_core_types.I.att_value) array;
      att_info        : (Pxp_core_types.I.att_type * bool) array;
      att_required    : int list;
      accept_undeclared_atts : bool;
    }
  (** This is an internal structure used to pass validation information 
   * efficiently from the DTD to the document nodes.
   * Please do not use this type in your own programs.
   *)
(**/**)

  (** This class manages mappings from URIs to normalized prefixes. For every
   * namespace a namespace_manager object contains a set that maps
   * various URI's to the same normalized prefix [np]:
   * {[ uri1 |-> np, uri2 |-> np, ..., uriN |-> np ]}
   * The normalized prefix [np] is characterstical of the namespace, and
   * identifies the namespace uniquely.
   * The first URI [uri1] is the primary URI, the other URIs are aliases.
   *
   * In order to create an empty namespace, call
   * {!Pxp_dtd.create_namespace_manager}.
   *
   * See {!Intro_namespaces} for an introduction to namespaces and more
   * links to other explanations about namespace managers.
   *
   * The following operations are supported:
   * - [add_namespace np uri]: adds a new mapping [uri |-> np] to the
   *   manager. Neither [np] nor [uri] must already be part of another
   *   mapping in the manager.
   * - [add_uri np uri]: adds a new alias [uri] for an existing namespace
   *   which is identified by the normprefix [np]. The normprefix [np]
   *   must already be part of a mapping which is then extended by this
   *   method.
   * - [lookup_or_add_namespace p uri]: If there is already some mapping
   *   [uri |-> np], the normprefix [np] is simply returned ("lookup"). In this
   *   case [p] is ignored. Otherwise [uri] is not yet mapped, and in this
   *   case some unique [np] must be found such that [uri |-> np] can be
   *   added ([add_namespace]). First, the passed prefix [p] is tried.
   *   If [p] is free, it can be taken as new normprefix: [np = p]. Otherwise
   *   some number [n] is found such that the concatenation [p ^ n] is free:
   *   [np = p ^ n]. The operation returns [np].
   *
   * {b Encodings:} prefixes and URIs are always encoded in the default
   * encoding of the document
   *)
class namespace_manager :
  object
    method add_namespace : string -> string -> unit
      (** [add_namespace np uri]: adds a new namespace to the object. The
       * namespace is identified by the normprefix [np] and contains initially
       * the primary URI [uri].
       * The method fails ([Namespace_error]) if either [np] already identifies
       * some namespace or if [uri] is already member of some namespace.
       * Nothing happens if [uri] is the sole member of the namespace [np].
       * It is required that [np <> ""].
       *)

    method add_uri : string -> string -> unit
      (** [add_uri np uri]: adds [uri] as alias URI to the namespace identified
       * by the normprefix [np] (see above for detailed semantics). The method
       * raises [Namespace_prefix_not_managed] if the normprefix [np] is unknown
       * to the object,
       * and it fails ([Namespace_error]) if the [uri] is member of a
       * different namespace. Nothing happens if the [uri] is already member
       * of the namespace [np].
       *
       * {b Change in PXP 1.2:} Using exception [Namespace_prefix_not_managed]
       * instead of [Not_found].
       *)

    method lookup_or_add_namespace : string -> string -> string
      (** [lookup_or_add_namespace p uri]: first, the method looks up if
       * the namespace for [uri] does already exist. If so, [p] is ignored,
       * and the method returns the normprefix identifying the namespace.
       * Otherwise, a new namespace is added for some normprefix [np] which
       * initially contains [uri]. The normprefix [np] is calculated upon [p]
       * serving as suggestion for the normprefix. The method returns
       * the normprefix.
       *)

    method get_primary_uri : string -> string
      (** Return the primary URI for a normprefix, or raises
       * [Namespace_prefix_not_managed]. [get_uri ""] raises always this
       * exception.
       *)

    method get_uri_list : string -> string list
      (** Return all URIs for a normprefix, or [[]] if the normprefix is
       * unused. [get_uri_list ""] returns always [[]]. The last URI of the
       * returned list is the primary URI.
       *)

    method get_normprefix : string -> string
      (** Return the normprefix for a URI, or raises 
       * [Namespace_not_managed].
       *)

    method iter_namespaces : (string -> unit) -> unit
      (** Iterates over all namespaces contained in the object, and
       * calls the passed function for every namespace. The argument of the
       * invoked function is the normprefix of the namespace.
       *)

    method as_declaration : (string * string) list
      (** Returns the list of normprefixes and primary URIs. Useful
       * to create the corresponding namespace scope, e.g.
       * {[new namespace_scope_impl mng None (mng#as_declaration) ]}
       *)

  end
;;


val create_namespace_manager : unit -> namespace_manager
  (** Preferred way of creating a [namespace_manager] *)


(** The recursive class type [namespace_scope] represents the original
 * namespace declarations found in the XML text. A single [namespace_scope]
 * object contains a list of declared namespaces
 * {[ [ (dp1, uri1); (dp2; uri2); ... ] ]}
 * corresponding to the "xmlns"-type declarations found in a single
 * XML element:
 * {[ <element xmlns:dp1="uri1" xmlns:dp2="uri2" ... > ]}
 * For the declaration of a default namespace [xmlns="uri"] the pair
 * [("",uri)] must be included in the list. The special pair [("","")]
 * means that the former default namespace is "undeclared".
 *
 * Furthermore, the [namespace_scope] object may have a parent 
 * [namespace_scope], representing the namespace declarations in the
 * surrounding XML text. [namespace_scope] objects are intentionally
 * immutable. When some XML subtree is cut out of a document
 * and inserted into another document, the original [namespace_scope]
 * declarations (including
 * all parents) are still applied to the subtree when it is in the
 * new document. Further changes in the old document cannot break this
 * assertion because of the immutability.
 *
 * The [namespace_scope] objects are connected with the [namespace_manager]
 * to allow translations from the namespace prefixes found in the XML
 * text (also called "display prefixes" from now on) to the normalized
 * prefixes stored in the [namespace_manager], and vice versa.
 *
 * Call {!Pxp_dtd.create_namespace_scope} to create a scope object using
 * the default implementation.
 *
 * See {!Intro_namespaces} for an introduction to namespaces and more
 * links to other explanations about scopes.
 *)
class type namespace_scope =
object
  method namespace_manager : namespace_manager
    (** Returns the [namespace_manager] to which this scope object is
     * connected
     *)

  method parent_scope : namespace_scope option
    (** Returns the parent object, if any *)

  method declaration : (string * string) list
    (** Returns the list of namespace declarations of this scope (i.e.
     * the declarations in parent objects are not considered). The
     * list contains pairs [ (display_prefix, uri) ].
     *)

  method effective_declaration : (string * string) list
    (** Returns the list of namespace declarations of this scope and
     * all parent scopes. The list contains pairs [ (display_prefix, uri) ].
     * Prefixes hidden by earlier declarations are suppressed in the list
     *)

  method display_prefix_of_uri : string -> string
    (** Translates the URI to the corresponding display prefix as declared
     * in this object or any parent object. Raises [Namespace_not_in_scope]
     * when the declaration cannot be found.
     *)

  method display_prefix_of_normprefix : string -> string
    (** Translates the normalized prefix to the corresponding display
     * prefix as declared in this object or any parent object. Raises
     * [Namespace_not_in_scope] when the declaration cannot be found, and
     * [Namespace_prefix_not_managed] when the
     * normalized prefix is unknown to the namespace manager.
     *)

  method uri_of_display_prefix : string -> string
    (** Translates the display prefix to the corresponding URI as
     * declared in this object or any parent object. Raises
     * [Not_found] when the declaration cannot be found.
     *)

  method normprefix_of_display_prefix : string -> string
    (** Translates the display prefix to the corresponding normalized
     * prefix as declared in this object or any parent object. Raises
     * [Not_found] when the declaration cannot be found, and
     * [Namespace_not_managed] when the
     * namespace manager does not know the namespace.
     *)
end
;;


class namespace_scope_impl : 
        namespace_manager -> 
	namespace_scope option ->
	(string * string) list ->
	  namespace_scope
   (** An implementation of [namespace_scope]. New scopes are created by
    * {[ new namespace_scope_impl mng parent_opt decl ]}
    * where [mng] is the namespace managaer, [parent_opt] is the optional
    * parent scope, and [decl] is the declaration list.
    *)


val create_namespace_scope : 
    ?parent:namespace_scope -> 
    ?decl:(string * string) list ->
    namespace_manager ->
      namespace_scope
  (** Preferred way of creating a [namespace_scope] *)
    

  (** DTD objects have two purposes:
       - They are containers for global declarations that apply to the
         whole XML document. This includes the character set, the
         standalone declaration, and all declaration that can appear
         in the "DTD part" of a document.
       - Also, they express formal constraints the document must fulfill
         such as validity, or (less ambitious) well-formedness.

      Normally, programmers neither need to create such objects, nor to
      fill them with data, as the parser already does this. If it is required
      to create a DTD object, the recommended function is
      {!Pxp_dtd.create_dtd}.

      Despite its name, this object does not only define the DTD as
      such (i.e. what would be found in a ".dtd" file), but all formal
      requirements of documents that are needed by PXP. This also includes:
        - The name of the root element
        - The character encoding of the document
        - Whether validation is on or off
        - The namespace manager
        - Whether the document is declared as standalone

      A consequence of this is that even documents have a DTD object
      that only have to comply to the relatively weak well-formedness
      constraints.

      For some introductory words about well-formedness mode, see
      {!Intro_getting_started.wfmode}.
   *)
class dtd :
  ?swarner:Pxp_core_types.I.symbolic_warnings ->
  Pxp_core_types.I.collect_warnings -> 
  Pxp_core_types.I.rep_encoding ->
object
  method root : string option
    (** get the name of the root element if present. This is the name
       * following "<!DOCTYPE". If there is no DOCTYPE declaration, 
       * this method will return None.
     *)

    method set_root : string -> unit
      (** set the name of the root element. This method can be invoked 
       * only once (usually by the parser)
       *)

    method id : Pxp_core_types.I.dtd_id option
      (** get the identifier for this DTD. Possible return values:
       * - [None]: There is no DOCTYPE declaration, or only
       *    [<!DOCTYPE name>]
       * - [Some Internal]: There is a DOCTYPE declaration with material
       *    in brackets like [ <!DOCTYPE name [ declarations ... ]> ]
       * - [Some(External xid)]: There is a DOCTYPE declaration with
       *    a SYSTEM or PUBLIC identifier (described by [xid]), but without
       *    brackets, i.e. [ <!DOCTYPE name SYSTEM '...'> ] or 
       *    [ <!DOCTYPE name PUBLIC '...' '...'> ].
       * - [Some(Derived xid)]: There is a DOCTYPE declaration with
       *    a SYSTEM or PUBLIC identifier (described by [xid]), {b and} with
       *    brackets
       *)

    method set_id : Pxp_core_types.I.dtd_id -> unit
      (** set the identifier. This method can be invoked only once *)

    method encoding : Pxp_core_types.I.rep_encoding
      (** returns the encoding used for character representation *)

    method lexer_factory : Pxp_lexer_types.lexer_factory
      (** Returns a lexer factory for the character encoding *)


    method allow_arbitrary : unit
      (** This method sets the [arbitrary_allowed] flag. This flag disables
       * a specific validation constraint, namely that all elements 
       * need to be declared in the DTD. This feature is used
       * to implement the well-formedness mode: In this mode, the element,
       * attribute, and notation declarations found in the textual DTD are ignored, and not
       * added to this DTD object. As the [arbitrary_allowed] flag is also
       * set, the net effect is that all validation checks regarding
       * the values of elements and attributes are omitted. The flag is
       * automatically set if the parser is called using one of the 
       * "wf" functions, e.g. {!Pxp_tree_parser.parse_wfdocument_entity}.
       *
       * Technically, the [arbitrary_allowed] flag changes the behaviour of
       * the [element] and [notation] methods defined below so that they
       * raise [Undeclared] instead of [Validation_error] when an unknown
       * element or notation name is encountered.
       *)

    method disallow_arbitrary : unit
      (** Clears the [arbitrary_allowed] flag again *)

    method arbitrary_allowed : bool
      (** Returns whether arbitrary contents are allowed or not. *)

    method standalone_declaration : bool
      (** Whether there is a 'standalone' declaration or not. *)

    method set_standalone_declaration : bool -> unit
      (** Sets the 'standalone' declaration. *)


    method namespace_manager : namespace_manager
      (** For namespace-aware implementations of the node class, this method
       * returns the namespace manager. If the namespace manager has not been
       * set, the exception [Not_found] is raised.
       *)

    method set_namespace_manager : namespace_manager -> unit
      (** Sets the namespace manager as returned by [namespace_manager].
       *)

    method add_element : dtd_element -> unit
      (** add the given element declaration to this DTD. Raises [Not_found]
       * if there is already an element declaration with the same name.
       *)

    method add_gen_entity : Pxp_entity.entity -> bool -> unit
      (** [add_gen_entity e extdecl]:
       * add the entity [e] as general entity to this DTD (general entities
       * are those represented by [&name;]). If there is already a declaration
       * with the same name, the second definition is ignored; as exception from
       * this rule, entities with names "lt", "gt", "amp", "quot", and "apos"
       * may only be redeclared with a definition that is equivalent to the
       * standard definition; otherwise a [Validation_error] is raised.
       *
       * [extdecl]: true indicates that the entity declaration occurs in
       * an external entity. (Used for the standalone check.)
       *)

    method add_par_entity : Pxp_entity.entity -> unit
      (** add the given entity as parameter entity to this DTD (parameter
       * entities are those represented by %name;). If there is already a 
       * declaration with the same name, the second definition is ignored.
       *)

    method add_notation : dtd_notation -> unit
      (** add the given notation to this DTD. If there is already a declaration
       * with the same name, a [Validation_error] is raised.
       *)

    method add_pinstr : proc_instruction -> unit
      (** add the given processing instruction to this DTD. *)

    method element : string -> dtd_element
      (** looks up the element declaration with the given name. Raises 
       * [Validation_error] if the element cannot be found. If the
       * [arbitrary_allowed] flag is set, however, 
       * [Undeclared] is raised instead.
       *)

    method element_names : string list
      (** returns the list of the names of all element declarations. *)

    method gen_entity : string -> (Pxp_entity.entity * bool)
      (** [let e, extdecl = obj # gen_entity n]:
       * looks up the general entity [e] with the name [n]. Raises
       * [WF_error] if the entity cannot be found.
       *
       * [extdecl]: indicates whether the entity declaration occured in an 
       * external entity.
       *)

    method gen_entity_names : string list
      (** returns the list of all general entity names *)

    method par_entity : string -> Pxp_entity.entity
      (** looks up the parameter entity with the given name. Raises
       * [WF_error] if the entity cannot be found.
       *)

    method par_entity_names : string list
      (** returns the list of all parameter entity names *)

    method notation : string -> dtd_notation
      (** looks up the notation declaration with the given name. Raises
       * [Validation_error] if the notation cannot be found. If the
       * [arbitrary_allowed] flag is sez, however, 
       * [Undeclared] is raised instead.
       *)

    method notation_names : string list
      (** Returns the list of the names of all added notations *)

    method pinstr : string -> proc_instruction list
      (** looks up all processing instructions with the given target.
       * The "target" is the identifier following [<?].
       *)

    method pinstr_names : string list
      (** Returns the list of the names (targets) of all added pinstrs *)

    method validate : unit
      (** ensures that the DTD is valid. This method is optimized such that
       * actual validation is only performed if DTD has been changed.
       * If the DTD is invalid, in most cases a [Validation_error] is raised,
       * but other exceptions are possible, too.
       *)

    method only_deterministic_models : unit
      (** Succeeds if all regexp content models are deterministic. 
       * Otherwise [Validation_error].
       *)

    method write : 
             ?root:string ->
             Pxp_core_types.I.output_stream -> 
	     Pxp_core_types.I.encoding -> 
	     bool -> 
	       unit
      (** [write os enc doctype]:
       * Writes the DTD as [enc]-encoded string to [os]. If [doctype], a 
       * DTD like [ <!DOCTYPE root [ ... ]> ] is written. If [not doctype],
       * only the declarations are written (the material within the
       * square brackets).
       *
       * The entity definitions are not written. However, it is ensured that
       * the generated string does not contain any reference to an entity.
       * The reason for the omission of the entites is that there is no
       * generic way of writing references to external entities.
       *
       * Option [root]: Override the name of the root element in  the 
       * DOCTYPE clause.
       *)

    method write_ref : 
             ?root:string ->
             Pxp_core_types.I.output_stream -> 
	     Pxp_core_types.I.encoding -> 
	       unit
     (** [write_ref os enc]:
      * Writes a reference to the DTD as [enc]-encoded string to [os].
      * The reference looks as follows:
      * {[
      *   <!DOCTYPE root SYSTEM ... > or
      *   <!DOCTYPE root PUBLIC ... >
      * ]}
      * Of course, the DTD must have an external ID:
      * - dtd#id = External(System ...) or
      * - dtd#id = External(Public ...)
      *
      * If the DTD is internal or mixed, the method [write_ref] will fail.
      * If the ID is anonymous or private, the method will fail, too.
      *
      * Option [root]: Override the name of the root element in  the 
      * DOCTYPE clause.
      *)

    (**/**)
    (*----------------------------------------*)
    method invalidate : unit
      (* INTERNAL METHOD *)
    method warner : Pxp_core_types.I.collect_warnings
      (* INTERNAL METHOD *)
    method swarner : Pxp_core_types.I.symbolic_warnings option
      (* INTERNAL METHOD *)
  end

(* ---------------------------------------------------------------------- *)

(** A single element declaration that can be added to the DTD object.
   * Element declarations are created by
   *   {[ new dtd_element init_dtd init_name ]}
   * This creates a new [dtd_element] object for [init_dtd] with [init_name].
   * The strings are represented in the same encoding as [init_dtd].
 *)
and dtd_element : dtd -> string -> 
  object

    method name : string
      (** returns the name of the declared element *)

    method externally_declared : bool
      (** returns whether the element declaration occurs in an external
       * entity.
       *)

    method content_model : Pxp_core_types.I.content_model_type
      (** get the content model of this element declaration, or [Unspecified] *)

    method content_dfa : Pxp_dfa.dfa_definition option
      (** return the DFA of the content model if there is a DFA, or [None].
       * A DFA exists only for regexp style content models which are
       * deterministic.
       *)

    method set_cm_and_extdecl : 
             Pxp_core_types.I.content_model_type -> bool -> unit
      (** [set_cm_and_extdecl cm extdecl]:
       * set the content model to [cm]. Once the content model is not 
       * [Unspecified], it cannot be set to a different value again.
       * Furthermore, it is set whether the element occurs in an external
       * entity ([extdecl]).
       *)

    method encoding : Pxp_core_types.I.rep_encoding
      (** Return the encoding of the strings *)

    method allow_arbitrary : unit
      (** This method sets the [arbitrary_allowed] flag for this element.
        * The effect of this flag is to ignore the validation constraint
        * that attributes for this element needs to be declared. Note that
        * this mode is not required for implementing the well-formedness
        * mode, because for this it is already sufficient to set the
        * same-named flag in the global DTD object. Setting this flag for
        * certain elements may still be useful, however. It is then possible
        * to allow arbitrary attributes for certain elements only.
        *
        * Technically, the [arbitrary_allowed] flag changes the behaviour of
        * the [attribute] method defined below so that it
        * raises [Undeclared] instead of [Validation_error] when an unknown
        * attribute name is encountered.
       *)

    method disallow_arbitrary : unit
      (** Clears the [arbitrary_allowed] flag *)

    method arbitrary_allowed : bool
      (** Returns whether arbitrary attributes are allowed or not. *)

    method attribute : string -> 
                         Pxp_core_types.I.att_type * Pxp_core_types.I.att_default
      (** get the type and default value of a declared attribute, or raise
       * [Validation_error] if the attribute does not exist.
       * If the [arbitrary_allowed] flag is set, the exception [Undeclared] 
       * is raised instead of [Validation_error].
       *)

    method attribute_violates_standalone_declaration : 
               string -> string option -> bool
      (** [attribute_violates_standalone_declaration name v]:
       * Checks whether the attribute [name] violates the standalone
       * declaration if it has value [v].
       * The method returns true if:
       * - The attribute declaration occurs in an external entity,
       *
       * and if one of the two conditions holds:
       * - [v = None], and there is a default for the attribute value
       * - [v = Some s], and the type of the attribute is not CDATA,
       *   and [s] changes if normalized according to the rules of the
       *   attribute type.
       *
       * The method raises [Validation_error] if the attribute does not exist.
       * If the [arbitrary_allowed] flag is set, the exception [Undeclared] 
       * is raised instead of [Validation_error].
       *)

    method attribute_names : string list
      (** get the list of all declared attributes *)

    method names_of_required_attributes : string list
      (** get the list of all attributes that are specified as required 
       * attributes
       *)

    method id_attribute_name : string option
      (** Returns the name of the attribute with type ID, or [None]. *)

    method idref_attribute_names : string list
      (** Returns the names of the attributes with type IDREF or IDREFS. *)

    method add_attribute : string -> 
                           Pxp_core_types.I.att_type -> 
			   Pxp_core_types.I.att_default -> 
			   bool ->
			     unit
      (** [add_attribute name type default extdecl]:
       * add an attribute declaration for an attribute with the given name,
       * type, and default value. If there is more than one declaration for
       * an attribute name, the first declaration counts; the other declarations
       * are ignored.
       *
       * [extdecl]: if true, the attribute declaration occurs in an external
       * entity. This property is used to check the "standalone" attribute.
       *)

    method validate : unit
      (** checks whether this element declaration (i.e. the content model and
       * all attribute declarations) is valid for the associated DTD.
       * Raises mostly [Validation_error] if the validation fails.
       *)

    (**/**)

    method write : 
             Pxp_core_types.I.output_stream -> Pxp_core_types.I.encoding -> unit
      (* write os enc:
       * Writes the <!ELEMENT ... > declaration to 'os' as 'enc'-encoded string.
       *)

    method internal_vr : validation_record
      (* INTERNAL METHOD: Returns the validation record for this element type. 
       *)
  end

(* ---------------------------------------------------------------------- *)

(** A single notation declaration that can be added to the DTD object.
   * Notation declarations are created by
   *  {[ new dtd_notation a_name an_external_ID init_encoding ]}
   * This creates a new dtd_notation object with the given name and the given
   * external ID.
   *)
and dtd_notation : 
       string -> Pxp_core_types.I.ext_id -> Pxp_core_types.I.rep_encoding ->
  object
    method name : string
    method ext_id : Pxp_core_types.I.ext_id
    method encoding : Pxp_core_types.I.rep_encoding

    (**/**)

    method write : 
             Pxp_core_types.I.output_stream -> Pxp_core_types.I.encoding -> unit
      (* write_compact_as_latin1 os enc:
       * Writes the <!NOTATION ... > declaration to 'os' as 'enc'-encoded 
       * string.
       *)

  end

(* ---------------------------------------------------------------------- *)

(** A single processing instruction occuring in DTD scope. This instruction
   * can also be added to the DTD object, Creation:
   *  {[ new proc_instruction a_target a_value ]}
   * creates a new proc_instruction object with the given target string and
   * the given value string. 
   * Note: A processing instruction is written as [ <?target value?> ]. 
   *)
and proc_instruction : string -> string -> Pxp_core_types.I.rep_encoding ->
  object
    method target : string
    method value : string
    method encoding : Pxp_core_types.I.rep_encoding

    method parse_pxp_option : (string * string * (string * string) list)
      (** Parses a PI containing a PXP option. Such PIs are formed like:
       *  {[ <?target option-name option-att="value" option-att="value" ... ?> ]}
       * The method returns a triple
       *   {[ (target, option-name, [option-att, value; ...]) ]}
       * or raises [Error].
       *)

    (**/**)

    method write : 
             Pxp_core_types.I.output_stream -> Pxp_core_types.I.encoding -> unit
      (* write os enc:
       * Writes the <?...?> PI to 'os' as 'enc'-encoded string.
       *)

  end

;;

val create_dtd :
      ?swarner:Pxp_core_types.I.symbolic_warnings ->
      ?warner:Pxp_core_types.I.collect_warnings -> 
      Pxp_core_types.I.rep_encoding ->
	dtd
  (** Preferred way of creating a DTD. Example:
   * {[ let dtd = create_dtd 
   *             ?swarner:config.swarner
   *             ~warner:config.warner
   *             config.encoding]}
   *
   * See also {!Pxp_dtd_parser.create_empty_dtd}, which creates a DTD
   * from a {!Pxp_types.config} record.
   *)


(* ---------------------------------------------------------------------- *)

(**/**)
type source =
    Entity of ((dtd -> Pxp_entity.entity) * Pxp_reader.resolver)
  | ExtID of (Pxp_core_types.I.ext_id * Pxp_reader.resolver)
  | XExtID of (Pxp_core_types.I.ext_id * string option * Pxp_reader.resolver)
  (* Sources are pairs of (1) names of entities to open, and (2) methods
   * of opening entities. See Pxp_yacc for more documentation.
   *)
(**/**)

(* ---------------------------------------------------------------------- *)

(** Useful properties of entities: The following submodule exports all 
 * stable properties of the entity classes. Please use this module, and
 * not [Pxp_entity] to access entities.
 *
 * Note that the types [entity] and [entity_id] are also exported
 * by {!Pxp_types}.
 *)
module Entity : sig
  val get_name : Pxp_entity.entity -> string
      (** Return the name of the entity. *)

  val get_full_name : Pxp_entity.entity -> string
      (** The full name includes the ID, too (for diagnostics messages) *)
 
  val get_encoding : Pxp_entity.entity -> Pxp_core_types.I.rep_encoding
      (** Return the encoding of the internal representation of the entity *)

  val get_type : Pxp_entity.entity -> 
                   [ `External | `Internal | `NDATA ]
      (** Returns the type of the entity. *)

  val replacement_text : Pxp_entity.entity -> string
      (** Return the replacement text of the entity. Works for both
       * internal and external entities. The replacement text is the
       * "right side" of the entity definition.
       *)

  val get_xid : Pxp_entity.entity -> Pxp_core_types.I.ext_id option
      (** Returns the external ID for external and NDATA entities, and None
       * for internal entities
       * 
       * TRAP: The external ID may be a relative SYSTEM ID, and it is not
       * known to which base ID the relative ID must be resolved. So the
       * external ID may be meaningless.
       *)

  val get_resolver_id : Pxp_entity.entity -> Pxp_core_types.I.resolver_id option
      (** Returns the resolver ID for external entities, and None for other
       * entities. This is the version as returned by the [active_id] method
       * by the resolver.
       * The resolver ID contains more information than the external ID,
       * for example the base URL relative to which SYSTEM IDs should
       * be interpreted.
       *)

  (* CHECK: There is still no base URL for NDATA entities *)

  val get_notation : Pxp_entity.entity -> string option
      (** Returns the notation of NDATA entities, and None for the other
       * entity types
       *)

  val create_internal_entity : 
      name:string -> value:string -> dtd -> Pxp_entity.entity
      (** Creates an internal entity. The name and the value must be
       * encoded in the same encoding as the DTD.
       * Note that if the entity is to be used as parameter entity,
       * the first and the last characters of the value should be 
       * spaces.
       *)

  val create_ndata_entity :
      name:string -> xid:Pxp_core_types.I.ext_id -> notation:string -> dtd -> 
	Pxp_entity.entity
      (** Creates an NDATA entity. The name and the notation must be encoded
       * in the same encoding as the DTD. The external ID must be encoded
       * as UTF-8 string (like all external IDs).
       *)

  val create_external_entity :
      ?doc_entity:bool ->
      ?system_base:string ->
      name:string -> 
      xid:Pxp_core_types.I.ext_id -> 
      resolver:Pxp_reader.resolver ->
      dtd ->
	Pxp_entity.entity
      (** Creates a reference to an external entity. The name must be encoded
       * in the same encoding as the DTD. The external ID must be encoded
       * as UTF-8 string (like all external IDs).
       *
       * - [doc_entity]: If true, the entity is a document entity. XML requires
       *   some additional restrictions for document entities. The default for
       *   the argument is false.
       * - [system_base]: The base URL if SYSTEM identifiers are passed 
       *   as [xid]
       *)

  val from_external_source :
      ?doc_entity:bool ->
      name:string -> 
      dtd -> 
      source -> 
	Pxp_entity.entity
	  (** Creates an external entity that reads from the passed 
              {!Pxp_types.source} 
	   *)

  val entity_id : Pxp_entity.entity -> Pxp_lexer_types.entity_id
    (** Returns the abstract entity ID *)

  val lookup : Pxp_lexer_types.entity_id ->  Pxp_entity.entity
    (** Looks the entity up for an entitiy ID *)

  val create_entity_id : unit -> Pxp_lexer_types.entity_id
    (** Create a new abstract entity ID. This ID can be used whereever
     * an [entity_id] is expected but no entity is available, except that
     * the back coercion [lookup] is not supported, and will raise
     * [Invalid_argument].
     *)

end
;;


(** {fixpxpcoretypes false} *)