2
* debugXML.c : This is a set of routines used for debugging the tree
3
* produced by the XML parser.
5
* See Copyright for the status of this software.
7
* Daniel Veillard <daniel@veillard.com>
12
#ifdef LIBXML_DEBUG_ENABLED
21
#include <libxml/xmlmemory.h>
22
#include <libxml/tree.h>
23
#include <libxml/parser.h>
24
#include <libxml/parserInternals.h>
25
#include <libxml/valid.h>
26
#include <libxml/debugXML.h>
27
#include <libxml/HTMLtree.h>
28
#include <libxml/HTMLparser.h>
29
#include <libxml/xmlerror.h>
30
#include <libxml/globals.h>
31
#include <libxml/xpathInternals.h>
32
#include <libxml/uri.h>
33
#ifdef LIBXML_SCHEMAS_ENABLED
34
#include <libxml/relaxng.h>
37
#define DUMP_TEXT_TYPE 1
39
typedef struct _xmlDebugCtxt xmlDebugCtxt;
40
typedef xmlDebugCtxt *xmlDebugCtxtPtr;
41
struct _xmlDebugCtxt {
42
FILE *output; /* the output file */
43
char shift[101]; /* used for indenting */
44
int depth; /* current depth */
45
xmlDocPtr doc; /* current document */
46
xmlNodePtr node; /* current node */
47
xmlDictPtr dict; /* the doc dictionnary */
48
int check; /* do just checkings */
49
int errors; /* number of errors found */
50
int nodict; /* if the document has no dictionnary */
51
int options; /* options */
54
static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
57
xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt)
64
ctxt->output = stdout;
70
for (i = 0; i < 100; i++)
76
xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED)
78
/* remove the ATTRIBUTE_UNUSED when this is added */
84
* @ns: the namespace node
86
* Check that a given namespace is in scope on a node.
88
* Returns 1 if in scope, -1 in case of argument error,
89
* -2 if the namespace is not in scope, and -3 if not on
93
xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
97
if ((node == NULL) || (ns == NULL))
100
if ((node->type != XML_ELEMENT_NODE) &&
101
(node->type != XML_ATTRIBUTE_NODE) &&
102
(node->type != XML_DOCUMENT_NODE) &&
103
(node->type != XML_TEXT_NODE) &&
104
(node->type != XML_HTML_DOCUMENT_NODE) &&
105
(node->type != XML_XINCLUDE_START))
108
while ((node != NULL) &&
109
((node->type == XML_ELEMENT_NODE) ||
110
(node->type == XML_ATTRIBUTE_NODE) ||
111
(node->type == XML_TEXT_NODE) ||
112
(node->type == XML_XINCLUDE_START))) {
113
if ((node->type == XML_ELEMENT_NODE) ||
114
(node->type == XML_XINCLUDE_START)) {
116
while (cur != NULL) {
119
if (xmlStrEqual(cur->prefix, ns->prefix))
126
/* the xml namespace may be declared on the document node */
127
if ((node != NULL) &&
128
((node->type == XML_DOCUMENT_NODE) ||
129
(node->type == XML_HTML_DOCUMENT_NODE))) {
130
xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
138
xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
142
if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
143
if (ctxt->depth < 50)
144
fprintf(ctxt->output, &ctxt->shift[100 - 2 * ctxt->depth]);
146
fprintf(ctxt->output, ctxt->shift);
152
* @ctxt: a debug context
153
* @error: the error code
155
* Handle a debug error.
158
xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
161
__xmlRaiseError(NULL, NULL, NULL,
162
NULL, ctxt->node, XML_FROM_CHECK,
163
error, XML_ERR_ERROR, NULL, 0,
164
NULL, NULL, NULL, 0, 0,
168
xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
171
__xmlRaiseError(NULL, NULL, NULL,
172
NULL, ctxt->node, XML_FROM_CHECK,
173
error, XML_ERR_ERROR, NULL, 0,
174
NULL, NULL, NULL, 0, 0,
178
xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
181
__xmlRaiseError(NULL, NULL, NULL,
182
NULL, ctxt->node, XML_FROM_CHECK,
183
error, XML_ERR_ERROR, NULL, 0,
184
NULL, NULL, NULL, 0, 0,
189
* xmlCtxtNsCheckScope:
190
* @ctxt: the debugging context
192
* @ns: the namespace node
194
* Report if a given namespace is is not in scope.
197
xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns)
201
ret = xmlNsCheckScope(node, ns);
203
if (ns->prefix == NULL)
204
xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
205
"Reference to default namespace not in scope\n");
207
xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
208
"Reference to namespace '%s' not in scope\n",
209
(char *) ns->prefix);
212
if (ns->prefix == NULL)
213
xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
214
"Reference to default namespace not on ancestor\n");
216
xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
217
"Reference to namespace '%s' not on ancestor\n",
218
(char *) ns->prefix);
223
* xmlCtxtCheckString:
224
* @ctxt: the debug context
227
* Do debugging on the string, currently it just checks the UTF-8 content
230
xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
232
if (str == NULL) return;
234
if (!xmlCheckUTF8(str)) {
235
xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8,
236
"String is not UTF-8 %s", (const char *) str);
243
* @ctxt: the debug context
246
* Do debugging on the name, for example the dictionnary status and
247
* conformance to the Name production.
250
xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name)
254
xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL");
257
if (xmlValidateName(name, 0)) {
258
xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME,
259
"Name is not an NCName '%s'", (const char *) name);
261
if ((ctxt->dict != NULL) &&
262
(!xmlDictOwns(ctxt->dict, name))) {
263
xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
264
"Name is not from the document dictionnary '%s'",
265
(const char *) name);
271
xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
277
if (node->parent == NULL)
278
xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
279
"Node has no parent\n");
280
if (node->doc == NULL) {
281
xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
282
"Node has no doc\n");
286
if ((dict == NULL) && (ctxt->nodict == 0)) {
288
/* desactivated right now as it raises too many errors */
289
if (doc->type == XML_DOCUMENT_NODE)
290
xmlDebugErr(ctxt, XML_CHECK_NO_DICT,
291
"Document has no dictionnary\n");
295
if (ctxt->doc == NULL)
298
if (ctxt->dict == NULL) {
302
if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
303
(!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
304
xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
305
"Node doc differs from parent's one\n");
306
if (node->prev == NULL) {
307
if (node->type == XML_ATTRIBUTE_NODE) {
308
if ((node->parent != NULL) &&
309
(node != (xmlNodePtr) node->parent->properties))
310
xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
311
"Attr has no prev and not first of attr list\n");
313
} else if ((node->parent != NULL) && (node->parent->children != node))
314
xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
315
"Node has no prev and not first of parent list\n");
317
if (node->prev->next != node)
318
xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
319
"Node prev->next : back link wrong\n");
321
if (node->next == NULL) {
322
if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
323
(node->parent->last != node) &&
324
(node->parent->type == XML_ELEMENT_NODE))
325
xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
326
"Node has no next and not last of parent list\n");
328
if (node->next->prev != node)
329
xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
330
"Node next->prev : forward link wrong\n");
331
if (node->next->parent != node->parent)
332
xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
333
"Node next->prev : forward link wrong\n");
335
if (node->type == XML_ELEMENT_NODE) {
340
xmlCtxtNsCheckScope(ctxt, node, ns);
343
if (node->ns != NULL)
344
xmlCtxtNsCheckScope(ctxt, node, node->ns);
345
} else if (node->type == XML_ATTRIBUTE_NODE) {
346
if (node->ns != NULL)
347
xmlCtxtNsCheckScope(ctxt, node, node->ns);
350
if ((node->type != XML_ELEMENT_NODE) &&
351
(node->type != XML_ATTRIBUTE_NODE) &&
352
(node->type != XML_ELEMENT_DECL) &&
353
(node->type != XML_ATTRIBUTE_DECL) &&
354
(node->type != XML_DTD_NODE) &&
355
(node->type != XML_ELEMENT_DECL) &&
356
(node->type != XML_HTML_DOCUMENT_NODE) &&
357
(node->type != XML_DOCUMENT_NODE)) {
358
if (node->content != NULL)
359
xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
361
switch (node->type) {
362
case XML_ELEMENT_NODE:
363
case XML_ATTRIBUTE_NODE:
364
xmlCtxtCheckName(ctxt, node->name);
367
if ((node->name == xmlStringText) ||
368
(node->name == xmlStringTextNoenc))
370
/* some case of entity substitution can lead to this */
371
if ((ctxt->dict != NULL) &&
372
(node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
376
xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
377
"Text node has wrong name '%s'",
378
(const char *) node->name);
380
case XML_COMMENT_NODE:
381
if (node->name == xmlStringComment)
383
xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
384
"Comment node has wrong name '%s'",
385
(const char *) node->name);
388
xmlCtxtCheckName(ctxt, node->name);
390
case XML_CDATA_SECTION_NODE:
391
if (node->name == NULL)
393
xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL,
394
"CData section has non NULL name '%s'",
395
(const char *) node->name);
397
case XML_ENTITY_REF_NODE:
398
case XML_ENTITY_NODE:
399
case XML_DOCUMENT_TYPE_NODE:
400
case XML_DOCUMENT_FRAG_NODE:
401
case XML_NOTATION_NODE:
403
case XML_ELEMENT_DECL:
404
case XML_ATTRIBUTE_DECL:
405
case XML_ENTITY_DECL:
406
case XML_NAMESPACE_DECL:
407
case XML_XINCLUDE_START:
408
case XML_XINCLUDE_END:
409
#ifdef LIBXML_DOCB_ENABLED
410
case XML_DOCB_DOCUMENT_NODE:
412
case XML_DOCUMENT_NODE:
413
case XML_HTML_DOCUMENT_NODE:
419
xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
426
/* TODO: check UTF8 content of the string */
428
fprintf(ctxt->output, "(NULL)");
431
for (i = 0; i < 40; i++)
434
else if (IS_BLANK_CH(str[i]))
435
fputc(' ', ctxt->output);
436
else if (str[i] >= 0x80)
437
fprintf(ctxt->output, "#%X", str[i]);
439
fputc(str[i], ctxt->output);
440
fprintf(ctxt->output, "...");
444
xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
446
xmlCtxtDumpSpaces(ctxt);
450
fprintf(ctxt->output, "DTD node is NULL\n");
454
if (dtd->type != XML_DTD_NODE) {
455
xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
456
"Node is not a DTD");
460
if (dtd->name != NULL)
461
fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
463
fprintf(ctxt->output, "DTD");
464
if (dtd->ExternalID != NULL)
465
fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
466
if (dtd->SystemID != NULL)
467
fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
468
fprintf(ctxt->output, "\n");
471
* Do a bit of checking
473
xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
477
xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr)
479
xmlCtxtDumpSpaces(ctxt);
483
fprintf(ctxt->output, "Attribute declaration is NULL\n");
486
if (attr->type != XML_ATTRIBUTE_DECL) {
487
xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
488
"Node is not an attribute declaration");
491
if (attr->name != NULL) {
493
fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
495
xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
496
"Node attribute declaration has no name");
497
if (attr->elem != NULL) {
499
fprintf(ctxt->output, " for %s", (char *) attr->elem);
501
xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
502
"Node attribute declaration has no element name");
504
switch (attr->atype) {
505
case XML_ATTRIBUTE_CDATA:
506
fprintf(ctxt->output, " CDATA");
508
case XML_ATTRIBUTE_ID:
509
fprintf(ctxt->output, " ID");
511
case XML_ATTRIBUTE_IDREF:
512
fprintf(ctxt->output, " IDREF");
514
case XML_ATTRIBUTE_IDREFS:
515
fprintf(ctxt->output, " IDREFS");
517
case XML_ATTRIBUTE_ENTITY:
518
fprintf(ctxt->output, " ENTITY");
520
case XML_ATTRIBUTE_ENTITIES:
521
fprintf(ctxt->output, " ENTITIES");
523
case XML_ATTRIBUTE_NMTOKEN:
524
fprintf(ctxt->output, " NMTOKEN");
526
case XML_ATTRIBUTE_NMTOKENS:
527
fprintf(ctxt->output, " NMTOKENS");
529
case XML_ATTRIBUTE_ENUMERATION:
530
fprintf(ctxt->output, " ENUMERATION");
532
case XML_ATTRIBUTE_NOTATION:
533
fprintf(ctxt->output, " NOTATION ");
536
if (attr->tree != NULL) {
538
xmlEnumerationPtr cur = attr->tree;
540
for (indx = 0; indx < 5; indx++) {
542
fprintf(ctxt->output, "|%s", (char *) cur->name);
544
fprintf(ctxt->output, " (%s", (char *) cur->name);
550
fprintf(ctxt->output, ")");
552
fprintf(ctxt->output, "...)");
555
case XML_ATTRIBUTE_NONE:
557
case XML_ATTRIBUTE_REQUIRED:
558
fprintf(ctxt->output, " REQUIRED");
560
case XML_ATTRIBUTE_IMPLIED:
561
fprintf(ctxt->output, " IMPLIED");
563
case XML_ATTRIBUTE_FIXED:
564
fprintf(ctxt->output, " FIXED");
567
if (attr->defaultValue != NULL) {
568
fprintf(ctxt->output, "\"");
569
xmlCtxtDumpString(ctxt, attr->defaultValue);
570
fprintf(ctxt->output, "\"");
572
fprintf(ctxt->output, "\n");
576
* Do a bit of checking
578
xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
582
xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem)
584
xmlCtxtDumpSpaces(ctxt);
588
fprintf(ctxt->output, "Element declaration is NULL\n");
591
if (elem->type != XML_ELEMENT_DECL) {
592
xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
593
"Node is not an element declaration");
596
if (elem->name != NULL) {
598
fprintf(ctxt->output, "ELEMDECL(");
599
xmlCtxtDumpString(ctxt, elem->name);
600
fprintf(ctxt->output, ")");
603
xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
604
"Element declaration has no name");
606
switch (elem->etype) {
607
case XML_ELEMENT_TYPE_UNDEFINED:
608
fprintf(ctxt->output, ", UNDEFINED");
610
case XML_ELEMENT_TYPE_EMPTY:
611
fprintf(ctxt->output, ", EMPTY");
613
case XML_ELEMENT_TYPE_ANY:
614
fprintf(ctxt->output, ", ANY");
616
case XML_ELEMENT_TYPE_MIXED:
617
fprintf(ctxt->output, ", MIXED ");
619
case XML_ELEMENT_TYPE_ELEMENT:
620
fprintf(ctxt->output, ", MIXED ");
623
if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) {
627
xmlSnprintfElementContent(buf, 5000, elem->content, 1);
629
fprintf(ctxt->output, "%s", buf);
631
fprintf(ctxt->output, "\n");
635
* Do a bit of checking
637
xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
641
xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
643
xmlCtxtDumpSpaces(ctxt);
647
fprintf(ctxt->output, "Entity declaration is NULL\n");
650
if (ent->type != XML_ENTITY_DECL) {
651
xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
652
"Node is not an entity declaration");
655
if (ent->name != NULL) {
657
fprintf(ctxt->output, "ENTITYDECL(");
658
xmlCtxtDumpString(ctxt, ent->name);
659
fprintf(ctxt->output, ")");
662
xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
663
"Entity declaration has no name");
665
switch (ent->etype) {
666
case XML_INTERNAL_GENERAL_ENTITY:
667
fprintf(ctxt->output, ", internal\n");
669
case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
670
fprintf(ctxt->output, ", external parsed\n");
672
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
673
fprintf(ctxt->output, ", unparsed\n");
675
case XML_INTERNAL_PARAMETER_ENTITY:
676
fprintf(ctxt->output, ", parameter\n");
678
case XML_EXTERNAL_PARAMETER_ENTITY:
679
fprintf(ctxt->output, ", external parameter\n");
681
case XML_INTERNAL_PREDEFINED_ENTITY:
682
fprintf(ctxt->output, ", predefined\n");
685
if (ent->ExternalID) {
686
xmlCtxtDumpSpaces(ctxt);
687
fprintf(ctxt->output, " ExternalID=%s\n",
688
(char *) ent->ExternalID);
691
xmlCtxtDumpSpaces(ctxt);
692
fprintf(ctxt->output, " SystemID=%s\n",
693
(char *) ent->SystemID);
695
if (ent->URI != NULL) {
696
xmlCtxtDumpSpaces(ctxt);
697
fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI);
700
xmlCtxtDumpSpaces(ctxt);
701
fprintf(ctxt->output, " content=");
702
xmlCtxtDumpString(ctxt, ent->content);
703
fprintf(ctxt->output, "\n");
708
* Do a bit of checking
710
xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
714
xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
716
xmlCtxtDumpSpaces(ctxt);
720
fprintf(ctxt->output, "namespace node is NULL\n");
723
if (ns->type != XML_NAMESPACE_DECL) {
724
xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
725
"Node is not a namespace declaration");
728
if (ns->href == NULL) {
729
if (ns->prefix != NULL)
730
xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
731
"Incomplete namespace %s href=NULL\n",
732
(char *) ns->prefix);
734
xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
735
"Incomplete default namespace href=NULL\n");
738
if (ns->prefix != NULL)
739
fprintf(ctxt->output, "namespace %s href=",
740
(char *) ns->prefix);
742
fprintf(ctxt->output, "default namespace href=");
744
xmlCtxtDumpString(ctxt, ns->href);
745
fprintf(ctxt->output, "\n");
751
xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
754
xmlCtxtDumpNamespace(ctxt, ns);
760
xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
762
xmlCtxtDumpSpaces(ctxt);
766
fprintf(ctxt->output, "Entity is NULL\n");
770
switch (ent->etype) {
771
case XML_INTERNAL_GENERAL_ENTITY:
772
fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY ");
774
case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
775
fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
777
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
778
fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
780
case XML_INTERNAL_PARAMETER_ENTITY:
781
fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY ");
783
case XML_EXTERNAL_PARAMETER_ENTITY:
784
fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY ");
787
fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype);
789
fprintf(ctxt->output, "%s\n", ent->name);
790
if (ent->ExternalID) {
791
xmlCtxtDumpSpaces(ctxt);
792
fprintf(ctxt->output, "ExternalID=%s\n",
793
(char *) ent->ExternalID);
796
xmlCtxtDumpSpaces(ctxt);
797
fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID);
800
xmlCtxtDumpSpaces(ctxt);
801
fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI);
804
xmlCtxtDumpSpaces(ctxt);
805
fprintf(ctxt->output, "content=");
806
xmlCtxtDumpString(ctxt, ent->content);
807
fprintf(ctxt->output, "\n");
814
* @output: the FILE * for the output
815
* @attr: the attribute
816
* @depth: the indentation level.
818
* Dumps debug information for the attribute
821
xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
823
xmlCtxtDumpSpaces(ctxt);
827
fprintf(ctxt->output, "Attr is NULL");
831
fprintf(ctxt->output, "ATTRIBUTE ");
832
xmlCtxtDumpString(ctxt, attr->name);
833
fprintf(ctxt->output, "\n");
834
if (attr->children != NULL) {
836
xmlCtxtDumpNodeList(ctxt, attr->children);
840
if (attr->name == NULL)
841
xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
842
"Attribute has no name");
845
* Do a bit of checking
847
xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
851
* xmlCtxtDumpAttrList:
852
* @output: the FILE * for the output
853
* @attr: the attribute list
854
* @depth: the indentation level.
856
* Dumps debug information for the attribute list
859
xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
861
while (attr != NULL) {
862
xmlCtxtDumpAttr(ctxt, attr);
868
* xmlCtxtDumpOneNode:
869
* @output: the FILE * for the output
871
* @depth: the indentation level.
873
* Dumps debug information for the element node, it is not recursive
876
xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
880
xmlCtxtDumpSpaces(ctxt);
881
fprintf(ctxt->output, "node is NULL\n");
887
switch (node->type) {
888
case XML_ELEMENT_NODE:
890
xmlCtxtDumpSpaces(ctxt);
891
fprintf(ctxt->output, "ELEMENT ");
892
if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
893
xmlCtxtDumpString(ctxt, node->ns->prefix);
894
fprintf(ctxt->output, ":");
896
xmlCtxtDumpString(ctxt, node->name);
897
fprintf(ctxt->output, "\n");
900
case XML_ATTRIBUTE_NODE:
902
xmlCtxtDumpSpaces(ctxt);
903
fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
904
xmlCtxtGenericNodeCheck(ctxt, node);
908
xmlCtxtDumpSpaces(ctxt);
909
if (node->name == (const xmlChar *) xmlStringTextNoenc)
910
fprintf(ctxt->output, "TEXT no enc");
912
fprintf(ctxt->output, "TEXT");
913
if (ctxt->options & DUMP_TEXT_TYPE) {
914
if (node->content == (xmlChar *) &(node->properties))
915
fprintf(ctxt->output, " compact\n");
916
else if (xmlDictOwns(ctxt->dict, node->content) == 1)
917
fprintf(ctxt->output, " interned\n");
919
fprintf(ctxt->output, "\n");
921
fprintf(ctxt->output, "\n");
924
case XML_CDATA_SECTION_NODE:
926
xmlCtxtDumpSpaces(ctxt);
927
fprintf(ctxt->output, "CDATA_SECTION\n");
930
case XML_ENTITY_REF_NODE:
932
xmlCtxtDumpSpaces(ctxt);
933
fprintf(ctxt->output, "ENTITY_REF(%s)\n",
934
(char *) node->name);
937
case XML_ENTITY_NODE:
939
xmlCtxtDumpSpaces(ctxt);
940
fprintf(ctxt->output, "ENTITY\n");
945
xmlCtxtDumpSpaces(ctxt);
946
fprintf(ctxt->output, "PI %s\n", (char *) node->name);
949
case XML_COMMENT_NODE:
951
xmlCtxtDumpSpaces(ctxt);
952
fprintf(ctxt->output, "COMMENT\n");
955
case XML_DOCUMENT_NODE:
956
case XML_HTML_DOCUMENT_NODE:
958
xmlCtxtDumpSpaces(ctxt);
960
fprintf(ctxt->output, "Error, DOCUMENT found here\n");
961
xmlCtxtGenericNodeCheck(ctxt, node);
963
case XML_DOCUMENT_TYPE_NODE:
965
xmlCtxtDumpSpaces(ctxt);
966
fprintf(ctxt->output, "DOCUMENT_TYPE\n");
969
case XML_DOCUMENT_FRAG_NODE:
971
xmlCtxtDumpSpaces(ctxt);
972
fprintf(ctxt->output, "DOCUMENT_FRAG\n");
975
case XML_NOTATION_NODE:
977
xmlCtxtDumpSpaces(ctxt);
978
fprintf(ctxt->output, "NOTATION\n");
982
xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node);
984
case XML_ELEMENT_DECL:
985
xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node);
987
case XML_ATTRIBUTE_DECL:
988
xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node);
990
case XML_ENTITY_DECL:
991
xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node);
993
case XML_NAMESPACE_DECL:
994
xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node);
996
case XML_XINCLUDE_START:
998
xmlCtxtDumpSpaces(ctxt);
999
fprintf(ctxt->output, "INCLUDE START\n");
1002
case XML_XINCLUDE_END:
1004
xmlCtxtDumpSpaces(ctxt);
1005
fprintf(ctxt->output, "INCLUDE END\n");
1010
xmlCtxtDumpSpaces(ctxt);
1011
xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1012
"Unknown node type %d\n", node->type);
1015
if (node->doc == NULL) {
1017
xmlCtxtDumpSpaces(ctxt);
1019
fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
1022
if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL))
1023
xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
1024
if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL))
1025
xmlCtxtDumpAttrList(ctxt, node->properties);
1026
if (node->type != XML_ENTITY_REF_NODE) {
1027
if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
1029
xmlCtxtDumpSpaces(ctxt);
1030
fprintf(ctxt->output, "content=");
1031
xmlCtxtDumpString(ctxt, node->content);
1032
fprintf(ctxt->output, "\n");
1038
ent = xmlGetDocEntity(node->doc, node->name);
1040
xmlCtxtDumpEntity(ctxt, ent);
1045
* Do a bit of checking
1047
xmlCtxtGenericNodeCheck(ctxt, node);
1052
* @output: the FILE * for the output
1054
* @depth: the indentation level.
1056
* Dumps debug information for the element node, it is recursive
1059
xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
1063
xmlCtxtDumpSpaces(ctxt);
1064
fprintf(ctxt->output, "node is NULL\n");
1068
xmlCtxtDumpOneNode(ctxt, node);
1069
if ((node->type != XML_NAMESPACE_DECL) &&
1070
(node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1072
xmlCtxtDumpNodeList(ctxt, node->children);
1078
* xmlCtxtDumpNodeList:
1079
* @output: the FILE * for the output
1080
* @node: the node list
1081
* @depth: the indentation level.
1083
* Dumps debug information for the list of element node, it is recursive
1086
xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
1088
while (node != NULL) {
1089
xmlCtxtDumpNode(ctxt, node);
1095
xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1099
fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1102
ctxt->node = (xmlNodePtr) doc;
1104
switch (doc->type) {
1105
case XML_ELEMENT_NODE:
1106
xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
1107
"Misplaced ELEMENT node\n");
1109
case XML_ATTRIBUTE_NODE:
1110
xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
1111
"Misplaced ATTRIBUTE node\n");
1114
xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
1115
"Misplaced TEXT node\n");
1117
case XML_CDATA_SECTION_NODE:
1118
xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
1119
"Misplaced CDATA node\n");
1121
case XML_ENTITY_REF_NODE:
1122
xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
1123
"Misplaced ENTITYREF node\n");
1125
case XML_ENTITY_NODE:
1126
xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
1127
"Misplaced ENTITY node\n");
1130
xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
1131
"Misplaced PI node\n");
1133
case XML_COMMENT_NODE:
1134
xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
1135
"Misplaced COMMENT node\n");
1137
case XML_DOCUMENT_NODE:
1139
fprintf(ctxt->output, "DOCUMENT\n");
1141
case XML_HTML_DOCUMENT_NODE:
1143
fprintf(ctxt->output, "HTML DOCUMENT\n");
1145
case XML_DOCUMENT_TYPE_NODE:
1146
xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
1147
"Misplaced DOCTYPE node\n");
1149
case XML_DOCUMENT_FRAG_NODE:
1150
xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
1151
"Misplaced FRAGMENT node\n");
1153
case XML_NOTATION_NODE:
1154
xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
1155
"Misplaced NOTATION node\n");
1158
xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1159
"Unknown node type %d\n", doc->type);
1164
* xmlCtxtDumpDocumentHead:
1165
* @output: the FILE * for the output
1166
* @doc: the document
1168
* Dumps debug information cncerning the document, not recursive
1171
xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1173
if (doc == NULL) return;
1174
xmlCtxtDumpDocHead(ctxt, doc);
1176
if (doc->name != NULL) {
1177
fprintf(ctxt->output, "name=");
1178
xmlCtxtDumpString(ctxt, BAD_CAST doc->name);
1179
fprintf(ctxt->output, "\n");
1181
if (doc->version != NULL) {
1182
fprintf(ctxt->output, "version=");
1183
xmlCtxtDumpString(ctxt, doc->version);
1184
fprintf(ctxt->output, "\n");
1186
if (doc->encoding != NULL) {
1187
fprintf(ctxt->output, "encoding=");
1188
xmlCtxtDumpString(ctxt, doc->encoding);
1189
fprintf(ctxt->output, "\n");
1191
if (doc->URL != NULL) {
1192
fprintf(ctxt->output, "URL=");
1193
xmlCtxtDumpString(ctxt, doc->URL);
1194
fprintf(ctxt->output, "\n");
1196
if (doc->standalone)
1197
fprintf(ctxt->output, "standalone=true\n");
1199
if (doc->oldNs != NULL)
1200
xmlCtxtDumpNamespaceList(ctxt, doc->oldNs);
1204
* xmlCtxtDumpDocument:
1205
* @output: the FILE * for the output
1206
* @doc: the document
1208
* Dumps debug information for the document, it's recursive
1211
xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1215
fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1218
xmlCtxtDumpDocumentHead(ctxt, doc);
1219
if (((doc->type == XML_DOCUMENT_NODE) ||
1220
(doc->type == XML_HTML_DOCUMENT_NODE))
1221
&& (doc->children != NULL)) {
1223
xmlCtxtDumpNodeList(ctxt, doc->children);
1229
xmlCtxtDumpEntityCallback(xmlEntityPtr cur, xmlDebugCtxtPtr ctxt)
1233
fprintf(ctxt->output, "Entity is NULL");
1237
fprintf(ctxt->output, "%s : ", (char *) cur->name);
1238
switch (cur->etype) {
1239
case XML_INTERNAL_GENERAL_ENTITY:
1240
fprintf(ctxt->output, "INTERNAL GENERAL, ");
1242
case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1243
fprintf(ctxt->output, "EXTERNAL PARSED, ");
1245
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1246
fprintf(ctxt->output, "EXTERNAL UNPARSED, ");
1248
case XML_INTERNAL_PARAMETER_ENTITY:
1249
fprintf(ctxt->output, "INTERNAL PARAMETER, ");
1251
case XML_EXTERNAL_PARAMETER_ENTITY:
1252
fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
1255
xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
1256
"Unknown entity type %d\n", cur->etype);
1258
if (cur->ExternalID != NULL)
1259
fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
1260
if (cur->SystemID != NULL)
1261
fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID);
1262
if (cur->orig != NULL)
1263
fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig);
1264
if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL))
1265
fprintf(ctxt->output, "\n content \"%s\"",
1266
(char *) cur->content);
1267
fprintf(ctxt->output, "\n");
1272
* xmlCtxtDumpEntities:
1273
* @output: the FILE * for the output
1274
* @doc: the document
1276
* Dumps debug information for all the entities in use by the document
1279
xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1281
if (doc == NULL) return;
1282
xmlCtxtDumpDocHead(ctxt, doc);
1283
if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1284
xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1285
doc->intSubset->entities;
1288
fprintf(ctxt->output, "Entities in internal subset\n");
1289
xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
1292
fprintf(ctxt->output, "No entities in internal subset\n");
1293
if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1294
xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1295
doc->extSubset->entities;
1298
fprintf(ctxt->output, "Entities in external subset\n");
1299
xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
1301
} else if (!ctxt->check)
1302
fprintf(ctxt->output, "No entities in external subset\n");
1307
* @output: the FILE * for the output
1310
* Dumps debug information for the DTD
1313
xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
1317
fprintf(ctxt->output, "DTD is NULL\n");
1320
xmlCtxtDumpDtdNode(ctxt, dtd);
1321
if (dtd->children == NULL)
1322
fprintf(ctxt->output, " DTD is empty\n");
1325
xmlCtxtDumpNodeList(ctxt, dtd->children);
1330
/************************************************************************
1332
* Public entry points for dump *
1334
************************************************************************/
1337
* xmlDebugDumpString:
1338
* @output: the FILE * for the output
1341
* Dumps informations about the string, shorten it if necessary
1344
xmlDebugDumpString(FILE * output, const xmlChar * str)
1351
fprintf(output, "(NULL)");
1354
for (i = 0; i < 40; i++)
1357
else if (IS_BLANK_CH(str[i]))
1359
else if (str[i] >= 0x80)
1360
fprintf(output, "#%X", str[i]);
1362
fputc(str[i], output);
1363
fprintf(output, "...");
1368
* @output: the FILE * for the output
1369
* @attr: the attribute
1370
* @depth: the indentation level.
1372
* Dumps debug information for the attribute
1375
xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
1378
if (output == NULL) return;
1379
xmlCtxtDumpInitCtxt(&ctxt);
1380
ctxt.output = output;
1382
xmlCtxtDumpAttr(&ctxt, attr);
1383
xmlCtxtDumpCleanCtxt(&ctxt);
1388
* xmlDebugDumpEntities:
1389
* @output: the FILE * for the output
1390
* @doc: the document
1392
* Dumps debug information for all the entities in use by the document
1395
xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1399
if (output == NULL) return;
1400
xmlCtxtDumpInitCtxt(&ctxt);
1401
ctxt.output = output;
1402
xmlCtxtDumpEntities(&ctxt, doc);
1403
xmlCtxtDumpCleanCtxt(&ctxt);
1407
* xmlDebugDumpAttrList:
1408
* @output: the FILE * for the output
1409
* @attr: the attribute list
1410
* @depth: the indentation level.
1412
* Dumps debug information for the attribute list
1415
xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
1419
if (output == NULL) return;
1420
xmlCtxtDumpInitCtxt(&ctxt);
1421
ctxt.output = output;
1423
xmlCtxtDumpAttrList(&ctxt, attr);
1424
xmlCtxtDumpCleanCtxt(&ctxt);
1428
* xmlDebugDumpOneNode:
1429
* @output: the FILE * for the output
1431
* @depth: the indentation level.
1433
* Dumps debug information for the element node, it is not recursive
1436
xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
1440
if (output == NULL) return;
1441
xmlCtxtDumpInitCtxt(&ctxt);
1442
ctxt.output = output;
1444
xmlCtxtDumpOneNode(&ctxt, node);
1445
xmlCtxtDumpCleanCtxt(&ctxt);
1450
* @output: the FILE * for the output
1452
* @depth: the indentation level.
1454
* Dumps debug information for the element node, it is recursive
1457
xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
1463
xmlCtxtDumpInitCtxt(&ctxt);
1464
ctxt.output = output;
1466
xmlCtxtDumpNode(&ctxt, node);
1467
xmlCtxtDumpCleanCtxt(&ctxt);
1471
* xmlDebugDumpNodeList:
1472
* @output: the FILE * for the output
1473
* @node: the node list
1474
* @depth: the indentation level.
1476
* Dumps debug information for the list of element node, it is recursive
1479
xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
1485
xmlCtxtDumpInitCtxt(&ctxt);
1486
ctxt.output = output;
1488
xmlCtxtDumpNodeList(&ctxt, node);
1489
xmlCtxtDumpCleanCtxt(&ctxt);
1493
* xmlDebugDumpDocumentHead:
1494
* @output: the FILE * for the output
1495
* @doc: the document
1497
* Dumps debug information cncerning the document, not recursive
1500
xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
1506
xmlCtxtDumpInitCtxt(&ctxt);
1507
ctxt.options |= DUMP_TEXT_TYPE;
1508
ctxt.output = output;
1509
xmlCtxtDumpDocumentHead(&ctxt, doc);
1510
xmlCtxtDumpCleanCtxt(&ctxt);
1514
* xmlDebugDumpDocument:
1515
* @output: the FILE * for the output
1516
* @doc: the document
1518
* Dumps debug information for the document, it's recursive
1521
xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
1527
xmlCtxtDumpInitCtxt(&ctxt);
1528
ctxt.options |= DUMP_TEXT_TYPE;
1529
ctxt.output = output;
1530
xmlCtxtDumpDocument(&ctxt, doc);
1531
xmlCtxtDumpCleanCtxt(&ctxt);
1536
* @output: the FILE * for the output
1539
* Dumps debug information for the DTD
1542
xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
1548
xmlCtxtDumpInitCtxt(&ctxt);
1549
ctxt.options |= DUMP_TEXT_TYPE;
1550
ctxt.output = output;
1551
xmlCtxtDumpDTD(&ctxt, dtd);
1552
xmlCtxtDumpCleanCtxt(&ctxt);
1555
/************************************************************************
1557
* Public entry points for checkings *
1559
************************************************************************/
1562
* xmlDebugCheckDocument:
1563
* @output: the FILE * for the output
1564
* @doc: the document
1566
* Check the document for potential content problems, and output
1567
* the errors to @output
1569
* Returns the number of errors found
1572
xmlDebugCheckDocument(FILE * output, xmlDocPtr doc)
1578
xmlCtxtDumpInitCtxt(&ctxt);
1579
ctxt.output = output;
1581
xmlCtxtDumpDocument(&ctxt, doc);
1582
xmlCtxtDumpCleanCtxt(&ctxt);
1583
return(ctxt.errors);
1586
/************************************************************************
1588
* Helpers for Shell *
1590
************************************************************************/
1594
* @node: the node to count
1596
* Count the children of @node.
1598
* Returns the number of children of @node.
1601
xmlLsCountNode(xmlNodePtr node) {
1603
xmlNodePtr list = NULL;
1608
switch (node->type) {
1609
case XML_ELEMENT_NODE:
1610
list = node->children;
1612
case XML_DOCUMENT_NODE:
1613
case XML_HTML_DOCUMENT_NODE:
1614
#ifdef LIBXML_DOCB_ENABLED
1615
case XML_DOCB_DOCUMENT_NODE:
1617
list = ((xmlDocPtr) node)->children;
1619
case XML_ATTRIBUTE_NODE:
1620
list = ((xmlAttrPtr) node)->children;
1623
case XML_CDATA_SECTION_NODE:
1625
case XML_COMMENT_NODE:
1626
if (node->content != NULL) {
1627
ret = xmlStrlen(node->content);
1630
case XML_ENTITY_REF_NODE:
1631
case XML_DOCUMENT_TYPE_NODE:
1632
case XML_ENTITY_NODE:
1633
case XML_DOCUMENT_FRAG_NODE:
1634
case XML_NOTATION_NODE:
1636
case XML_ELEMENT_DECL:
1637
case XML_ATTRIBUTE_DECL:
1638
case XML_ENTITY_DECL:
1639
case XML_NAMESPACE_DECL:
1640
case XML_XINCLUDE_START:
1641
case XML_XINCLUDE_END:
1645
for (;list != NULL;ret++)
1652
* @output: the FILE * for the output
1653
* @node: the node to dump
1655
* Dump to @output the type and name of @node.
1658
xmlLsOneNode(FILE *output, xmlNodePtr node) {
1659
if (output == NULL) return;
1661
fprintf(output, "NULL\n");
1664
switch (node->type) {
1665
case XML_ELEMENT_NODE:
1666
fprintf(output, "-");
1668
case XML_ATTRIBUTE_NODE:
1669
fprintf(output, "a");
1672
fprintf(output, "t");
1674
case XML_CDATA_SECTION_NODE:
1675
fprintf(output, "C");
1677
case XML_ENTITY_REF_NODE:
1678
fprintf(output, "e");
1680
case XML_ENTITY_NODE:
1681
fprintf(output, "E");
1684
fprintf(output, "p");
1686
case XML_COMMENT_NODE:
1687
fprintf(output, "c");
1689
case XML_DOCUMENT_NODE:
1690
fprintf(output, "d");
1692
case XML_HTML_DOCUMENT_NODE:
1693
fprintf(output, "h");
1695
case XML_DOCUMENT_TYPE_NODE:
1696
fprintf(output, "T");
1698
case XML_DOCUMENT_FRAG_NODE:
1699
fprintf(output, "F");
1701
case XML_NOTATION_NODE:
1702
fprintf(output, "N");
1704
case XML_NAMESPACE_DECL:
1705
fprintf(output, "n");
1708
fprintf(output, "?");
1710
if (node->type != XML_NAMESPACE_DECL) {
1711
if (node->properties != NULL)
1712
fprintf(output, "a");
1714
fprintf(output, "-");
1715
if (node->nsDef != NULL)
1716
fprintf(output, "n");
1718
fprintf(output, "-");
1721
fprintf(output, " %8d ", xmlLsCountNode(node));
1723
switch (node->type) {
1724
case XML_ELEMENT_NODE:
1725
if (node->name != NULL)
1726
fprintf(output, "%s", (const char *) node->name);
1728
case XML_ATTRIBUTE_NODE:
1729
if (node->name != NULL)
1730
fprintf(output, "%s", (const char *) node->name);
1733
if (node->content != NULL) {
1734
xmlDebugDumpString(output, node->content);
1737
case XML_CDATA_SECTION_NODE:
1739
case XML_ENTITY_REF_NODE:
1740
if (node->name != NULL)
1741
fprintf(output, "%s", (const char *) node->name);
1743
case XML_ENTITY_NODE:
1744
if (node->name != NULL)
1745
fprintf(output, "%s", (const char *) node->name);
1748
if (node->name != NULL)
1749
fprintf(output, "%s", (const char *) node->name);
1751
case XML_COMMENT_NODE:
1753
case XML_DOCUMENT_NODE:
1755
case XML_HTML_DOCUMENT_NODE:
1757
case XML_DOCUMENT_TYPE_NODE:
1759
case XML_DOCUMENT_FRAG_NODE:
1761
case XML_NOTATION_NODE:
1763
case XML_NAMESPACE_DECL: {
1764
xmlNsPtr ns = (xmlNsPtr) node;
1766
if (ns->prefix == NULL)
1767
fprintf(output, "default -> %s", (char *)ns->href);
1769
fprintf(output, "%s -> %s", (char *)ns->prefix,
1774
if (node->name != NULL)
1775
fprintf(output, "%s", (const char *) node->name);
1777
fprintf(output, "\n");
1782
* @boolval: a bool to turn into text
1784
* Convenient way to turn bool into text
1786
* Returns a pointer to either "True" or "False"
1789
xmlBoolToText(int boolval)
1797
#ifdef LIBXML_XPATH_ENABLED
1798
/****************************************************************
1800
* The XML shell related functions *
1802
****************************************************************/
1807
* TODO: Improvement/cleanups for the XML shell
1808
* - allow to shell out an editor on a subpart
1809
* - cleanup function registrations (with help) and calling
1810
* - provide registration routines
1814
* xmlShellPrintXPathError:
1815
* @errorType: valid xpath error id
1816
* @arg: the argument that cause xpath to fail
1818
* Print the xpath error to libxml default error channel
1821
xmlShellPrintXPathError(int errorType, const char *arg)
1823
const char *default_arg = "Result";
1828
switch (errorType) {
1829
case XPATH_UNDEFINED:
1830
xmlGenericError(xmlGenericErrorContext,
1831
"%s: no such node\n", arg);
1835
xmlGenericError(xmlGenericErrorContext,
1836
"%s is a Boolean\n", arg);
1839
xmlGenericError(xmlGenericErrorContext,
1840
"%s is a number\n", arg);
1843
xmlGenericError(xmlGenericErrorContext,
1844
"%s is a string\n", arg);
1847
xmlGenericError(xmlGenericErrorContext,
1848
"%s is a point\n", arg);
1851
xmlGenericError(xmlGenericErrorContext,
1852
"%s is a range\n", arg);
1854
case XPATH_LOCATIONSET:
1855
xmlGenericError(xmlGenericErrorContext,
1856
"%s is a range\n", arg);
1859
xmlGenericError(xmlGenericErrorContext,
1860
"%s is user-defined\n", arg);
1862
case XPATH_XSLT_TREE:
1863
xmlGenericError(xmlGenericErrorContext,
1864
"%s is an XSLT value tree\n", arg);
1868
xmlGenericError(xmlGenericErrorContext,
1869
"Try casting the result string function (xpath builtin)\n",
1875
#ifdef LIBXML_OUTPUT_ENABLED
1877
* xmlShellPrintNodeCtxt:
1878
* @ctxt : a non-null shell context
1879
* @node : a non-null node to print to the output FILE
1881
* Print node to the output FILE
1884
xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1895
if (node->type == XML_DOCUMENT_NODE)
1896
xmlDocDump(fp, (xmlDocPtr) node);
1897
else if (node->type == XML_ATTRIBUTE_NODE)
1898
xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
1900
xmlElemDump(fp, node->doc, node);
1906
* xmlShellPrintNode:
1907
* @node : a non-null node to print to the output FILE
1909
* Print node to the output FILE
1912
xmlShellPrintNode(xmlNodePtr node)
1914
xmlShellPrintNodeCtxt(NULL, node);
1916
#endif /* LIBXML_OUTPUT_ENABLED */
1919
* xmlShellPrintXPathResultCtxt:
1920
* @ctxt: a valid shell context
1921
* @list: a valid result generated by an xpath evaluation
1923
* Prints result to the output FILE
1926
xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
1932
switch (list->type) {
1933
case XPATH_NODESET:{
1934
#ifdef LIBXML_OUTPUT_ENABLED
1937
if (list->nodesetval) {
1938
for (indx = 0; indx < list->nodesetval->nodeNr;
1940
xmlShellPrintNodeCtxt(ctxt,
1941
list->nodesetval->nodeTab[indx]);
1944
xmlGenericError(xmlGenericErrorContext,
1945
"Empty node set\n");
1949
xmlGenericError(xmlGenericErrorContext,
1951
#endif /* LIBXML_OUTPUT_ENABLED */
1954
xmlGenericError(xmlGenericErrorContext,
1955
"Is a Boolean:%s\n",
1956
xmlBoolToText(list->boolval));
1959
xmlGenericError(xmlGenericErrorContext,
1960
"Is a number:%0g\n", list->floatval);
1963
xmlGenericError(xmlGenericErrorContext,
1964
"Is a string:%s\n", list->stringval);
1968
xmlShellPrintXPathError(list->type, NULL);
1974
* xmlShellPrintXPathResult:
1975
* @list: a valid result generated by an xpath evaluation
1977
* Prints result to the output FILE
1980
xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1982
xmlShellPrintXPathResultCtxt(NULL, list);
1987
* @ctxt: the shell context
1992
* Implements the XML shell function "ls"
1993
* Does an Unix like listing of the given node (like a directory)
1998
xmlShellList(xmlShellCtxtPtr ctxt,
1999
char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2000
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2006
fprintf(ctxt->output, "NULL\n");
2009
if ((node->type == XML_DOCUMENT_NODE) ||
2010
(node->type == XML_HTML_DOCUMENT_NODE)) {
2011
cur = ((xmlDocPtr) node)->children;
2012
} else if (node->type == XML_NAMESPACE_DECL) {
2013
xmlLsOneNode(ctxt->output, node);
2015
} else if (node->children != NULL) {
2016
cur = node->children;
2018
xmlLsOneNode(ctxt->output, node);
2021
while (cur != NULL) {
2022
xmlLsOneNode(ctxt->output, cur);
2030
* @ctxt: the shell context
2035
* Implements the XML shell function "base"
2036
* dumps the current XML base of the node
2041
xmlShellBase(xmlShellCtxtPtr ctxt,
2042
char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2043
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2049
fprintf(ctxt->output, "NULL\n");
2053
base = xmlNodeGetBase(node->doc, node);
2056
fprintf(ctxt->output, " No base found !!!\n");
2058
fprintf(ctxt->output, "%s\n", base);
2064
#ifdef LIBXML_TREE_ENABLED
2067
* @ctxt: the shell context
2068
* @arg: the new base
2072
* Implements the XML shell function "setbase"
2073
* change the current XML base of the node
2078
xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2079
char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2080
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2082
xmlNodeSetBase(node, (xmlChar*) arg);
2087
#ifdef LIBXML_XPATH_ENABLED
2089
* xmlShellRegisterNamespace:
2090
* @ctxt: the shell context
2091
* @arg: a string in prefix=nsuri format
2095
* Implements the XML shell function "setns"
2096
* register/unregister a prefix=namespace pair
2097
* on the XPath context
2099
* Returns 0 on success and a negative value otherwise.
2102
xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg,
2103
xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2110
nsListDup = xmlStrdup((xmlChar *) arg);
2112
while(next != NULL) {
2114
/*while((*next) == ' ') next++;*/
2115
if((*next) == '\0') break;
2119
next = (xmlChar*)xmlStrchr(next, '=');
2121
fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
2129
next = (xmlChar*)xmlStrchr(next, ' ');
2134
/* do register namespace */
2135
if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
2136
fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
2146
* xmlShellRegisterRootNamespaces:
2147
* @ctxt: the shell context
2149
* @node: the root element
2152
* Implements the XML shell function "setrootns"
2153
* which registers all namespaces declarations found on the root element.
2155
* Returns 0 on success and a negative value otherwise.
2158
xmlShellRegisterRootNamespaces(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
2159
xmlNodePtr root, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2163
if ((root == NULL) || (root->type != XML_ELEMENT_NODE) ||
2164
(root->nsDef == NULL) || (ctxt == NULL) || (ctxt->pctxt == NULL))
2167
while (ns != NULL) {
2168
if (ns->prefix == NULL)
2169
xmlXPathRegisterNs(ctxt->pctxt, BAD_CAST "defaultns", ns->href);
2171
xmlXPathRegisterNs(ctxt->pctxt, ns->prefix, ns->href);
2180
* @ctxt: the shell context
2181
* @arg: the string or regular expression to find
2185
* Implements the XML shell function "grep"
2186
* dumps informations about the node (namespace, attributes, content).
2191
xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2192
char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2200
#ifdef LIBXML_REGEXP_ENABLED
2201
if ((xmlStrchr((xmlChar *) arg, '?')) ||
2202
(xmlStrchr((xmlChar *) arg, '*')) ||
2203
(xmlStrchr((xmlChar *) arg, '.')) ||
2204
(xmlStrchr((xmlChar *) arg, '['))) {
2207
while (node != NULL) {
2208
if (node->type == XML_COMMENT_NODE) {
2209
if (xmlStrstr(node->content, (xmlChar *) arg)) {
2211
fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
2212
xmlShellList(ctxt, NULL, node, NULL);
2214
} else if (node->type == XML_TEXT_NODE) {
2215
if (xmlStrstr(node->content, (xmlChar *) arg)) {
2217
fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
2218
xmlShellList(ctxt, NULL, node->parent, NULL);
2223
* Browse the full subtree, deep first
2226
if ((node->type == XML_DOCUMENT_NODE) ||
2227
(node->type == XML_HTML_DOCUMENT_NODE)) {
2228
node = ((xmlDocPtr) node)->children;
2229
} else if ((node->children != NULL)
2230
&& (node->type != XML_ENTITY_REF_NODE)) {
2232
node = node->children;
2233
} else if (node->next != NULL) {
2237
/* go up to parents->next if needed */
2238
while (node != NULL) {
2239
if (node->parent != NULL) {
2240
node = node->parent;
2242
if (node->next != NULL) {
2246
if (node->parent == NULL) {
2258
* @ctxt: the shell context
2263
* Implements the XML shell function "dir"
2264
* dumps informations about the node (namespace, attributes, content).
2269
xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2270
char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2271
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2276
fprintf(ctxt->output, "NULL\n");
2279
if ((node->type == XML_DOCUMENT_NODE) ||
2280
(node->type == XML_HTML_DOCUMENT_NODE)) {
2281
xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
2282
} else if (node->type == XML_ATTRIBUTE_NODE) {
2283
xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
2285
xmlDebugDumpOneNode(ctxt->output, node, 0);
2291
* xmlShellSetContent:
2292
* @ctxt: the shell context
2293
* @value: the content as a string
2297
* Implements the XML shell function "dir"
2298
* dumps informations about the node (namespace, attributes, content).
2303
xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2304
char *value, xmlNodePtr node,
2305
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2308
xmlParserErrors ret;
2313
fprintf(ctxt->output, "NULL\n");
2316
if (value == NULL) {
2317
fprintf(ctxt->output, "NULL\n");
2321
ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results);
2322
if (ret == XML_ERR_OK) {
2323
if (node->children != NULL) {
2324
xmlFreeNodeList(node->children);
2325
node->children = NULL;
2328
xmlAddChildList(node, results);
2330
fprintf(ctxt->output, "failed to parse content\n");
2335
#ifdef LIBXML_SCHEMAS_ENABLED
2337
* xmlShellRNGValidate:
2338
* @ctxt: the shell context
2339
* @schemas: the path to the Relax-NG schemas
2343
* Implements the XML shell function "relaxng"
2344
* validating the instance against a Relax-NG schemas
2349
xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
2350
xmlNodePtr node ATTRIBUTE_UNUSED,
2351
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2353
xmlRelaxNGPtr relaxngschemas;
2354
xmlRelaxNGParserCtxtPtr ctxt;
2355
xmlRelaxNGValidCtxtPtr vctxt;
2358
ctxt = xmlRelaxNGNewParserCtxt(schemas);
2359
xmlRelaxNGSetParserErrors(ctxt,
2360
(xmlRelaxNGValidityErrorFunc) fprintf,
2361
(xmlRelaxNGValidityWarningFunc) fprintf,
2363
relaxngschemas = xmlRelaxNGParse(ctxt);
2364
xmlRelaxNGFreeParserCtxt(ctxt);
2365
if (relaxngschemas == NULL) {
2366
xmlGenericError(xmlGenericErrorContext,
2367
"Relax-NG schema %s failed to compile\n", schemas);
2370
vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2371
xmlRelaxNGSetValidErrors(vctxt,
2372
(xmlRelaxNGValidityErrorFunc) fprintf,
2373
(xmlRelaxNGValidityWarningFunc) fprintf,
2375
ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
2377
fprintf(stderr, "%s validates\n", sctxt->filename);
2378
} else if (ret > 0) {
2379
fprintf(stderr, "%s fails to validate\n", sctxt->filename);
2381
fprintf(stderr, "%s validation generated an internal error\n",
2384
xmlRelaxNGFreeValidCtxt(vctxt);
2385
if (relaxngschemas != NULL)
2386
xmlRelaxNGFree(relaxngschemas);
2391
#ifdef LIBXML_OUTPUT_ENABLED
2394
* @ctxt: the shell context
2399
* Implements the XML shell function "cat"
2400
* dumps the serialization node content (XML or HTML).
2405
xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
2406
xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2411
fprintf(ctxt->output, "NULL\n");
2414
if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
2415
#ifdef LIBXML_HTML_ENABLED
2416
if (node->type == XML_HTML_DOCUMENT_NODE)
2417
htmlDocDump(ctxt->output, (htmlDocPtr) node);
2419
htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
2421
if (node->type == XML_DOCUMENT_NODE)
2422
xmlDocDump(ctxt->output, (xmlDocPtr) node);
2424
xmlElemDump(ctxt->output, ctxt->doc, node);
2425
#endif /* LIBXML_HTML_ENABLED */
2427
if (node->type == XML_DOCUMENT_NODE)
2428
xmlDocDump(ctxt->output, (xmlDocPtr) node);
2430
xmlElemDump(ctxt->output, ctxt->doc, node);
2432
fprintf(ctxt->output, "\n");
2435
#endif /* LIBXML_OUTPUT_ENABLED */
2439
* @ctxt: the shell context
2440
* @filename: the file name
2444
* Implements the XML shell function "load"
2445
* loads a new document specified by the filename
2447
* Returns 0 or -1 if loading failed
2450
xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
2451
xmlNodePtr node ATTRIBUTE_UNUSED,
2452
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2457
if ((ctxt == NULL) || (filename == NULL)) return(-1);
2458
if (ctxt->doc != NULL)
2459
html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
2462
#ifdef LIBXML_HTML_ENABLED
2463
doc = htmlParseFile(filename, NULL);
2465
fprintf(ctxt->output, "HTML support not compiled in\n");
2467
#endif /* LIBXML_HTML_ENABLED */
2469
doc = xmlReadFile(filename,NULL,0);
2472
if (ctxt->loaded == 1) {
2473
xmlFreeDoc(ctxt->doc);
2476
#ifdef LIBXML_XPATH_ENABLED
2477
xmlXPathFreeContext(ctxt->pctxt);
2478
#endif /* LIBXML_XPATH_ENABLED */
2479
xmlFree(ctxt->filename);
2481
ctxt->node = (xmlNodePtr) doc;
2482
#ifdef LIBXML_XPATH_ENABLED
2483
ctxt->pctxt = xmlXPathNewContext(doc);
2484
#endif /* LIBXML_XPATH_ENABLED */
2485
ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
2491
#ifdef LIBXML_OUTPUT_ENABLED
2494
* @ctxt: the shell context
2495
* @filename: the file name
2496
* @node: a node in the tree
2499
* Implements the XML shell function "write"
2500
* Write the current node to the filename, it saves the serialization
2501
* of the subtree under the @node specified
2503
* Returns 0 or -1 in case of error
2506
xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
2507
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2511
if ((filename == NULL) || (filename[0] == 0)) {
2515
if (access((char *) filename, W_OK)) {
2516
xmlGenericError(xmlGenericErrorContext,
2517
"Cannot write to %s\n", filename);
2521
switch (node->type) {
2522
case XML_DOCUMENT_NODE:
2523
if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2524
xmlGenericError(xmlGenericErrorContext,
2525
"Failed to write to %s\n", filename);
2529
case XML_HTML_DOCUMENT_NODE:
2530
#ifdef LIBXML_HTML_ENABLED
2531
if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2532
xmlGenericError(xmlGenericErrorContext,
2533
"Failed to write to %s\n", filename);
2537
if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2538
xmlGenericError(xmlGenericErrorContext,
2539
"Failed to write to %s\n", filename);
2542
#endif /* LIBXML_HTML_ENABLED */
2547
f = fopen((char *) filename, "w");
2549
xmlGenericError(xmlGenericErrorContext,
2550
"Failed to write to %s\n", filename);
2553
xmlElemDump(f, ctxt->doc, node);
2562
* @ctxt: the shell context
2563
* @filename: the file name (optional)
2567
* Implements the XML shell function "save"
2568
* Write the current document to the filename, or it's original name
2570
* Returns 0 or -1 in case of error
2573
xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
2574
xmlNodePtr node ATTRIBUTE_UNUSED,
2575
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2577
if ((ctxt == NULL) || (ctxt->doc == NULL))
2579
if ((filename == NULL) || (filename[0] == 0))
2580
filename = ctxt->filename;
2581
if (filename == NULL)
2584
if (access((char *) filename, W_OK)) {
2585
xmlGenericError(xmlGenericErrorContext,
2586
"Cannot save to %s\n", filename);
2590
switch (ctxt->doc->type) {
2591
case XML_DOCUMENT_NODE:
2592
if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2593
xmlGenericError(xmlGenericErrorContext,
2594
"Failed to save to %s\n", filename);
2597
case XML_HTML_DOCUMENT_NODE:
2598
#ifdef LIBXML_HTML_ENABLED
2599
if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2600
xmlGenericError(xmlGenericErrorContext,
2601
"Failed to save to %s\n", filename);
2604
if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2605
xmlGenericError(xmlGenericErrorContext,
2606
"Failed to save to %s\n", filename);
2608
#endif /* LIBXML_HTML_ENABLED */
2611
xmlGenericError(xmlGenericErrorContext,
2612
"To save to subparts of a document use the 'write' command\n");
2618
#endif /* LIBXML_OUTPUT_ENABLED */
2620
#ifdef LIBXML_VALID_ENABLED
2623
* @ctxt: the shell context
2624
* @dtd: the DTD URI (optional)
2628
* Implements the XML shell function "validate"
2629
* Validate the document, if a DTD path is provided, then the validation
2630
* is done against the given DTD.
2632
* Returns 0 or -1 in case of error
2635
xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
2636
xmlNodePtr node ATTRIBUTE_UNUSED,
2637
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2642
if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1);
2643
vctxt.userData = stderr;
2644
vctxt.error = (xmlValidityErrorFunc) fprintf;
2645
vctxt.warning = (xmlValidityWarningFunc) fprintf;
2647
if ((dtd == NULL) || (dtd[0] == 0)) {
2648
res = xmlValidateDocument(&vctxt, ctxt->doc);
2652
subset = xmlParseDTD(NULL, (xmlChar *) dtd);
2653
if (subset != NULL) {
2654
res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
2661
#endif /* LIBXML_VALID_ENABLED */
2665
* @ctxt: the shell context
2667
* @tree: a node defining a subtree
2670
* Implements the XML shell function "du"
2671
* show the structure of the subtree under node @tree
2672
* If @tree is null, the command works on the current node.
2674
* Returns 0 or -1 in case of error
2677
xmlShellDu(xmlShellCtxtPtr ctxt,
2678
char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
2679
xmlNodePtr node2 ATTRIBUTE_UNUSED)
2690
while (node != NULL) {
2691
if ((node->type == XML_DOCUMENT_NODE) ||
2692
(node->type == XML_HTML_DOCUMENT_NODE)) {
2693
fprintf(ctxt->output, "/\n");
2694
} else if (node->type == XML_ELEMENT_NODE) {
2695
for (i = 0; i < indent; i++)
2696
fprintf(ctxt->output, " ");
2697
fprintf(ctxt->output, "%s\n", node->name);
2702
* Browse the full subtree, deep first
2705
if ((node->type == XML_DOCUMENT_NODE) ||
2706
(node->type == XML_HTML_DOCUMENT_NODE)) {
2707
node = ((xmlDocPtr) node)->children;
2708
} else if ((node->children != NULL)
2709
&& (node->type != XML_ENTITY_REF_NODE)) {
2711
node = node->children;
2713
} else if ((node != tree) && (node->next != NULL)) {
2716
} else if (node != tree) {
2717
/* go up to parents->next if needed */
2718
while (node != tree) {
2719
if (node->parent != NULL) {
2720
node = node->parent;
2723
if ((node != tree) && (node->next != NULL)) {
2727
if (node->parent == NULL) {
2736
/* exit condition */
2747
* @ctxt: the shell context
2748
* @buffer: the output buffer
2752
* Implements the XML shell function "pwd"
2753
* Show the full path from the root to the node, if needed building
2754
* thumblers when similar elements exists at a given ancestor level.
2755
* The output is compatible with XPath commands.
2757
* Returns 0 or -1 in case of error
2760
xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2761
xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2765
if ((node == NULL) || (buffer == NULL))
2768
path = xmlGetNodePath(node);
2773
* This test prevents buffer overflow, because this routine
2774
* is only called by xmlShell, in which the second argument is
2776
* It is a dirty hack before a cleaner solution is found.
2777
* Documentation should mention that the second argument must
2778
* be at least 500 chars long, and could be stripped if too long.
2780
snprintf(buffer, 499, "%s", path);
2789
* @doc: the initial document
2790
* @filename: the output buffer
2791
* @input: the line reading function
2792
* @output: the output FILE*, defaults to stdout if NULL
2794
* Implements the XML shell
2795
* This allow to load, validate, view, modify and save a document
2796
* using a environment similar to a UNIX commandline.
2799
xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
2802
char prompt[500] = "/ > ";
2803
char *cmdline = NULL, *cur;
2808
xmlShellCtxtPtr ctxt;
2809
xmlXPathObjectPtr list;
2813
if (filename == NULL)
2819
ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
2824
ctxt->input = input;
2825
ctxt->output = output;
2826
ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
2827
ctxt->node = (xmlNodePtr) ctxt->doc;
2829
#ifdef LIBXML_XPATH_ENABLED
2830
ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2831
if (ctxt->pctxt == NULL) {
2835
#endif /* LIBXML_XPATH_ENABLED */
2837
if (ctxt->node == (xmlNodePtr) ctxt->doc)
2838
snprintf(prompt, sizeof(prompt), "%s > ", "/");
2839
else if ((ctxt->node != NULL) && (ctxt->node->name))
2840
snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
2842
snprintf(prompt, sizeof(prompt), "? > ");
2843
prompt[sizeof(prompt) - 1] = 0;
2846
* Get a new command line
2848
cmdline = ctxt->input(prompt);
2849
if (cmdline == NULL)
2853
* Parse the command itself
2857
while ((*cur == ' ') || (*cur == '\t'))
2860
while ((*cur != ' ') && (*cur != '\t') &&
2861
(*cur != '\n') && (*cur != '\r')) {
2864
command[i++] = *cur++;
2872
* Parse the argument
2874
while ((*cur == ' ') || (*cur == '\t'))
2877
while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2887
* start interpreting the command
2889
if (!strcmp(command, "exit"))
2891
if (!strcmp(command, "quit"))
2893
if (!strcmp(command, "bye"))
2895
if (!strcmp(command, "help")) {
2896
fprintf(ctxt->output, "\tbase display XML base of the node\n");
2897
fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2898
fprintf(ctxt->output, "\tbye leave shell\n");
2899
fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2900
fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2901
fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2902
fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2903
fprintf(ctxt->output, "\texit leave shell\n");
2904
fprintf(ctxt->output, "\thelp display this help\n");
2905
fprintf(ctxt->output, "\tfree display memory usage\n");
2906
fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2907
fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
2908
fprintf(ctxt->output, "\tset xml_fragment replace the current node content with the fragment parsed in context\n");
2909
#ifdef LIBXML_XPATH_ENABLED
2910
fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
2911
fprintf(ctxt->output, "\tsetns nsreg register a namespace to a prefix in the XPath evaluation context\n");
2912
fprintf(ctxt->output, "\t format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
2913
fprintf(ctxt->output, "\tsetrootns register all namespace found on the root element\n");
2914
fprintf(ctxt->output, "\t the default namespace if any uses 'defaultns' prefix\n");
2915
#endif /* LIBXML_XPATH_ENABLED */
2916
fprintf(ctxt->output, "\tpwd display current working directory\n");
2917
fprintf(ctxt->output, "\tquit leave shell\n");
2918
#ifdef LIBXML_OUTPUT_ENABLED
2919
fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
2920
fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
2921
#endif /* LIBXML_OUTPUT_ENABLED */
2922
#ifdef LIBXML_VALID_ENABLED
2923
fprintf(ctxt->output, "\tvalidate check the document for errors\n");
2924
#endif /* LIBXML_VALID_ENABLED */
2925
#ifdef LIBXML_SCHEMAS_ENABLED
2926
fprintf(ctxt->output, "\trelaxng rng validate the document agaisnt the Relax-NG schemas\n");
2928
fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
2929
#ifdef LIBXML_VALID_ENABLED
2930
} else if (!strcmp(command, "validate")) {
2931
xmlShellValidate(ctxt, arg, NULL, NULL);
2932
#endif /* LIBXML_VALID_ENABLED */
2933
} else if (!strcmp(command, "load")) {
2934
xmlShellLoad(ctxt, arg, NULL, NULL);
2935
#ifdef LIBXML_SCHEMAS_ENABLED
2936
} else if (!strcmp(command, "relaxng")) {
2937
xmlShellRNGValidate(ctxt, arg, NULL, NULL);
2939
#ifdef LIBXML_OUTPUT_ENABLED
2940
} else if (!strcmp(command, "save")) {
2941
xmlShellSave(ctxt, arg, NULL, NULL);
2942
} else if (!strcmp(command, "write")) {
2943
if ((arg == NULL) || (arg[0] == 0))
2944
xmlGenericError(xmlGenericErrorContext,
2945
"Write command requires a filename argument\n");
2947
xmlShellWrite(ctxt, arg, NULL, NULL);
2948
#endif /* LIBXML_OUTPUT_ENABLED */
2949
} else if (!strcmp(command, "grep")) {
2950
xmlShellGrep(ctxt, arg, ctxt->node, NULL);
2951
} else if (!strcmp(command, "free")) {
2953
xmlMemShow(ctxt->output, 0);
2957
sscanf(arg, "%d", &len);
2958
xmlMemShow(ctxt->output, len);
2960
} else if (!strcmp(command, "pwd")) {
2963
if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
2964
fprintf(ctxt->output, "%s\n", dir);
2965
} else if (!strcmp(command, "du")) {
2966
xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2967
} else if (!strcmp(command, "base")) {
2968
xmlShellBase(ctxt, NULL, ctxt->node, NULL);
2969
} else if (!strcmp(command, "set")) {
2970
xmlShellSetContent(ctxt, arg, ctxt->node, NULL);
2971
#ifdef LIBXML_XPATH_ENABLED
2972
} else if (!strcmp(command, "setns")) {
2974
xmlGenericError(xmlGenericErrorContext,
2975
"setns: prefix=[nsuri] required\n");
2977
xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
2979
} else if (!strcmp(command, "setrootns")) {
2982
root = xmlDocGetRootElement(ctxt->doc);
2983
xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL);
2984
} else if (!strcmp(command, "xpath")) {
2986
xmlGenericError(xmlGenericErrorContext,
2987
"xpath: expression required\n");
2989
ctxt->pctxt->node = ctxt->node;
2990
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2991
xmlXPathDebugDumpObject(ctxt->output, list, 0);
2992
xmlXPathFreeObject(list);
2994
#endif /* LIBXML_XPATH_ENABLED */
2995
#ifdef LIBXML_TREE_ENABLED
2996
} else if (!strcmp(command, "setbase")) {
2997
xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
2999
} else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
3000
int dir = (!strcmp(command, "dir"));
3004
xmlShellDir(ctxt, NULL, ctxt->node, NULL);
3006
xmlShellList(ctxt, NULL, ctxt->node, NULL);
3008
ctxt->pctxt->node = ctxt->node;
3009
#ifdef LIBXML_XPATH_ENABLED
3010
ctxt->pctxt->node = ctxt->node;
3011
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3014
#endif /* LIBXML_XPATH_ENABLED */
3016
switch (list->type) {
3017
case XPATH_UNDEFINED:
3018
xmlGenericError(xmlGenericErrorContext,
3019
"%s: no such node\n", arg);
3021
case XPATH_NODESET:{
3024
if (list->nodesetval == NULL)
3028
indx < list->nodesetval->nodeNr;
3031
xmlShellDir(ctxt, NULL,
3033
nodeTab[indx], NULL);
3035
xmlShellList(ctxt, NULL,
3037
nodeTab[indx], NULL);
3042
xmlGenericError(xmlGenericErrorContext,
3043
"%s is a Boolean\n", arg);
3046
xmlGenericError(xmlGenericErrorContext,
3047
"%s is a number\n", arg);
3050
xmlGenericError(xmlGenericErrorContext,
3051
"%s is a string\n", arg);
3054
xmlGenericError(xmlGenericErrorContext,
3055
"%s is a point\n", arg);
3058
xmlGenericError(xmlGenericErrorContext,
3059
"%s is a range\n", arg);
3061
case XPATH_LOCATIONSET:
3062
xmlGenericError(xmlGenericErrorContext,
3063
"%s is a range\n", arg);
3066
xmlGenericError(xmlGenericErrorContext,
3067
"%s is user-defined\n", arg);
3069
case XPATH_XSLT_TREE:
3070
xmlGenericError(xmlGenericErrorContext,
3071
"%s is an XSLT value tree\n",
3075
#ifdef LIBXML_XPATH_ENABLED
3076
xmlXPathFreeObject(list);
3079
xmlGenericError(xmlGenericErrorContext,
3080
"%s: no such node\n", arg);
3082
ctxt->pctxt->node = NULL;
3084
} else if (!strcmp(command, "cd")) {
3086
ctxt->node = (xmlNodePtr) ctxt->doc;
3088
#ifdef LIBXML_XPATH_ENABLED
3089
ctxt->pctxt->node = ctxt->node;
3090
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3093
#endif /* LIBXML_XPATH_ENABLED */
3095
switch (list->type) {
3096
case XPATH_UNDEFINED:
3097
xmlGenericError(xmlGenericErrorContext,
3098
"%s: no such node\n", arg);
3101
if (list->nodesetval != NULL) {
3102
if (list->nodesetval->nodeNr == 1) {
3103
ctxt->node = list->nodesetval->nodeTab[0];
3104
if ((ctxt->node != NULL) &&
3105
(ctxt->node->type ==
3106
XML_NAMESPACE_DECL)) {
3107
xmlGenericError(xmlGenericErrorContext,
3108
"cannot cd to namespace\n");
3112
xmlGenericError(xmlGenericErrorContext,
3113
"%s is a %d Node Set\n",
3115
list->nodesetval->nodeNr);
3117
xmlGenericError(xmlGenericErrorContext,
3118
"%s is an empty Node Set\n",
3122
xmlGenericError(xmlGenericErrorContext,
3123
"%s is a Boolean\n", arg);
3126
xmlGenericError(xmlGenericErrorContext,
3127
"%s is a number\n", arg);
3130
xmlGenericError(xmlGenericErrorContext,
3131
"%s is a string\n", arg);
3134
xmlGenericError(xmlGenericErrorContext,
3135
"%s is a point\n", arg);
3138
xmlGenericError(xmlGenericErrorContext,
3139
"%s is a range\n", arg);
3141
case XPATH_LOCATIONSET:
3142
xmlGenericError(xmlGenericErrorContext,
3143
"%s is a range\n", arg);
3146
xmlGenericError(xmlGenericErrorContext,
3147
"%s is user-defined\n", arg);
3149
case XPATH_XSLT_TREE:
3150
xmlGenericError(xmlGenericErrorContext,
3151
"%s is an XSLT value tree\n",
3155
#ifdef LIBXML_XPATH_ENABLED
3156
xmlXPathFreeObject(list);
3159
xmlGenericError(xmlGenericErrorContext,
3160
"%s: no such node\n", arg);
3162
ctxt->pctxt->node = NULL;
3164
#ifdef LIBXML_OUTPUT_ENABLED
3165
} else if (!strcmp(command, "cat")) {
3167
xmlShellCat(ctxt, NULL, ctxt->node, NULL);
3169
ctxt->pctxt->node = ctxt->node;
3170
#ifdef LIBXML_XPATH_ENABLED
3171
ctxt->pctxt->node = ctxt->node;
3172
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3175
#endif /* LIBXML_XPATH_ENABLED */
3177
switch (list->type) {
3178
case XPATH_UNDEFINED:
3179
xmlGenericError(xmlGenericErrorContext,
3180
"%s: no such node\n", arg);
3182
case XPATH_NODESET:{
3185
if (list->nodesetval == NULL)
3189
indx < list->nodesetval->nodeNr;
3192
fprintf(ctxt->output, " -------\n");
3193
xmlShellCat(ctxt, NULL,
3195
nodeTab[indx], NULL);
3200
xmlGenericError(xmlGenericErrorContext,
3201
"%s is a Boolean\n", arg);
3204
xmlGenericError(xmlGenericErrorContext,
3205
"%s is a number\n", arg);
3208
xmlGenericError(xmlGenericErrorContext,
3209
"%s is a string\n", arg);
3212
xmlGenericError(xmlGenericErrorContext,
3213
"%s is a point\n", arg);
3216
xmlGenericError(xmlGenericErrorContext,
3217
"%s is a range\n", arg);
3219
case XPATH_LOCATIONSET:
3220
xmlGenericError(xmlGenericErrorContext,
3221
"%s is a range\n", arg);
3224
xmlGenericError(xmlGenericErrorContext,
3225
"%s is user-defined\n", arg);
3227
case XPATH_XSLT_TREE:
3228
xmlGenericError(xmlGenericErrorContext,
3229
"%s is an XSLT value tree\n",
3233
#ifdef LIBXML_XPATH_ENABLED
3234
xmlXPathFreeObject(list);
3237
xmlGenericError(xmlGenericErrorContext,
3238
"%s: no such node\n", arg);
3240
ctxt->pctxt->node = NULL;
3242
#endif /* LIBXML_OUTPUT_ENABLED */
3244
xmlGenericError(xmlGenericErrorContext,
3245
"Unknown command %s\n", command);
3247
free(cmdline); /* not xmlFree here ! */
3250
#ifdef LIBXML_XPATH_ENABLED
3251
xmlXPathFreeContext(ctxt->pctxt);
3252
#endif /* LIBXML_XPATH_ENABLED */
3254
xmlFreeDoc(ctxt->doc);
3256
if (ctxt->filename != NULL)
3257
xmlFree(ctxt->filename);
3259
if (cmdline != NULL)
3260
free(cmdline); /* not xmlFree here ! */
3263
#endif /* LIBXML_XPATH_ENABLED */
3264
#define bottom_debugXML
3265
#include "elfgcchack.h"
3266
#endif /* LIBXML_DEBUG_ENABLED */