DTD (Document Type Definition)

DTD je další technologie podporovaná knihovnou libxml2. Je to jednoduchý jazyk na popis obsahu XML dokumentu. DTD může být součástí XML dokumentu (jako v příkladu config.xml), nebo může být v extra souboru, na který se XML odkazuje.

DTD vám říká, jaké elementy a atributy se mohou/musí v XML vyskytovat, v jakém pořadí a co může být jejich hodnotou.

DTD můžete použít pro kontrolu, zda XML dokument obsahuje to, co má. Alespoň přibližně. Novější jazyk pro popis XML, XML Schema dokáže popsat XML dokument podrobněji, ale není (zatím) podporován knihovnou libxml2.

Pokud dokument XML odpovídá XML pravidlům, říká se o něm, že je well-formed, tedy správně strukturovaný. Bez toho by vám nefungoval DOM ani SAX parser ani jiné XML nástroje.

Pokud obsah dokumentu XML odpovídá DTD (nebo XML Schema), říká se o něm, že je valid, tedy významově validní.

DTD můžete používat k tomu, aby vám program zkontroloval, že se v něm nachází to co má a neobsahuje, to co nemá. DTD ale taky vůbec používat nemusíte, když nechcete.

V této kapitole se nebudu zabývat popisem DTD jako takového (na to si najdětě jiný tutoriál), ale popíši, jak můžete XML dokument zvalidovat pomocí libxml2.

Dělá se to v zásadě zavoláním jedné funkce: xmlValidateDocument(). Tato funkce potřebuje odkaz na xmlDoc strukturu, kterou získáte např. funkcí xmlParseFile() a na strukturu xmlValidCtxt, kterou získáte zavoláním xmlNewValidCtxt(). Tuto strukturu nakonec uvolníte voláním xmlFreeValidCtxt().

Funkce xmlValidateDocument() defaultně vypisuje chyby na obrazovku. Pokud se vám toto chování nehodí, můžete definovat funkce pro zpracování chyb a varování a přiřadit odkazy na tyto funkce do kontextu xmlValidCtxt. Povinné to není, ale v příkladu níže jsem tyto funkce použil.

  1. /*------------------------------------------------*/
  2. /* 27cDtd/dtd.h                                   */
  3. #include <stdio.h>
  4. #include <libxml/parser.h>
  5. #include <libxml/valid.h>
  6.  
  7. void onWarning(void * ctx, const char * msg, ...) {
  8.         va_list ap;
  9.         va_start(ap, msg);
  10.         printf("WARNING: ");
  11.         vprintf(msg, ap);
  12.         printf("****\n");
  13.         va_end(ap);
  14. }
  15.  
  16. void onError(void * ctx, const char * msg, ...) {
  17.         va_list ap;
  18.         va_start(ap, msg);
  19.         printf("ERROR: ");
  20.         vprintf(msg, ap);
  21.         printf("****\n");
  22.         va_end(ap);
  23. }
  24.  
  25. int main(void) {
  26.     xmlDocPtr doc;
  27.     xmlValidCtxtPtr ctxt = xmlNewValidCtxt();
  28.     int valid;
  29.     ctxt->error = onError;
  30.     ctxt->warning = onWarning;
  31.     doc = xmlParseFile("config.xml");
  32.     if (doc == NULL) {
  33.         fprintf(stderr, "Document se nepodařilo naparsovat.\n");
  34.         return 1;
  35.     }
  36.        
  37.    valid = xmlValidateDocument(ctxt, doc);
  38.    if(valid)
  39.         printf("Document je validní.\n");
  40.    else
  41.         printf("Dokument není validní.\n");
  42.    
  43.  
  44.    xmlFreeValidCtxt(ctxt);
  45.    return 0;
  46. }
  47. /*------------------------------------------------*/

Nainstalujte si balíček libxml2-devel. Bez toho tento příklad nepřeložíte. Překlad může vypadat takto:

$ clang -o dtd -g -Wall `xml2-config --cflags --libs` dtd.c

Výstup z programu je tentokrát trochu nudný:

Document je validní.

Zkuste si ale změnit config.xml tak, aby neodpovídal DTD a sledujte co se stane. Třeba odstranění elementu minor způsobí toto:

ERROR: Element version content does not follow the DTD, expecting (major , minor), got (major )
****
Dokument není validní.
Komentář Hlášení chyby
Created: 6.9.2014
Last updated: 10.10.2014
Tato stánka používá ke svému běhu cookies, díky kterým je možné monitorovat, co tu provádíte (ne že bych to bez cookies nezvládl). Také vás tu bude špehovat google analytics. Jestli si myslíte, že je to problém, vypněte si cookies ve vašem prohlížeči, nebo odejděte a už se nevracejte :-). Prohlížením tohoto webu souhlasíte s používáním cookies. Dozvědět se více..