@@ -440,23 +440,180 @@ reader.closeFile();
440440
441441## DTD Support
442442
443- The library includes comprehensive DTD (Document Type Definition) support:
443+ The library includes comprehensive DTD (Document Type Definition) support with complete Grammar generation :
444444
445- ### DTD Classes
445+ ### DTD Parser and Grammar
446446
447447``` typescript
448448import {
449449 DTDParser ,
450+ Grammar ,
451+ ContentModel ,
450452 ElementDecl ,
451453 AttListDecl ,
452454 EntityDecl ,
453455 NotationDecl ,
454456 InternalSubset
455457} from ' typesxml' ;
456458
457- // Parse DTD
459+ // Parse DTD and generate Grammar
458460const dtdParser = new DTDParser ();
459461const grammar = dtdParser .parseDTD (' schema.dtd' );
462+
463+ // Access parsed components
464+ const elementDeclarations = grammar .getElementDeclMap ();
465+ const attributeDeclarations = grammar .getAttributesMap ();
466+ const entities = grammar .getEntitiesMap ();
467+ const notations = grammar .getNotationsMap ();
468+ ```
469+
470+ ### Grammar Class
471+
472+ The ` Grammar ` class represents a complete parsed DTD with all its components:
473+
474+ #### Grammar Methods
475+
476+ | Method | Description | Returns |
477+ | --------| -------------| ---------|
478+ | ` getContentModel(elementName) ` | Get content model for an element | ` ContentModel \| undefined ` |
479+ | ` getElementDeclMap() ` | Get all element declarations | ` Map<string, ElementDecl> ` |
480+ | ` getAttributesMap() ` | Get all attribute declarations | ` Map<string, Map<string, AttDecl>> ` |
481+ | ` getElementAttributesMap(element) ` | Get attributes for specific element | ` Map<string, AttDecl> \| undefined ` |
482+ | ` getEntitiesMap() ` | Get all entity declarations | ` Map<string, EntityDecl> ` |
483+ | ` getNotationsMap() ` | Get all notation declarations | ` Map<string, NotationDecl> ` |
484+ | ` getEntity(name) ` | Get specific entity by name | ` EntityDecl \| undefined ` |
485+
486+ #### Grammar Usage Example
487+
488+ ``` typescript
489+ // Parse DTD
490+ const grammar = dtdParser .parseDTD (' bookstore.dtd' );
491+
492+ // Check element structure
493+ const bookModel = grammar .getContentModel (' book' );
494+ if (bookModel ) {
495+ console .log (' Book content type:' , bookModel .getType ());
496+ console .log (' Book children:' , [... bookModel .getChildren ()]);
497+ }
498+
499+ // Check attributes for an element
500+ const bookAttributes = grammar .getElementAttributesMap (' book' );
501+ bookAttributes ?.forEach ((attDecl , attName ) => {
502+ console .log (` ${attName }: ${attDecl .getType ()} = ${attDecl .getDefaultValue ()} ` );
503+ });
504+
505+ // Access entities
506+ const copyrightEntity = grammar .getEntity (' copyright' );
507+ if (copyrightEntity ) {
508+ console .log (' Copyright text:' , copyrightEntity .getValue ());
509+ }
510+ ```
511+
512+ ### ContentModel Class
513+
514+ The ` ContentModel ` class represents the content structure of XML elements:
515+
516+ #### Content Model Types
517+
518+ - ** EMPTY** : Element cannot contain any content
519+ - ** ANY** : Element can contain any content
520+ - ** Mixed** : Element contains #PCDATA mixed with child elements
521+ - ** Children** : Element contains only child elements (sequences/choices)
522+
523+ #### ContentModel Instance Methods
524+
525+ | Method | Description | Returns |
526+ | --------| -------------| ---------|
527+ | ` getType() ` | Get content model type | ` 'EMPTY' \| 'ANY' \| 'Mixed' \| 'Children' ` |
528+ | ` getContent() ` | Get content particles array | ` Array<ContentParticle> ` |
529+ | ` getChildren() ` | Get set of child element names | ` Set<string> ` |
530+ | ` isMixed() ` | Check if content is mixed | ` boolean ` |
531+ | ` toString() ` | Get string representation | ` string ` |
532+
533+ #### ContentModel Static Methods
534+
535+ | Method | Description | Parameters | Returns |
536+ | --------| -------------| ------------| ---------|
537+ | ` ContentModel.parse(modelString) ` | Parse content model from string | ` modelString: string ` | ` ContentModel ` |
538+
539+ #### ContentModel Usage Example
540+
541+ ``` typescript
542+ // Parse content model from DTD declaration
543+ const bookModel = ContentModel .parse (' (title, author+, (chapter | appendix)+)' );
544+
545+ console .log (' Content type:' , bookModel .getType ()); // 'Children'
546+ console .log (' String form:' , bookModel .toString ()); // '(title,author+,(chapter|appendix)+)'
547+ console .log (' Child elements:' , [... bookModel .getChildren ()]); // ['title', 'author', 'chapter', 'appendix']
548+
549+ // Check for mixed content
550+ const paraModel = ContentModel .parse (' (#PCDATA | em | strong)*' );
551+ console .log (' Is mixed:' , paraModel .isMixed ()); // true
552+ console .log (' Inline elements:' , [... paraModel .getChildren ()]); // ['em', 'strong']
553+ ```
554+
555+ ### Content Particles
556+
557+ Content models are composed of particles representing different content types:
558+
559+ #### ContentParticle Types
560+
561+ - ** DTDName** : Represents a child element name
562+ - ** DTDChoice** : Represents alternatives (A | B | C)
563+ - ** DTDSecuence** : Represents sequences (A, B, C)
564+ - ** DTDPCData** : Represents #PCDATA content
565+
566+ #### Cardinality Support
567+
568+ All particles support XML cardinality operators:
569+
570+ - ** NONE** (default): Exactly one occurrence
571+ - ** OPTIONAL** (?): Zero or one occurrence
572+ - ** ZEROMANY** (* ): Zero or more occurrences
573+ - ** ONEMANY** (+): One or more occurrences
574+
575+ ### DTD Declarations
576+
577+ #### ElementDecl
578+
579+ ``` typescript
580+ const elementDecl = grammar .getElementDeclMap ().get (' book' );
581+ console .log (' Element name:' , elementDecl .getName ());
582+ console .log (' Content spec:' , elementDecl .getContentSpec ());
583+ ```
584+
585+ #### AttDecl (Attribute Declaration)
586+
587+ ``` typescript
588+ const bookAttributes = grammar .getElementAttributesMap (' book' );
589+ const idAttr = bookAttributes ?.get (' id' );
590+ if (idAttr ) {
591+ console .log (' Attribute name:' , idAttr .getName ());
592+ console .log (' Attribute type:' , idAttr .getType ()); // 'ID', 'CDATA', etc.
593+ console .log (' Default value:' , idAttr .getDefaultValue ());
594+ console .log (' Default declaration:' , idAttr .getDefaultDecl ()); // '#REQUIRED', '#IMPLIED', etc.
595+ }
596+ ```
597+
598+ #### EntityDecl
599+
600+ ``` typescript
601+ const entities = grammar .getEntitiesMap ();
602+ entities .forEach ((entity , name ) => {
603+ console .log (` Entity ${name }: ` , entity .getValue ());
604+ console .log (' Is parameter entity:' , entity .isParameterEntity ());
605+ });
606+ ```
607+
608+ #### NotationDecl
609+
610+ ``` typescript
611+ const notations = grammar .getNotationsMap ();
612+ notations .forEach ((notation , name ) => {
613+ console .log (` Notation ${name }: ` );
614+ console .log (' Public ID:' , notation .getPublicId ());
615+ console .log (' System ID:' , notation .getSystemId ());
616+ });
460617```
461618
462619### Catalog Support
0 commit comments