debugXML.c
1 /* 2 * debugXML.c : This is a set of routines used for debugging the tree 3 * produced by the XML parser. 4 * 5 * See Copyright for the status of this software. 6 * 7 * Daniel Veillard <daniel@veillard.com> 8 */ 9 10 #define IN_LIBXML 11 #include "libxml.h" 12 #ifdef LIBXML_DEBUG_ENABLED 13 14 #include <string.h> 15 #ifdef HAVE_STDLIB_H 16 #include <stdlib.h> 17 #endif 18 #ifdef HAVE_STRING_H 19 #include <string.h> 20 #endif 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> 35 #endif 36 37 #define DUMP_TEXT_TYPE 1 38 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 dictionary */ 48 int check; /* do just checkings */ 49 int errors; /* number of errors found */ 50 int nodict; /* if the document has no dictionary */ 51 int options; /* options */ 52 }; 53 54 static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node); 55 56 static void 57 xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt) 58 { 59 int i; 60 61 ctxt->depth = 0; 62 ctxt->check = 0; 63 ctxt->errors = 0; 64 ctxt->output = stdout; 65 ctxt->doc = NULL; 66 ctxt->node = NULL; 67 ctxt->dict = NULL; 68 ctxt->nodict = 0; 69 ctxt->options = 0; 70 for (i = 0; i < 100; i++) 71 ctxt->shift[i] = ' '; 72 ctxt->shift[100] = 0; 73 } 74 75 static void 76 xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED) 77 { 78 /* remove the ATTRIBUTE_UNUSED when this is added */ 79 } 80 81 /** 82 * xmlNsCheckScope: 83 * @node: the node 84 * @ns: the namespace node 85 * 86 * Check that a given namespace is in scope on a node. 87 * 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 90 * an ancestor node. 91 */ 92 static int 93 xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns) 94 { 95 xmlNsPtr cur; 96 97 if ((node == NULL) || (ns == NULL)) 98 return(-1); 99 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)) 106 return(-2); 107 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)) { 115 cur = node->nsDef; 116 while (cur != NULL) { 117 if (cur == ns) 118 return(1); 119 if (xmlStrEqual(cur->prefix, ns->prefix)) 120 return(-2); 121 cur = cur->next; 122 } 123 } 124 node = node->parent; 125 } 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; 131 if (oldNs == ns) 132 return(1); 133 } 134 return(-3); 135 } 136 137 static void 138 xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt) 139 { 140 if (ctxt->check) 141 return; 142 if ((ctxt->output != NULL) && (ctxt->depth > 0)) { 143 if (ctxt->depth < 50) 144 fprintf(ctxt->output, "%s", &ctxt->shift[100 - 2 * ctxt->depth]); 145 else 146 fprintf(ctxt->output, "%s", ctxt->shift); 147 } 148 } 149 150 /** 151 * xmlDebugErr: 152 * @ctxt: a debug context 153 * @error: the error code 154 * 155 * Handle a debug error. 156 */ 157 static void 158 xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg) 159 { 160 ctxt->errors++; 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, 165 "%s", msg); 166 } 167 static void LIBXML_ATTR_FORMAT(3,0) 168 xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra) 169 { 170 ctxt->errors++; 171 #pragma clang diagnostic push 172 #pragma clang diagnostic ignored "-Wformat-nonliteral" 173 __xmlRaiseError(NULL, NULL, NULL, 174 NULL, ctxt->node, XML_FROM_CHECK, 175 error, XML_ERR_ERROR, NULL, 0, 176 NULL, NULL, NULL, 0, 0, 177 msg, extra); 178 #pragma clang diagnostic pop 179 } 180 static void LIBXML_ATTR_FORMAT(3,0) 181 xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra) 182 { 183 ctxt->errors++; 184 #pragma clang diagnostic push 185 #pragma clang diagnostic ignored "-Wformat-nonliteral" 186 __xmlRaiseError(NULL, NULL, NULL, 187 NULL, ctxt->node, XML_FROM_CHECK, 188 error, XML_ERR_ERROR, NULL, 0, 189 NULL, NULL, NULL, 0, 0, 190 msg, extra); 191 #pragma clang diagnostic pop 192 } 193 194 /** 195 * xmlCtxtNsCheckScope: 196 * @ctxt: the debugging context 197 * @node: the node 198 * @ns: the namespace node 199 * 200 * Report if a given namespace is is not in scope. 201 */ 202 static void 203 xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns) 204 { 205 int ret; 206 207 ret = xmlNsCheckScope(node, ns); 208 if (ret == -2) { 209 if (ns->prefix == NULL) 210 xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE, 211 "Reference to default namespace not in scope\n"); 212 else 213 xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE, 214 "Reference to namespace '%s' not in scope\n", 215 (char *) ns->prefix); 216 } 217 if (ret == -3) { 218 if (ns->prefix == NULL) 219 xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR, 220 "Reference to default namespace not on ancestor\n"); 221 else 222 xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR, 223 "Reference to namespace '%s' not on ancestor\n", 224 (char *) ns->prefix); 225 } 226 } 227 228 /** 229 * xmlCtxtCheckString: 230 * @ctxt: the debug context 231 * @str: the string 232 * 233 * Do debugging on the string, currently it just checks the UTF-8 content 234 */ 235 static void 236 xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str) 237 { 238 if (str == NULL) return; 239 if (ctxt->check) { 240 if (!xmlCheckUTF8(str)) { 241 xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8, 242 "String is not UTF-8 %s", (const char *) str); 243 } 244 } 245 } 246 247 /** 248 * xmlCtxtCheckName: 249 * @ctxt: the debug context 250 * @name: the name 251 * 252 * Do debugging on the name, for example the dictionary status and 253 * conformance to the Name production. 254 */ 255 static void 256 xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name) 257 { 258 if (ctxt->check) { 259 if (name == NULL) { 260 xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL"); 261 return; 262 } 263 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) 264 if (xmlValidateName(name, 0)) { 265 xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME, 266 "Name is not an NCName '%s'", (const char *) name); 267 } 268 #endif 269 if ((ctxt->dict != NULL) && 270 (!xmlDictOwns(ctxt->dict, name)) && 271 ((ctxt->doc == NULL) || 272 ((ctxt->doc->parseFlags & (XML_PARSE_SAX1 | XML_PARSE_NODICT)) == 0))) { 273 xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT, 274 "Name is not from the document dictionary '%s'", 275 (const char *) name); 276 } 277 } 278 } 279 280 static void 281 xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) { 282 xmlDocPtr doc; 283 xmlDictPtr dict; 284 285 doc = node->doc; 286 287 if (node->parent == NULL) 288 xmlDebugErr(ctxt, XML_CHECK_NO_PARENT, 289 "Node has no parent\n"); 290 if (node->doc == NULL) { 291 xmlDebugErr(ctxt, XML_CHECK_NO_DOC, 292 "Node has no doc\n"); 293 dict = NULL; 294 } else { 295 dict = doc->dict; 296 if ((dict == NULL) && (ctxt->nodict == 0)) { 297 #if 0 298 /* desactivated right now as it raises too many errors */ 299 if (doc->type == XML_DOCUMENT_NODE) 300 xmlDebugErr(ctxt, XML_CHECK_NO_DICT, 301 "Document has no dictionary\n"); 302 #endif 303 ctxt->nodict = 1; 304 } 305 if (ctxt->doc == NULL) 306 ctxt->doc = doc; 307 308 if (ctxt->dict == NULL) { 309 ctxt->dict = dict; 310 } 311 } 312 if ((node->parent != NULL) && (node->doc != node->parent->doc) && 313 (!xmlStrEqual(node->name, BAD_CAST "pseudoroot"))) 314 xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC, 315 "Node doc differs from parent's one\n"); 316 if (node->prev == NULL) { 317 if (node->type == XML_ATTRIBUTE_NODE) { 318 if ((node->parent != NULL) && 319 (node != (xmlNodePtr) node->parent->properties)) 320 xmlDebugErr(ctxt, XML_CHECK_NO_PREV, 321 "Attr has no prev and not first of attr list\n"); 322 323 } else if ((node->parent != NULL) && (node->parent->children != node)) 324 xmlDebugErr(ctxt, XML_CHECK_NO_PREV, 325 "Node has no prev and not first of parent list\n"); 326 } else { 327 if (node->prev->next != node) 328 xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV, 329 "Node prev->next : back link wrong\n"); 330 } 331 if (node->next == NULL) { 332 if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) && 333 (node->parent->last != node) && 334 (node->parent->type == XML_ELEMENT_NODE)) 335 xmlDebugErr(ctxt, XML_CHECK_NO_NEXT, 336 "Node has no next and not last of parent list\n"); 337 } else { 338 if (node->next->prev != node) 339 xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT, 340 "Node next->prev : forward link wrong\n"); 341 if (node->next->parent != node->parent) 342 xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT, 343 "Node next->prev : forward link wrong\n"); 344 } 345 if (node->type == XML_ELEMENT_NODE) { 346 xmlNsPtr ns; 347 348 ns = node->nsDef; 349 while (ns != NULL) { 350 xmlCtxtNsCheckScope(ctxt, node, ns); 351 ns = ns->next; 352 } 353 if (node->ns != NULL) 354 xmlCtxtNsCheckScope(ctxt, node, node->ns); 355 } else if (node->type == XML_ATTRIBUTE_NODE) { 356 if (node->ns != NULL) 357 xmlCtxtNsCheckScope(ctxt, node, node->ns); 358 } 359 360 if ((node->type != XML_ELEMENT_NODE) && 361 (node->type != XML_ATTRIBUTE_NODE) && 362 (node->type != XML_ELEMENT_DECL) && 363 (node->type != XML_ATTRIBUTE_DECL) && 364 (node->type != XML_DTD_NODE) && 365 (node->type != XML_HTML_DOCUMENT_NODE) && 366 (node->type != XML_DOCUMENT_NODE)) { 367 if (node->content != NULL) 368 xmlCtxtCheckString(ctxt, (const xmlChar *) node->content); 369 } 370 switch (node->type) { 371 case XML_ELEMENT_NODE: 372 case XML_ATTRIBUTE_NODE: 373 xmlCtxtCheckName(ctxt, node->name); 374 break; 375 case XML_TEXT_NODE: 376 if ((node->name == xmlStringText) || 377 (node->name == xmlStringTextNoenc)) 378 break; 379 /* some case of entity substitution can lead to this */ 380 if ((ctxt->dict != NULL) && 381 (node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext", 382 7))) 383 break; 384 385 xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME, 386 "Text node has wrong name '%s'", 387 (const char *) node->name); 388 break; 389 case XML_COMMENT_NODE: 390 if (node->name == xmlStringComment) 391 break; 392 xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME, 393 "Comment node has wrong name '%s'", 394 (const char *) node->name); 395 break; 396 case XML_PI_NODE: 397 xmlCtxtCheckName(ctxt, node->name); 398 break; 399 case XML_CDATA_SECTION_NODE: 400 if (node->name == NULL) 401 break; 402 xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL, 403 "CData section has non NULL name '%s'", 404 (const char *) node->name); 405 break; 406 case XML_ENTITY_REF_NODE: 407 case XML_ENTITY_NODE: 408 case XML_DOCUMENT_TYPE_NODE: 409 case XML_DOCUMENT_FRAG_NODE: 410 case XML_NOTATION_NODE: 411 case XML_DTD_NODE: 412 case XML_ELEMENT_DECL: 413 case XML_ATTRIBUTE_DECL: 414 case XML_ENTITY_DECL: 415 case XML_NAMESPACE_DECL: 416 case XML_XINCLUDE_START: 417 case XML_XINCLUDE_END: 418 #ifdef LIBXML_DOCB_ENABLED 419 case XML_DOCB_DOCUMENT_NODE: 420 #endif 421 case XML_DOCUMENT_NODE: 422 case XML_HTML_DOCUMENT_NODE: 423 break; 424 } 425 } 426 427 static void 428 xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str) 429 { 430 int i; 431 432 if (ctxt->check) { 433 return; 434 } 435 /* TODO: check UTF8 content of the string */ 436 if (str == NULL) { 437 fprintf(ctxt->output, "(NULL)"); 438 return; 439 } 440 for (i = 0; i < 40; i++) 441 if (str[i] == 0) 442 return; 443 else if (IS_BLANK_CH(str[i])) 444 fputc(' ', ctxt->output); 445 else if (str[i] >= 0x80) 446 fprintf(ctxt->output, "#%X", str[i]); 447 else 448 fputc(str[i], ctxt->output); 449 fprintf(ctxt->output, "..."); 450 } 451 452 static void 453 xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd) 454 { 455 xmlCtxtDumpSpaces(ctxt); 456 457 if (dtd == NULL) { 458 if (!ctxt->check) 459 fprintf(ctxt->output, "DTD node is NULL\n"); 460 return; 461 } 462 463 if (dtd->type != XML_DTD_NODE) { 464 xmlDebugErr(ctxt, XML_CHECK_NOT_DTD, 465 "Node is not a DTD"); 466 return; 467 } 468 if (!ctxt->check) { 469 if (dtd->name != NULL) 470 fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name); 471 else 472 fprintf(ctxt->output, "DTD"); 473 if (dtd->ExternalID != NULL) 474 fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID); 475 if (dtd->SystemID != NULL) 476 fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID); 477 fprintf(ctxt->output, "\n"); 478 } 479 /* 480 * Do a bit of checking 481 */ 482 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd); 483 } 484 485 static void 486 xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr) 487 { 488 xmlCtxtDumpSpaces(ctxt); 489 490 if (attr == NULL) { 491 if (!ctxt->check) 492 fprintf(ctxt->output, "Attribute declaration is NULL\n"); 493 return; 494 } 495 if (attr->type != XML_ATTRIBUTE_DECL) { 496 xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL, 497 "Node is not an attribute declaration"); 498 return; 499 } 500 if (attr->name != NULL) { 501 if (!ctxt->check) 502 fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name); 503 } else 504 xmlDebugErr(ctxt, XML_CHECK_NO_NAME, 505 "Node attribute declaration has no name"); 506 if (attr->elem != NULL) { 507 if (!ctxt->check) 508 fprintf(ctxt->output, " for %s", (char *) attr->elem); 509 } else 510 xmlDebugErr(ctxt, XML_CHECK_NO_ELEM, 511 "Node attribute declaration has no element name"); 512 if (!ctxt->check) { 513 switch (attr->atype) { 514 case XML_ATTRIBUTE_CDATA: 515 fprintf(ctxt->output, " CDATA"); 516 break; 517 case XML_ATTRIBUTE_ID: 518 fprintf(ctxt->output, " ID"); 519 break; 520 case XML_ATTRIBUTE_IDREF: 521 fprintf(ctxt->output, " IDREF"); 522 break; 523 case XML_ATTRIBUTE_IDREFS: 524 fprintf(ctxt->output, " IDREFS"); 525 break; 526 case XML_ATTRIBUTE_ENTITY: 527 fprintf(ctxt->output, " ENTITY"); 528 break; 529 case XML_ATTRIBUTE_ENTITIES: 530 fprintf(ctxt->output, " ENTITIES"); 531 break; 532 case XML_ATTRIBUTE_NMTOKEN: 533 fprintf(ctxt->output, " NMTOKEN"); 534 break; 535 case XML_ATTRIBUTE_NMTOKENS: 536 fprintf(ctxt->output, " NMTOKENS"); 537 break; 538 case XML_ATTRIBUTE_ENUMERATION: 539 fprintf(ctxt->output, " ENUMERATION"); 540 break; 541 case XML_ATTRIBUTE_NOTATION: 542 fprintf(ctxt->output, " NOTATION "); 543 break; 544 } 545 if (attr->tree != NULL) { 546 int indx; 547 xmlEnumerationPtr cur = attr->tree; 548 549 for (indx = 0; indx < 5; indx++) { 550 if (indx != 0) 551 fprintf(ctxt->output, "|%s", (char *) cur->name); 552 else 553 fprintf(ctxt->output, " (%s", (char *) cur->name); 554 cur = cur->next; 555 if (cur == NULL) 556 break; 557 } 558 if (cur == NULL) 559 fprintf(ctxt->output, ")"); 560 else 561 fprintf(ctxt->output, "...)"); 562 } 563 switch (attr->def) { 564 case XML_ATTRIBUTE_NONE: 565 break; 566 case XML_ATTRIBUTE_REQUIRED: 567 fprintf(ctxt->output, " REQUIRED"); 568 break; 569 case XML_ATTRIBUTE_IMPLIED: 570 fprintf(ctxt->output, " IMPLIED"); 571 break; 572 case XML_ATTRIBUTE_FIXED: 573 fprintf(ctxt->output, " FIXED"); 574 break; 575 } 576 if (attr->defaultValue != NULL) { 577 fprintf(ctxt->output, "\""); 578 xmlCtxtDumpString(ctxt, attr->defaultValue); 579 fprintf(ctxt->output, "\""); 580 } 581 fprintf(ctxt->output, "\n"); 582 } 583 584 /* 585 * Do a bit of checking 586 */ 587 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr); 588 } 589 590 static void 591 xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem) 592 { 593 xmlCtxtDumpSpaces(ctxt); 594 595 if (elem == NULL) { 596 if (!ctxt->check) 597 fprintf(ctxt->output, "Element declaration is NULL\n"); 598 return; 599 } 600 if (elem->type != XML_ELEMENT_DECL) { 601 xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL, 602 "Node is not an element declaration"); 603 return; 604 } 605 if (elem->name != NULL) { 606 if (!ctxt->check) { 607 fprintf(ctxt->output, "ELEMDECL("); 608 xmlCtxtDumpString(ctxt, elem->name); 609 fprintf(ctxt->output, ")"); 610 } 611 } else 612 xmlDebugErr(ctxt, XML_CHECK_NO_NAME, 613 "Element declaration has no name"); 614 if (!ctxt->check) { 615 switch (elem->etype) { 616 case XML_ELEMENT_TYPE_UNDEFINED: 617 fprintf(ctxt->output, ", UNDEFINED"); 618 break; 619 case XML_ELEMENT_TYPE_EMPTY: 620 fprintf(ctxt->output, ", EMPTY"); 621 break; 622 case XML_ELEMENT_TYPE_ANY: 623 fprintf(ctxt->output, ", ANY"); 624 break; 625 case XML_ELEMENT_TYPE_MIXED: 626 fprintf(ctxt->output, ", MIXED "); 627 break; 628 case XML_ELEMENT_TYPE_ELEMENT: 629 fprintf(ctxt->output, ", MIXED "); 630 break; 631 } 632 if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) { 633 char buf[5001]; 634 635 buf[0] = 0; 636 xmlSnprintfElementContent(buf, 5000, elem->content, 1); 637 buf[5000] = 0; 638 fprintf(ctxt->output, "%s", buf); 639 } 640 fprintf(ctxt->output, "\n"); 641 } 642 643 /* 644 * Do a bit of checking 645 */ 646 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem); 647 } 648 649 static void 650 xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent) 651 { 652 xmlCtxtDumpSpaces(ctxt); 653 654 if (ent == NULL) { 655 if (!ctxt->check) 656 fprintf(ctxt->output, "Entity declaration is NULL\n"); 657 return; 658 } 659 if (ent->type != XML_ENTITY_DECL) { 660 xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL, 661 "Node is not an entity declaration"); 662 return; 663 } 664 if (ent->name != NULL) { 665 if (!ctxt->check) { 666 fprintf(ctxt->output, "ENTITYDECL("); 667 xmlCtxtDumpString(ctxt, ent->name); 668 fprintf(ctxt->output, ")"); 669 } 670 } else 671 xmlDebugErr(ctxt, XML_CHECK_NO_NAME, 672 "Entity declaration has no name"); 673 if (!ctxt->check) { 674 switch (ent->etype) { 675 case XML_INTERNAL_GENERAL_ENTITY: 676 fprintf(ctxt->output, ", internal\n"); 677 break; 678 case XML_EXTERNAL_GENERAL_PARSED_ENTITY: 679 fprintf(ctxt->output, ", external parsed\n"); 680 break; 681 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: 682 fprintf(ctxt->output, ", unparsed\n"); 683 break; 684 case XML_INTERNAL_PARAMETER_ENTITY: 685 fprintf(ctxt->output, ", parameter\n"); 686 break; 687 case XML_EXTERNAL_PARAMETER_ENTITY: 688 fprintf(ctxt->output, ", external parameter\n"); 689 break; 690 case XML_INTERNAL_PREDEFINED_ENTITY: 691 fprintf(ctxt->output, ", predefined\n"); 692 break; 693 } 694 if (ent->ExternalID) { 695 xmlCtxtDumpSpaces(ctxt); 696 fprintf(ctxt->output, " ExternalID=%s\n", 697 (char *) ent->ExternalID); 698 } 699 if (ent->SystemID) { 700 xmlCtxtDumpSpaces(ctxt); 701 fprintf(ctxt->output, " SystemID=%s\n", 702 (char *) ent->SystemID); 703 } 704 if (ent->URI != NULL) { 705 xmlCtxtDumpSpaces(ctxt); 706 fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI); 707 } 708 if (ent->content) { 709 xmlCtxtDumpSpaces(ctxt); 710 fprintf(ctxt->output, " content="); 711 xmlCtxtDumpString(ctxt, ent->content); 712 fprintf(ctxt->output, "\n"); 713 } 714 } 715 716 /* 717 * Do a bit of checking 718 */ 719 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent); 720 } 721 722 static void 723 xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns) 724 { 725 xmlCtxtDumpSpaces(ctxt); 726 727 if (ns == NULL) { 728 if (!ctxt->check) 729 fprintf(ctxt->output, "namespace node is NULL\n"); 730 return; 731 } 732 if (ns->type != XML_NAMESPACE_DECL) { 733 xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL, 734 "Node is not a namespace declaration"); 735 return; 736 } 737 if (ns->href == NULL) { 738 if (ns->prefix != NULL) 739 xmlDebugErr3(ctxt, XML_CHECK_NO_HREF, 740 "Incomplete namespace %s href=NULL\n", 741 (char *) ns->prefix); 742 else 743 xmlDebugErr(ctxt, XML_CHECK_NO_HREF, 744 "Incomplete default namespace href=NULL\n"); 745 } else { 746 if (!ctxt->check) { 747 if (ns->prefix != NULL) 748 fprintf(ctxt->output, "namespace %s href=", 749 (char *) ns->prefix); 750 else 751 fprintf(ctxt->output, "default namespace href="); 752 753 xmlCtxtDumpString(ctxt, ns->href); 754 fprintf(ctxt->output, "\n"); 755 } 756 } 757 } 758 759 static void 760 xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns) 761 { 762 while (ns != NULL) { 763 xmlCtxtDumpNamespace(ctxt, ns); 764 ns = ns->next; 765 } 766 } 767 768 static void 769 xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent) 770 { 771 xmlCtxtDumpSpaces(ctxt); 772 773 if (ent == NULL) { 774 if (!ctxt->check) 775 fprintf(ctxt->output, "Entity is NULL\n"); 776 return; 777 } 778 if (!ctxt->check) { 779 switch (ent->etype) { 780 case XML_INTERNAL_GENERAL_ENTITY: 781 fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY "); 782 break; 783 case XML_EXTERNAL_GENERAL_PARSED_ENTITY: 784 fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY "); 785 break; 786 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: 787 fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY "); 788 break; 789 case XML_INTERNAL_PARAMETER_ENTITY: 790 fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY "); 791 break; 792 case XML_EXTERNAL_PARAMETER_ENTITY: 793 fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY "); 794 break; 795 default: 796 fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype); 797 } 798 fprintf(ctxt->output, "%s\n", ent->name); 799 if (ent->ExternalID) { 800 xmlCtxtDumpSpaces(ctxt); 801 fprintf(ctxt->output, "ExternalID=%s\n", 802 (char *) ent->ExternalID); 803 } 804 if (ent->SystemID) { 805 xmlCtxtDumpSpaces(ctxt); 806 fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID); 807 } 808 if (ent->URI) { 809 xmlCtxtDumpSpaces(ctxt); 810 fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI); 811 } 812 if (ent->content) { 813 xmlCtxtDumpSpaces(ctxt); 814 fprintf(ctxt->output, "content="); 815 xmlCtxtDumpString(ctxt, ent->content); 816 fprintf(ctxt->output, "\n"); 817 } 818 } 819 } 820 821 /** 822 * xmlCtxtDumpAttr: 823 * @output: the FILE * for the output 824 * @attr: the attribute 825 * @depth: the indentation level. 826 * 827 * Dumps debug information for the attribute 828 */ 829 static void 830 xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr) 831 { 832 xmlCtxtDumpSpaces(ctxt); 833 834 if (attr == NULL) { 835 if (!ctxt->check) 836 fprintf(ctxt->output, "Attr is NULL"); 837 return; 838 } 839 if (!ctxt->check) { 840 fprintf(ctxt->output, "ATTRIBUTE "); 841 xmlCtxtDumpString(ctxt, attr->name); 842 fprintf(ctxt->output, "\n"); 843 if (attr->children != NULL) { 844 ctxt->depth++; 845 xmlCtxtDumpNodeList(ctxt, attr->children); 846 ctxt->depth--; 847 } 848 } 849 if (attr->name == NULL) 850 xmlDebugErr(ctxt, XML_CHECK_NO_NAME, 851 "Attribute has no name"); 852 853 /* 854 * Do a bit of checking 855 */ 856 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr); 857 } 858 859 /** 860 * xmlCtxtDumpAttrList: 861 * @output: the FILE * for the output 862 * @attr: the attribute list 863 * @depth: the indentation level. 864 * 865 * Dumps debug information for the attribute list 866 */ 867 static void 868 xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr) 869 { 870 while (attr != NULL) { 871 xmlCtxtDumpAttr(ctxt, attr); 872 attr = attr->next; 873 } 874 } 875 876 /** 877 * xmlCtxtDumpOneNode: 878 * @output: the FILE * for the output 879 * @node: the node 880 * @depth: the indentation level. 881 * 882 * Dumps debug information for the element node, it is not recursive 883 */ 884 static void 885 xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node) 886 { 887 if (node == NULL) { 888 if (!ctxt->check) { 889 xmlCtxtDumpSpaces(ctxt); 890 fprintf(ctxt->output, "node is NULL\n"); 891 } 892 return; 893 } 894 ctxt->node = node; 895 896 switch (node->type) { 897 case XML_ELEMENT_NODE: 898 if (!ctxt->check) { 899 xmlCtxtDumpSpaces(ctxt); 900 fprintf(ctxt->output, "ELEMENT "); 901 if ((node->ns != NULL) && (node->ns->prefix != NULL)) { 902 xmlCtxtDumpString(ctxt, node->ns->prefix); 903 fprintf(ctxt->output, ":"); 904 } 905 xmlCtxtDumpString(ctxt, node->name); 906 fprintf(ctxt->output, "\n"); 907 } 908 break; 909 case XML_ATTRIBUTE_NODE: 910 if (!ctxt->check) 911 xmlCtxtDumpSpaces(ctxt); 912 fprintf(ctxt->output, "Error, ATTRIBUTE found here\n"); 913 xmlCtxtGenericNodeCheck(ctxt, node); 914 return; 915 case XML_TEXT_NODE: 916 if (!ctxt->check) { 917 xmlCtxtDumpSpaces(ctxt); 918 if (node->name == (const xmlChar *) xmlStringTextNoenc) 919 fprintf(ctxt->output, "TEXT no enc"); 920 else 921 fprintf(ctxt->output, "TEXT"); 922 if (ctxt->options & DUMP_TEXT_TYPE) { 923 if (node->content == (xmlChar *) &(node->properties)) 924 fprintf(ctxt->output, " compact\n"); 925 else if (xmlDictOwns(ctxt->dict, node->content) == 1) 926 fprintf(ctxt->output, " interned\n"); 927 else 928 fprintf(ctxt->output, "\n"); 929 } else 930 fprintf(ctxt->output, "\n"); 931 } 932 break; 933 case XML_CDATA_SECTION_NODE: 934 if (!ctxt->check) { 935 xmlCtxtDumpSpaces(ctxt); 936 fprintf(ctxt->output, "CDATA_SECTION\n"); 937 } 938 break; 939 case XML_ENTITY_REF_NODE: 940 if (!ctxt->check) { 941 xmlCtxtDumpSpaces(ctxt); 942 fprintf(ctxt->output, "ENTITY_REF(%s)\n", 943 (char *) node->name); 944 } 945 break; 946 case XML_ENTITY_NODE: 947 if (!ctxt->check) { 948 xmlCtxtDumpSpaces(ctxt); 949 fprintf(ctxt->output, "ENTITY\n"); 950 } 951 break; 952 case XML_PI_NODE: 953 if (!ctxt->check) { 954 xmlCtxtDumpSpaces(ctxt); 955 fprintf(ctxt->output, "PI %s\n", (char *) node->name); 956 } 957 break; 958 case XML_COMMENT_NODE: 959 if (!ctxt->check) { 960 xmlCtxtDumpSpaces(ctxt); 961 fprintf(ctxt->output, "COMMENT\n"); 962 } 963 break; 964 case XML_DOCUMENT_NODE: 965 case XML_HTML_DOCUMENT_NODE: 966 if (!ctxt->check) { 967 xmlCtxtDumpSpaces(ctxt); 968 } 969 fprintf(ctxt->output, "Error, DOCUMENT found here\n"); 970 xmlCtxtGenericNodeCheck(ctxt, node); 971 return; 972 case XML_DOCUMENT_TYPE_NODE: 973 if (!ctxt->check) { 974 xmlCtxtDumpSpaces(ctxt); 975 fprintf(ctxt->output, "DOCUMENT_TYPE\n"); 976 } 977 break; 978 case XML_DOCUMENT_FRAG_NODE: 979 if (!ctxt->check) { 980 xmlCtxtDumpSpaces(ctxt); 981 fprintf(ctxt->output, "DOCUMENT_FRAG\n"); 982 } 983 break; 984 case XML_NOTATION_NODE: 985 if (!ctxt->check) { 986 xmlCtxtDumpSpaces(ctxt); 987 fprintf(ctxt->output, "NOTATION\n"); 988 } 989 break; 990 case XML_DTD_NODE: 991 xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node); 992 return; 993 case XML_ELEMENT_DECL: 994 xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node); 995 return; 996 case XML_ATTRIBUTE_DECL: 997 xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node); 998 return; 999 case XML_ENTITY_DECL: 1000 xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node); 1001 return; 1002 case XML_NAMESPACE_DECL: 1003 xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node); 1004 return; 1005 case XML_XINCLUDE_START: 1006 if (!ctxt->check) { 1007 xmlCtxtDumpSpaces(ctxt); 1008 fprintf(ctxt->output, "INCLUDE START\n"); 1009 } 1010 return; 1011 case XML_XINCLUDE_END: 1012 if (!ctxt->check) { 1013 xmlCtxtDumpSpaces(ctxt); 1014 fprintf(ctxt->output, "INCLUDE END\n"); 1015 } 1016 return; 1017 default: 1018 if (!ctxt->check) 1019 xmlCtxtDumpSpaces(ctxt); 1020 xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE, 1021 "Unknown node type %d\n", node->type); 1022 return; 1023 } 1024 if (node->doc == NULL) { 1025 if (!ctxt->check) { 1026 xmlCtxtDumpSpaces(ctxt); 1027 } 1028 fprintf(ctxt->output, "PBM: doc == NULL !!!\n"); 1029 } 1030 ctxt->depth++; 1031 if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL)) 1032 xmlCtxtDumpNamespaceList(ctxt, node->nsDef); 1033 if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL)) 1034 xmlCtxtDumpAttrList(ctxt, node->properties); 1035 if (node->type != XML_ENTITY_REF_NODE) { 1036 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) { 1037 if (!ctxt->check) { 1038 xmlCtxtDumpSpaces(ctxt); 1039 fprintf(ctxt->output, "content="); 1040 xmlCtxtDumpString(ctxt, node->content); 1041 fprintf(ctxt->output, "\n"); 1042 } 1043 } 1044 } else { 1045 xmlEntityPtr ent; 1046 1047 ent = xmlGetDocEntity(node->doc, node->name); 1048 if (ent != NULL) 1049 xmlCtxtDumpEntity(ctxt, ent); 1050 } 1051 ctxt->depth--; 1052 1053 /* 1054 * Do a bit of checking 1055 */ 1056 xmlCtxtGenericNodeCheck(ctxt, node); 1057 } 1058 1059 /** 1060 * xmlCtxtDumpNode: 1061 * @output: the FILE * for the output 1062 * @node: the node 1063 * @depth: the indentation level. 1064 * 1065 * Dumps debug information for the element node, it is recursive 1066 */ 1067 static void 1068 xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node) 1069 { 1070 if (node == NULL) { 1071 if (!ctxt->check) { 1072 xmlCtxtDumpSpaces(ctxt); 1073 fprintf(ctxt->output, "node is NULL\n"); 1074 } 1075 return; 1076 } 1077 xmlCtxtDumpOneNode(ctxt, node); 1078 if ((node->type != XML_NAMESPACE_DECL) && 1079 (node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) { 1080 ctxt->depth++; 1081 xmlCtxtDumpNodeList(ctxt, node->children); 1082 ctxt->depth--; 1083 } 1084 } 1085 1086 /** 1087 * xmlCtxtDumpNodeList: 1088 * @output: the FILE * for the output 1089 * @node: the node list 1090 * @depth: the indentation level. 1091 * 1092 * Dumps debug information for the list of element node, it is recursive 1093 */ 1094 static void 1095 xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node) 1096 { 1097 while (node != NULL) { 1098 xmlCtxtDumpNode(ctxt, node); 1099 node = node->next; 1100 } 1101 } 1102 1103 static void 1104 xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc) 1105 { 1106 if (doc == NULL) { 1107 if (!ctxt->check) 1108 fprintf(ctxt->output, "DOCUMENT == NULL !\n"); 1109 return; 1110 } 1111 ctxt->node = (xmlNodePtr) doc; 1112 1113 switch (doc->type) { 1114 case XML_ELEMENT_NODE: 1115 xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT, 1116 "Misplaced ELEMENT node\n"); 1117 break; 1118 case XML_ATTRIBUTE_NODE: 1119 xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE, 1120 "Misplaced ATTRIBUTE node\n"); 1121 break; 1122 case XML_TEXT_NODE: 1123 xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT, 1124 "Misplaced TEXT node\n"); 1125 break; 1126 case XML_CDATA_SECTION_NODE: 1127 xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA, 1128 "Misplaced CDATA node\n"); 1129 break; 1130 case XML_ENTITY_REF_NODE: 1131 xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF, 1132 "Misplaced ENTITYREF node\n"); 1133 break; 1134 case XML_ENTITY_NODE: 1135 xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY, 1136 "Misplaced ENTITY node\n"); 1137 break; 1138 case XML_PI_NODE: 1139 xmlDebugErr(ctxt, XML_CHECK_FOUND_PI, 1140 "Misplaced PI node\n"); 1141 break; 1142 case XML_COMMENT_NODE: 1143 xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT, 1144 "Misplaced COMMENT node\n"); 1145 break; 1146 case XML_DOCUMENT_NODE: 1147 if (!ctxt->check) 1148 fprintf(ctxt->output, "DOCUMENT\n"); 1149 break; 1150 case XML_HTML_DOCUMENT_NODE: 1151 if (!ctxt->check) 1152 fprintf(ctxt->output, "HTML DOCUMENT\n"); 1153 break; 1154 case XML_DOCUMENT_TYPE_NODE: 1155 xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE, 1156 "Misplaced DOCTYPE node\n"); 1157 break; 1158 case XML_DOCUMENT_FRAG_NODE: 1159 xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT, 1160 "Misplaced FRAGMENT node\n"); 1161 break; 1162 case XML_NOTATION_NODE: 1163 xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION, 1164 "Misplaced NOTATION node\n"); 1165 break; 1166 default: 1167 xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE, 1168 "Unknown node type %d\n", doc->type); 1169 } 1170 } 1171 1172 /** 1173 * xmlCtxtDumpDocumentHead: 1174 * @output: the FILE * for the output 1175 * @doc: the document 1176 * 1177 * Dumps debug information cncerning the document, not recursive 1178 */ 1179 static void 1180 xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc) 1181 { 1182 if (doc == NULL) return; 1183 xmlCtxtDumpDocHead(ctxt, doc); 1184 if (!ctxt->check) { 1185 if (doc->name != NULL) { 1186 fprintf(ctxt->output, "name="); 1187 xmlCtxtDumpString(ctxt, BAD_CAST doc->name); 1188 fprintf(ctxt->output, "\n"); 1189 } 1190 if (doc->version != NULL) { 1191 fprintf(ctxt->output, "version="); 1192 xmlCtxtDumpString(ctxt, doc->version); 1193 fprintf(ctxt->output, "\n"); 1194 } 1195 if (doc->encoding != NULL) { 1196 fprintf(ctxt->output, "encoding="); 1197 xmlCtxtDumpString(ctxt, doc->encoding); 1198 fprintf(ctxt->output, "\n"); 1199 } 1200 if (doc->URL != NULL) { 1201 fprintf(ctxt->output, "URL="); 1202 xmlCtxtDumpString(ctxt, doc->URL); 1203 fprintf(ctxt->output, "\n"); 1204 } 1205 if (doc->standalone) 1206 fprintf(ctxt->output, "standalone=true\n"); 1207 } 1208 if (doc->oldNs != NULL) 1209 xmlCtxtDumpNamespaceList(ctxt, doc->oldNs); 1210 } 1211 1212 /** 1213 * xmlCtxtDumpDocument: 1214 * @output: the FILE * for the output 1215 * @doc: the document 1216 * 1217 * Dumps debug information for the document, it's recursive 1218 */ 1219 static void 1220 xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc) 1221 { 1222 if (doc == NULL) { 1223 if (!ctxt->check) 1224 fprintf(ctxt->output, "DOCUMENT == NULL !\n"); 1225 return; 1226 } 1227 xmlCtxtDumpDocumentHead(ctxt, doc); 1228 if (((doc->type == XML_DOCUMENT_NODE) || 1229 (doc->type == XML_HTML_DOCUMENT_NODE)) 1230 && (doc->children != NULL)) { 1231 ctxt->depth++; 1232 xmlCtxtDumpNodeList(ctxt, doc->children); 1233 ctxt->depth--; 1234 } 1235 } 1236 1237 static void 1238 xmlCtxtDumpEntityCallback(xmlEntityPtr cur, xmlDebugCtxtPtr ctxt) 1239 { 1240 if (cur == NULL) { 1241 if (!ctxt->check) 1242 fprintf(ctxt->output, "Entity is NULL"); 1243 return; 1244 } 1245 if (!ctxt->check) { 1246 fprintf(ctxt->output, "%s : ", (char *) cur->name); 1247 switch (cur->etype) { 1248 case XML_INTERNAL_GENERAL_ENTITY: 1249 fprintf(ctxt->output, "INTERNAL GENERAL, "); 1250 break; 1251 case XML_EXTERNAL_GENERAL_PARSED_ENTITY: 1252 fprintf(ctxt->output, "EXTERNAL PARSED, "); 1253 break; 1254 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: 1255 fprintf(ctxt->output, "EXTERNAL UNPARSED, "); 1256 break; 1257 case XML_INTERNAL_PARAMETER_ENTITY: 1258 fprintf(ctxt->output, "INTERNAL PARAMETER, "); 1259 break; 1260 case XML_EXTERNAL_PARAMETER_ENTITY: 1261 fprintf(ctxt->output, "EXTERNAL PARAMETER, "); 1262 break; 1263 default: 1264 xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE, 1265 "Unknown entity type %d\n", cur->etype); 1266 } 1267 if (cur->ExternalID != NULL) 1268 fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID); 1269 if (cur->SystemID != NULL) 1270 fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID); 1271 if (cur->orig != NULL) 1272 fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig); 1273 if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) 1274 fprintf(ctxt->output, "\n content \"%s\"", 1275 (char *) cur->content); 1276 fprintf(ctxt->output, "\n"); 1277 } 1278 } 1279 1280 /** 1281 * xmlCtxtDumpEntities: 1282 * @output: the FILE * for the output 1283 * @doc: the document 1284 * 1285 * Dumps debug information for all the entities in use by the document 1286 */ 1287 static void 1288 xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc) 1289 { 1290 if (doc == NULL) return; 1291 xmlCtxtDumpDocHead(ctxt, doc); 1292 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) { 1293 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 1294 doc->intSubset->entities; 1295 1296 if (!ctxt->check) 1297 fprintf(ctxt->output, "Entities in internal subset\n"); 1298 xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback, 1299 ctxt); 1300 } else 1301 fprintf(ctxt->output, "No entities in internal subset\n"); 1302 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) { 1303 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 1304 doc->extSubset->entities; 1305 1306 if (!ctxt->check) 1307 fprintf(ctxt->output, "Entities in external subset\n"); 1308 xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback, 1309 ctxt); 1310 } else if (!ctxt->check) 1311 fprintf(ctxt->output, "No entities in external subset\n"); 1312 } 1313 1314 /** 1315 * xmlCtxtDumpDTD: 1316 * @output: the FILE * for the output 1317 * @dtd: the DTD 1318 * 1319 * Dumps debug information for the DTD 1320 */ 1321 static void 1322 xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd) 1323 { 1324 if (dtd == NULL) { 1325 if (!ctxt->check) 1326 fprintf(ctxt->output, "DTD is NULL\n"); 1327 return; 1328 } 1329 xmlCtxtDumpDtdNode(ctxt, dtd); 1330 if (dtd->children == NULL) 1331 fprintf(ctxt->output, " DTD is empty\n"); 1332 else { 1333 ctxt->depth++; 1334 xmlCtxtDumpNodeList(ctxt, dtd->children); 1335 ctxt->depth--; 1336 } 1337 } 1338 1339 /************************************************************************ 1340 * * 1341 * Public entry points for dump * 1342 * * 1343 ************************************************************************/ 1344 1345 /** 1346 * xmlDebugDumpString: 1347 * @output: the FILE * for the output 1348 * @str: the string 1349 * 1350 * Dumps informations about the string, shorten it if necessary 1351 */ 1352 void 1353 xmlDebugDumpString(FILE * output, const xmlChar * str) 1354 { 1355 int i; 1356 1357 if (output == NULL) 1358 output = stdout; 1359 if (str == NULL) { 1360 fprintf(output, "(NULL)"); 1361 return; 1362 } 1363 for (i = 0; i < 40; i++) 1364 if (str[i] == 0) 1365 return; 1366 else if (IS_BLANK_CH(str[i])) 1367 fputc(' ', output); 1368 else if (str[i] >= 0x80) 1369 fprintf(output, "#%X", str[i]); 1370 else 1371 fputc(str[i], output); 1372 fprintf(output, "..."); 1373 } 1374 1375 /** 1376 * xmlDebugDumpAttr: 1377 * @output: the FILE * for the output 1378 * @attr: the attribute 1379 * @depth: the indentation level. 1380 * 1381 * Dumps debug information for the attribute 1382 */ 1383 void 1384 xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) { 1385 xmlDebugCtxt ctxt; 1386 1387 if (output == NULL) return; 1388 xmlCtxtDumpInitCtxt(&ctxt); 1389 ctxt.output = output; 1390 ctxt.depth = depth; 1391 xmlCtxtDumpAttr(&ctxt, attr); 1392 xmlCtxtDumpCleanCtxt(&ctxt); 1393 } 1394 1395 1396 /** 1397 * xmlDebugDumpEntities: 1398 * @output: the FILE * for the output 1399 * @doc: the document 1400 * 1401 * Dumps debug information for all the entities in use by the document 1402 */ 1403 void 1404 xmlDebugDumpEntities(FILE * output, xmlDocPtr doc) 1405 { 1406 xmlDebugCtxt ctxt; 1407 1408 if (output == NULL) return; 1409 xmlCtxtDumpInitCtxt(&ctxt); 1410 ctxt.output = output; 1411 xmlCtxtDumpEntities(&ctxt, doc); 1412 xmlCtxtDumpCleanCtxt(&ctxt); 1413 } 1414 1415 /** 1416 * xmlDebugDumpAttrList: 1417 * @output: the FILE * for the output 1418 * @attr: the attribute list 1419 * @depth: the indentation level. 1420 * 1421 * Dumps debug information for the attribute list 1422 */ 1423 void 1424 xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth) 1425 { 1426 xmlDebugCtxt ctxt; 1427 1428 if (output == NULL) return; 1429 xmlCtxtDumpInitCtxt(&ctxt); 1430 ctxt.output = output; 1431 ctxt.depth = depth; 1432 xmlCtxtDumpAttrList(&ctxt, attr); 1433 xmlCtxtDumpCleanCtxt(&ctxt); 1434 } 1435 1436 /** 1437 * xmlDebugDumpOneNode: 1438 * @output: the FILE * for the output 1439 * @node: the node 1440 * @depth: the indentation level. 1441 * 1442 * Dumps debug information for the element node, it is not recursive 1443 */ 1444 void 1445 xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth) 1446 { 1447 xmlDebugCtxt ctxt; 1448 1449 if (output == NULL) return; 1450 xmlCtxtDumpInitCtxt(&ctxt); 1451 ctxt.output = output; 1452 ctxt.depth = depth; 1453 xmlCtxtDumpOneNode(&ctxt, node); 1454 xmlCtxtDumpCleanCtxt(&ctxt); 1455 } 1456 1457 /** 1458 * xmlDebugDumpNode: 1459 * @output: the FILE * for the output 1460 * @node: the node 1461 * @depth: the indentation level. 1462 * 1463 * Dumps debug information for the element node, it is recursive 1464 */ 1465 void 1466 xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth) 1467 { 1468 xmlDebugCtxt ctxt; 1469 1470 if (output == NULL) 1471 output = stdout; 1472 xmlCtxtDumpInitCtxt(&ctxt); 1473 ctxt.output = output; 1474 ctxt.depth = depth; 1475 xmlCtxtDumpNode(&ctxt, node); 1476 xmlCtxtDumpCleanCtxt(&ctxt); 1477 } 1478 1479 /** 1480 * xmlDebugDumpNodeList: 1481 * @output: the FILE * for the output 1482 * @node: the node list 1483 * @depth: the indentation level. 1484 * 1485 * Dumps debug information for the list of element node, it is recursive 1486 */ 1487 void 1488 xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth) 1489 { 1490 xmlDebugCtxt ctxt; 1491 1492 if (output == NULL) 1493 output = stdout; 1494 xmlCtxtDumpInitCtxt(&ctxt); 1495 ctxt.output = output; 1496 ctxt.depth = depth; 1497 xmlCtxtDumpNodeList(&ctxt, node); 1498 xmlCtxtDumpCleanCtxt(&ctxt); 1499 } 1500 1501 /** 1502 * xmlDebugDumpDocumentHead: 1503 * @output: the FILE * for the output 1504 * @doc: the document 1505 * 1506 * Dumps debug information cncerning the document, not recursive 1507 */ 1508 void 1509 xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc) 1510 { 1511 xmlDebugCtxt ctxt; 1512 1513 if (output == NULL) 1514 output = stdout; 1515 xmlCtxtDumpInitCtxt(&ctxt); 1516 ctxt.options |= DUMP_TEXT_TYPE; 1517 ctxt.output = output; 1518 xmlCtxtDumpDocumentHead(&ctxt, doc); 1519 xmlCtxtDumpCleanCtxt(&ctxt); 1520 } 1521 1522 /** 1523 * xmlDebugDumpDocument: 1524 * @output: the FILE * for the output 1525 * @doc: the document 1526 * 1527 * Dumps debug information for the document, it's recursive 1528 */ 1529 void 1530 xmlDebugDumpDocument(FILE * output, xmlDocPtr doc) 1531 { 1532 xmlDebugCtxt ctxt; 1533 1534 if (output == NULL) 1535 output = stdout; 1536 xmlCtxtDumpInitCtxt(&ctxt); 1537 ctxt.options |= DUMP_TEXT_TYPE; 1538 ctxt.output = output; 1539 xmlCtxtDumpDocument(&ctxt, doc); 1540 xmlCtxtDumpCleanCtxt(&ctxt); 1541 } 1542 1543 /** 1544 * xmlDebugDumpDTD: 1545 * @output: the FILE * for the output 1546 * @dtd: the DTD 1547 * 1548 * Dumps debug information for the DTD 1549 */ 1550 void 1551 xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd) 1552 { 1553 xmlDebugCtxt ctxt; 1554 1555 if (output == NULL) 1556 output = stdout; 1557 xmlCtxtDumpInitCtxt(&ctxt); 1558 ctxt.options |= DUMP_TEXT_TYPE; 1559 ctxt.output = output; 1560 xmlCtxtDumpDTD(&ctxt, dtd); 1561 xmlCtxtDumpCleanCtxt(&ctxt); 1562 } 1563 1564 /************************************************************************ 1565 * * 1566 * Public entry points for checkings * 1567 * * 1568 ************************************************************************/ 1569 1570 /** 1571 * xmlDebugCheckDocument: 1572 * @output: the FILE * for the output 1573 * @doc: the document 1574 * 1575 * Check the document for potential content problems, and output 1576 * the errors to @output 1577 * 1578 * Returns the number of errors found 1579 */ 1580 int 1581 xmlDebugCheckDocument(FILE * output, xmlDocPtr doc) 1582 { 1583 xmlDebugCtxt ctxt; 1584 1585 if (output == NULL) 1586 output = stdout; 1587 xmlCtxtDumpInitCtxt(&ctxt); 1588 ctxt.output = output; 1589 ctxt.check = 1; 1590 xmlCtxtDumpDocument(&ctxt, doc); 1591 xmlCtxtDumpCleanCtxt(&ctxt); 1592 return(ctxt.errors); 1593 } 1594 1595 /************************************************************************ 1596 * * 1597 * Helpers for Shell * 1598 * * 1599 ************************************************************************/ 1600 1601 /** 1602 * xmlLsCountNode: 1603 * @node: the node to count 1604 * 1605 * Count the children of @node. 1606 * 1607 * Returns the number of children of @node. 1608 */ 1609 int 1610 xmlLsCountNode(xmlNodePtr node) { 1611 int ret = 0; 1612 xmlNodePtr list = NULL; 1613 1614 if (node == NULL) 1615 return(0); 1616 1617 switch (node->type) { 1618 case XML_ELEMENT_NODE: 1619 list = node->children; 1620 break; 1621 case XML_DOCUMENT_NODE: 1622 case XML_HTML_DOCUMENT_NODE: 1623 #ifdef LIBXML_DOCB_ENABLED 1624 case XML_DOCB_DOCUMENT_NODE: 1625 #endif 1626 list = ((xmlDocPtr) node)->children; 1627 break; 1628 case XML_ATTRIBUTE_NODE: 1629 list = ((xmlAttrPtr) node)->children; 1630 break; 1631 case XML_TEXT_NODE: 1632 case XML_CDATA_SECTION_NODE: 1633 case XML_PI_NODE: 1634 case XML_COMMENT_NODE: 1635 if (node->content != NULL) { 1636 ret = xmlStrlen(node->content); 1637 } 1638 break; 1639 case XML_ENTITY_REF_NODE: 1640 case XML_DOCUMENT_TYPE_NODE: 1641 case XML_ENTITY_NODE: 1642 case XML_DOCUMENT_FRAG_NODE: 1643 case XML_NOTATION_NODE: 1644 case XML_DTD_NODE: 1645 case XML_ELEMENT_DECL: 1646 case XML_ATTRIBUTE_DECL: 1647 case XML_ENTITY_DECL: 1648 case XML_NAMESPACE_DECL: 1649 case XML_XINCLUDE_START: 1650 case XML_XINCLUDE_END: 1651 ret = 1; 1652 break; 1653 } 1654 for (;list != NULL;ret++) 1655 list = list->next; 1656 return(ret); 1657 } 1658 1659 /** 1660 * xmlLsOneNode: 1661 * @output: the FILE * for the output 1662 * @node: the node to dump 1663 * 1664 * Dump to @output the type and name of @node. 1665 */ 1666 void 1667 xmlLsOneNode(FILE *output, xmlNodePtr node) { 1668 if (output == NULL) return; 1669 if (node == NULL) { 1670 fprintf(output, "NULL\n"); 1671 return; 1672 } 1673 switch (node->type) { 1674 case XML_ELEMENT_NODE: 1675 fprintf(output, "-"); 1676 break; 1677 case XML_ATTRIBUTE_NODE: 1678 fprintf(output, "a"); 1679 break; 1680 case XML_TEXT_NODE: 1681 fprintf(output, "t"); 1682 break; 1683 case XML_CDATA_SECTION_NODE: 1684 fprintf(output, "C"); 1685 break; 1686 case XML_ENTITY_REF_NODE: 1687 fprintf(output, "e"); 1688 break; 1689 case XML_ENTITY_NODE: 1690 fprintf(output, "E"); 1691 break; 1692 case XML_PI_NODE: 1693 fprintf(output, "p"); 1694 break; 1695 case XML_COMMENT_NODE: 1696 fprintf(output, "c"); 1697 break; 1698 case XML_DOCUMENT_NODE: 1699 fprintf(output, "d"); 1700 break; 1701 case XML_HTML_DOCUMENT_NODE: 1702 fprintf(output, "h"); 1703 break; 1704 case XML_DOCUMENT_TYPE_NODE: 1705 fprintf(output, "T"); 1706 break; 1707 case XML_DOCUMENT_FRAG_NODE: 1708 fprintf(output, "F"); 1709 break; 1710 case XML_NOTATION_NODE: 1711 fprintf(output, "N"); 1712 break; 1713 case XML_NAMESPACE_DECL: 1714 fprintf(output, "n"); 1715 break; 1716 default: 1717 fprintf(output, "?"); 1718 } 1719 if (node->type != XML_NAMESPACE_DECL) { 1720 if (node->properties != NULL) 1721 fprintf(output, "a"); 1722 else 1723 fprintf(output, "-"); 1724 if (node->nsDef != NULL) 1725 fprintf(output, "n"); 1726 else 1727 fprintf(output, "-"); 1728 } 1729 1730 fprintf(output, " %8d ", xmlLsCountNode(node)); 1731 1732 switch (node->type) { 1733 case XML_ELEMENT_NODE: 1734 if (node->name != NULL) { 1735 if ((node->ns != NULL) && (node->ns->prefix != NULL)) 1736 fprintf(output, "%s:", node->ns->prefix); 1737 fprintf(output, "%s", (const char *) node->name); 1738 } 1739 break; 1740 case XML_ATTRIBUTE_NODE: 1741 if (node->name != NULL) 1742 fprintf(output, "%s", (const char *) node->name); 1743 break; 1744 case XML_TEXT_NODE: 1745 if (node->content != NULL) { 1746 xmlDebugDumpString(output, node->content); 1747 } 1748 break; 1749 case XML_CDATA_SECTION_NODE: 1750 break; 1751 case XML_ENTITY_REF_NODE: 1752 if (node->name != NULL) 1753 fprintf(output, "%s", (const char *) node->name); 1754 break; 1755 case XML_ENTITY_NODE: 1756 if (node->name != NULL) 1757 fprintf(output, "%s", (const char *) node->name); 1758 break; 1759 case XML_PI_NODE: 1760 if (node->name != NULL) 1761 fprintf(output, "%s", (const char *) node->name); 1762 break; 1763 case XML_COMMENT_NODE: 1764 break; 1765 case XML_DOCUMENT_NODE: 1766 break; 1767 case XML_HTML_DOCUMENT_NODE: 1768 break; 1769 case XML_DOCUMENT_TYPE_NODE: 1770 break; 1771 case XML_DOCUMENT_FRAG_NODE: 1772 break; 1773 case XML_NOTATION_NODE: 1774 break; 1775 case XML_NAMESPACE_DECL: { 1776 xmlNsPtr ns = (xmlNsPtr) node; 1777 1778 if (ns->prefix == NULL) 1779 fprintf(output, "default -> %s", (char *)ns->href); 1780 else 1781 fprintf(output, "%s -> %s", (char *)ns->prefix, 1782 (char *)ns->href); 1783 break; 1784 } 1785 default: 1786 if (node->name != NULL) 1787 fprintf(output, "%s", (const char *) node->name); 1788 } 1789 fprintf(output, "\n"); 1790 } 1791 1792 /** 1793 * xmlBoolToText: 1794 * @boolval: a bool to turn into text 1795 * 1796 * Convenient way to turn bool into text 1797 * 1798 * Returns a pointer to either "True" or "False" 1799 */ 1800 const char * 1801 xmlBoolToText(int boolval) 1802 { 1803 if (boolval) 1804 return("True"); 1805 else 1806 return("False"); 1807 } 1808 1809 #ifdef LIBXML_XPATH_ENABLED 1810 /**************************************************************** 1811 * * 1812 * The XML shell related functions * 1813 * * 1814 ****************************************************************/ 1815 1816 1817 1818 /* 1819 * TODO: Improvement/cleanups for the XML shell 1820 * - allow to shell out an editor on a subpart 1821 * - cleanup function registrations (with help) and calling 1822 * - provide registration routines 1823 */ 1824 1825 /** 1826 * xmlShellPrintXPathError: 1827 * @errorType: valid xpath error id 1828 * @arg: the argument that cause xpath to fail 1829 * 1830 * Print the xpath error to libxml default error channel 1831 */ 1832 void 1833 xmlShellPrintXPathError(int errorType, const char *arg) 1834 { 1835 const char *default_arg = "Result"; 1836 1837 if (!arg) 1838 arg = default_arg; 1839 1840 switch (errorType) { 1841 case XPATH_UNDEFINED: 1842 xmlGenericError(xmlGenericErrorContext, 1843 "%s: no such node\n", arg); 1844 break; 1845 1846 case XPATH_BOOLEAN: 1847 xmlGenericError(xmlGenericErrorContext, 1848 "%s is a Boolean\n", arg); 1849 break; 1850 case XPATH_NUMBER: 1851 xmlGenericError(xmlGenericErrorContext, 1852 "%s is a number\n", arg); 1853 break; 1854 case XPATH_STRING: 1855 xmlGenericError(xmlGenericErrorContext, 1856 "%s is a string\n", arg); 1857 break; 1858 case XPATH_POINT: 1859 xmlGenericError(xmlGenericErrorContext, 1860 "%s is a point\n", arg); 1861 break; 1862 case XPATH_RANGE: 1863 xmlGenericError(xmlGenericErrorContext, 1864 "%s is a range\n", arg); 1865 break; 1866 case XPATH_LOCATIONSET: 1867 xmlGenericError(xmlGenericErrorContext, 1868 "%s is a range\n", arg); 1869 break; 1870 case XPATH_USERS: 1871 xmlGenericError(xmlGenericErrorContext, 1872 "%s is user-defined\n", arg); 1873 break; 1874 case XPATH_XSLT_TREE: 1875 xmlGenericError(xmlGenericErrorContext, 1876 "%s is an XSLT value tree\n", arg); 1877 break; 1878 } 1879 #if 0 1880 xmlGenericError(xmlGenericErrorContext, 1881 "Try casting the result string function (xpath builtin)\n", 1882 arg); 1883 #endif 1884 } 1885 1886 1887 #ifdef LIBXML_OUTPUT_ENABLED 1888 /** 1889 * xmlShellPrintNodeCtxt: 1890 * @ctxt : a non-null shell context 1891 * @node : a non-null node to print to the output FILE 1892 * 1893 * Print node to the output FILE 1894 */ 1895 static void 1896 xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node) 1897 { 1898 FILE *fp; 1899 1900 if (!node) 1901 return; 1902 if (ctxt == NULL) 1903 fp = stdout; 1904 else 1905 fp = ctxt->output; 1906 1907 if (node->type == XML_DOCUMENT_NODE) 1908 xmlDocDump(fp, (xmlDocPtr) node); 1909 else if (node->type == XML_ATTRIBUTE_NODE) 1910 xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0); 1911 else 1912 xmlElemDump(fp, node->doc, node); 1913 1914 fprintf(fp, "\n"); 1915 } 1916 1917 /** 1918 * xmlShellPrintNode: 1919 * @node : a non-null node to print to the output FILE 1920 * 1921 * Print node to the output FILE 1922 */ 1923 void 1924 xmlShellPrintNode(xmlNodePtr node) 1925 { 1926 xmlShellPrintNodeCtxt(NULL, node); 1927 } 1928 #endif /* LIBXML_OUTPUT_ENABLED */ 1929 1930 /** 1931 * xmlShellPrintXPathResultCtxt: 1932 * @ctxt: a valid shell context 1933 * @list: a valid result generated by an xpath evaluation 1934 * 1935 * Prints result to the output FILE 1936 */ 1937 static void 1938 xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list) 1939 { 1940 if (!ctxt) 1941 return; 1942 1943 if (list != NULL) { 1944 switch (list->type) { 1945 case XPATH_NODESET:{ 1946 #ifdef LIBXML_OUTPUT_ENABLED 1947 int indx; 1948 1949 if (list->nodesetval) { 1950 for (indx = 0; indx < list->nodesetval->nodeNr; 1951 indx++) { 1952 xmlShellPrintNodeCtxt(ctxt, 1953 list->nodesetval->nodeTab[indx]); 1954 } 1955 } else { 1956 xmlGenericError(xmlGenericErrorContext, 1957 "Empty node set\n"); 1958 } 1959 break; 1960 #else 1961 xmlGenericError(xmlGenericErrorContext, 1962 "Node set\n"); 1963 #endif /* LIBXML_OUTPUT_ENABLED */ 1964 } 1965 case XPATH_BOOLEAN: 1966 xmlGenericError(xmlGenericErrorContext, 1967 "Is a Boolean:%s\n", 1968 xmlBoolToText(list->boolval)); 1969 break; 1970 case XPATH_NUMBER: 1971 xmlGenericError(xmlGenericErrorContext, 1972 "Is a number:%0g\n", list->floatval); 1973 break; 1974 case XPATH_STRING: 1975 xmlGenericError(xmlGenericErrorContext, 1976 "Is a string:%s\n", list->stringval); 1977 break; 1978 1979 default: 1980 xmlShellPrintXPathError(list->type, NULL); 1981 } 1982 } 1983 } 1984 1985 /** 1986 * xmlShellPrintXPathResult: 1987 * @list: a valid result generated by an xpath evaluation 1988 * 1989 * Prints result to the output FILE 1990 */ 1991 void 1992 xmlShellPrintXPathResult(xmlXPathObjectPtr list) 1993 { 1994 xmlShellPrintXPathResultCtxt(NULL, list); 1995 } 1996 1997 /** 1998 * xmlShellList: 1999 * @ctxt: the shell context 2000 * @arg: unused 2001 * @node: a node 2002 * @node2: unused 2003 * 2004 * Implements the XML shell function "ls" 2005 * Does an Unix like listing of the given node (like a directory) 2006 * 2007 * Returns 0 2008 */ 2009 int 2010 xmlShellList(xmlShellCtxtPtr ctxt, 2011 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, 2012 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2013 { 2014 xmlNodePtr cur; 2015 if (!ctxt) 2016 return (0); 2017 if (node == NULL) { 2018 fprintf(ctxt->output, "NULL\n"); 2019 return (0); 2020 } 2021 if ((node->type == XML_DOCUMENT_NODE) || 2022 (node->type == XML_HTML_DOCUMENT_NODE)) { 2023 cur = ((xmlDocPtr) node)->children; 2024 } else if (node->type == XML_NAMESPACE_DECL) { 2025 xmlLsOneNode(ctxt->output, node); 2026 return (0); 2027 } else if (node->children != NULL) { 2028 cur = node->children; 2029 } else { 2030 xmlLsOneNode(ctxt->output, node); 2031 return (0); 2032 } 2033 while (cur != NULL) { 2034 xmlLsOneNode(ctxt->output, cur); 2035 cur = cur->next; 2036 } 2037 return (0); 2038 } 2039 2040 /** 2041 * xmlShellBase: 2042 * @ctxt: the shell context 2043 * @arg: unused 2044 * @node: a node 2045 * @node2: unused 2046 * 2047 * Implements the XML shell function "base" 2048 * dumps the current XML base of the node 2049 * 2050 * Returns 0 2051 */ 2052 int 2053 xmlShellBase(xmlShellCtxtPtr ctxt, 2054 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, 2055 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2056 { 2057 xmlChar *base; 2058 if (!ctxt) 2059 return 0; 2060 if (node == NULL) { 2061 fprintf(ctxt->output, "NULL\n"); 2062 return (0); 2063 } 2064 2065 base = xmlNodeGetBase(node->doc, node); 2066 2067 if (base == NULL) { 2068 fprintf(ctxt->output, " No base found !!!\n"); 2069 } else { 2070 fprintf(ctxt->output, "%s\n", base); 2071 xmlFree(base); 2072 } 2073 return (0); 2074 } 2075 2076 #ifdef LIBXML_TREE_ENABLED 2077 /** 2078 * xmlShellSetBase: 2079 * @ctxt: the shell context 2080 * @arg: the new base 2081 * @node: a node 2082 * @node2: unused 2083 * 2084 * Implements the XML shell function "setbase" 2085 * change the current XML base of the node 2086 * 2087 * Returns 0 2088 */ 2089 static int 2090 xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, 2091 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, 2092 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2093 { 2094 xmlNodeSetBase(node, (xmlChar*) arg); 2095 return (0); 2096 } 2097 #endif 2098 2099 #ifdef LIBXML_XPATH_ENABLED 2100 /** 2101 * xmlShellRegisterNamespace: 2102 * @ctxt: the shell context 2103 * @arg: a string in prefix=nsuri format 2104 * @node: unused 2105 * @node2: unused 2106 * 2107 * Implements the XML shell function "setns" 2108 * register/unregister a prefix=namespace pair 2109 * on the XPath context 2110 * 2111 * Returns 0 on success and a negative value otherwise. 2112 */ 2113 static int 2114 xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg, 2115 xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED) 2116 { 2117 xmlChar* nsListDup; 2118 xmlChar* prefix; 2119 xmlChar* href; 2120 xmlChar* next; 2121 2122 nsListDup = xmlStrdup((xmlChar *) arg); 2123 next = nsListDup; 2124 while(next != NULL) { 2125 /* skip spaces */ 2126 /*while((*next) == ' ') next++;*/ 2127 if((*next) == '\0') break; 2128 2129 /* find prefix */ 2130 prefix = next; 2131 next = (xmlChar*)xmlStrchr(next, '='); 2132 if(next == NULL) { 2133 fprintf(ctxt->output, "setns: prefix=[nsuri] required\n"); 2134 xmlFree(nsListDup); 2135 return(-1); 2136 } 2137 *(next++) = '\0'; 2138 2139 /* find href */ 2140 href = next; 2141 next = (xmlChar*)xmlStrchr(next, ' '); 2142 if(next != NULL) { 2143 *(next++) = '\0'; 2144 } 2145 2146 /* do register namespace */ 2147 if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) { 2148 fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href); 2149 xmlFree(nsListDup); 2150 return(-1); 2151 } 2152 } 2153 2154 xmlFree(nsListDup); 2155 return(0); 2156 } 2157 /** 2158 * xmlShellRegisterRootNamespaces: 2159 * @ctxt: the shell context 2160 * @arg: unused 2161 * @node: the root element 2162 * @node2: unused 2163 * 2164 * Implements the XML shell function "setrootns" 2165 * which registers all namespaces declarations found on the root element. 2166 * 2167 * Returns 0 on success and a negative value otherwise. 2168 */ 2169 static int 2170 xmlShellRegisterRootNamespaces(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED, 2171 xmlNodePtr root, xmlNodePtr node2 ATTRIBUTE_UNUSED) 2172 { 2173 xmlNsPtr ns; 2174 2175 if ((root == NULL) || (root->type != XML_ELEMENT_NODE) || 2176 (root->nsDef == NULL) || (ctxt == NULL) || (ctxt->pctxt == NULL)) 2177 return(-1); 2178 ns = root->nsDef; 2179 while (ns != NULL) { 2180 if (ns->prefix == NULL) 2181 xmlXPathRegisterNs(ctxt->pctxt, BAD_CAST "defaultns", ns->href); 2182 else 2183 xmlXPathRegisterNs(ctxt->pctxt, ns->prefix, ns->href); 2184 ns = ns->next; 2185 } 2186 return(0); 2187 } 2188 #endif 2189 2190 /** 2191 * xmlShellGrep: 2192 * @ctxt: the shell context 2193 * @arg: the string or regular expression to find 2194 * @node: a node 2195 * @node2: unused 2196 * 2197 * Implements the XML shell function "grep" 2198 * dumps informations about the node (namespace, attributes, content). 2199 * 2200 * Returns 0 2201 */ 2202 static int 2203 xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, 2204 char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) 2205 { 2206 if (!ctxt) 2207 return (0); 2208 if (node == NULL) 2209 return (0); 2210 if (arg == NULL) 2211 return (0); 2212 #ifdef LIBXML_REGEXP_ENABLED 2213 if ((xmlStrchr((xmlChar *) arg, '?')) || 2214 (xmlStrchr((xmlChar *) arg, '*')) || 2215 (xmlStrchr((xmlChar *) arg, '.')) || 2216 (xmlStrchr((xmlChar *) arg, '['))) { 2217 } 2218 #endif 2219 while (node != NULL) { 2220 if (node->type == XML_COMMENT_NODE) { 2221 if (xmlStrstr(node->content, (xmlChar *) arg)) { 2222 2223 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node)); 2224 xmlShellList(ctxt, NULL, node, NULL); 2225 } 2226 } else if (node->type == XML_TEXT_NODE) { 2227 if (xmlStrstr(node->content, (xmlChar *) arg)) { 2228 2229 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent)); 2230 xmlShellList(ctxt, NULL, node->parent, NULL); 2231 } 2232 } 2233 2234 /* 2235 * Browse the full subtree, deep first 2236 */ 2237 2238 if ((node->type == XML_DOCUMENT_NODE) || 2239 (node->type == XML_HTML_DOCUMENT_NODE)) { 2240 node = ((xmlDocPtr) node)->children; 2241 } else if ((node->children != NULL) 2242 && (node->type != XML_ENTITY_REF_NODE)) { 2243 /* deep first */ 2244 node = node->children; 2245 } else if (node->next != NULL) { 2246 /* then siblings */ 2247 node = node->next; 2248 } else { 2249 /* go up to parents->next if needed */ 2250 while (node != NULL) { 2251 if (node->parent != NULL) { 2252 node = node->parent; 2253 } 2254 if (node->next != NULL) { 2255 node = node->next; 2256 break; 2257 } 2258 if (node->parent == NULL) { 2259 node = NULL; 2260 break; 2261 } 2262 } 2263 } 2264 } 2265 return (0); 2266 } 2267 2268 /** 2269 * xmlShellDir: 2270 * @ctxt: the shell context 2271 * @arg: unused 2272 * @node: a node 2273 * @node2: unused 2274 * 2275 * Implements the XML shell function "dir" 2276 * dumps informations about the node (namespace, attributes, content). 2277 * 2278 * Returns 0 2279 */ 2280 int 2281 xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, 2282 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, 2283 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2284 { 2285 if (!ctxt) 2286 return (0); 2287 if (node == NULL) { 2288 fprintf(ctxt->output, "NULL\n"); 2289 return (0); 2290 } 2291 if ((node->type == XML_DOCUMENT_NODE) || 2292 (node->type == XML_HTML_DOCUMENT_NODE)) { 2293 xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node); 2294 } else if (node->type == XML_ATTRIBUTE_NODE) { 2295 xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0); 2296 } else { 2297 xmlDebugDumpOneNode(ctxt->output, node, 0); 2298 } 2299 return (0); 2300 } 2301 2302 /** 2303 * xmlShellSetContent: 2304 * @ctxt: the shell context 2305 * @value: the content as a string 2306 * @node: a node 2307 * @node2: unused 2308 * 2309 * Implements the XML shell function "dir" 2310 * dumps informations about the node (namespace, attributes, content). 2311 * 2312 * Returns 0 2313 */ 2314 static int 2315 xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, 2316 char *value, xmlNodePtr node, 2317 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2318 { 2319 xmlNodePtr results; 2320 xmlParserErrors ret; 2321 2322 if (!ctxt) 2323 return (0); 2324 if (node == NULL) { 2325 fprintf(ctxt->output, "NULL\n"); 2326 return (0); 2327 } 2328 if (value == NULL) { 2329 fprintf(ctxt->output, "NULL\n"); 2330 return (0); 2331 } 2332 2333 ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results); 2334 if (ret == XML_ERR_OK) { 2335 if (node->children != NULL) { 2336 xmlFreeNodeList(node->children); 2337 node->children = NULL; 2338 node->last = NULL; 2339 } 2340 xmlAddChildList(node, results); 2341 } else { 2342 fprintf(ctxt->output, "failed to parse content\n"); 2343 } 2344 return (0); 2345 } 2346 2347 #ifdef LIBXML_SCHEMAS_ENABLED 2348 /** 2349 * xmlShellRNGValidate: 2350 * @ctxt: the shell context 2351 * @schemas: the path to the Relax-NG schemas 2352 * @node: a node 2353 * @node2: unused 2354 * 2355 * Implements the XML shell function "relaxng" 2356 * validating the instance against a Relax-NG schemas 2357 * 2358 * Returns 0 2359 */ 2360 static int 2361 xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas, 2362 xmlNodePtr node ATTRIBUTE_UNUSED, 2363 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2364 { 2365 xmlRelaxNGPtr relaxngschemas; 2366 xmlRelaxNGParserCtxtPtr ctxt; 2367 xmlRelaxNGValidCtxtPtr vctxt; 2368 int ret; 2369 2370 ctxt = xmlRelaxNGNewParserCtxt(schemas); 2371 xmlRelaxNGSetParserErrors(ctxt, 2372 (xmlRelaxNGValidityErrorFunc) fprintf, 2373 (xmlRelaxNGValidityWarningFunc) fprintf, 2374 stderr); 2375 relaxngschemas = xmlRelaxNGParse(ctxt); 2376 xmlRelaxNGFreeParserCtxt(ctxt); 2377 if (relaxngschemas == NULL) { 2378 xmlGenericError(xmlGenericErrorContext, 2379 "Relax-NG schema %s failed to compile\n", schemas); 2380 return(-1); 2381 } 2382 vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas); 2383 xmlRelaxNGSetValidErrors(vctxt, 2384 (xmlRelaxNGValidityErrorFunc) fprintf, 2385 (xmlRelaxNGValidityWarningFunc) fprintf, 2386 stderr); 2387 ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc); 2388 if (ret == 0) { 2389 fprintf(stderr, "%s validates\n", sctxt->filename); 2390 } else if (ret > 0) { 2391 fprintf(stderr, "%s fails to validate\n", sctxt->filename); 2392 } else { 2393 fprintf(stderr, "%s validation generated an internal error\n", 2394 sctxt->filename); 2395 } 2396 xmlRelaxNGFreeValidCtxt(vctxt); 2397 if (relaxngschemas != NULL) 2398 xmlRelaxNGFree(relaxngschemas); 2399 return(0); 2400 } 2401 #endif 2402 2403 #ifdef LIBXML_OUTPUT_ENABLED 2404 /** 2405 * xmlShellCat: 2406 * @ctxt: the shell context 2407 * @arg: unused 2408 * @node: a node 2409 * @node2: unused 2410 * 2411 * Implements the XML shell function "cat" 2412 * dumps the serialization node content (XML or HTML). 2413 * 2414 * Returns 0 2415 */ 2416 int 2417 xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED, 2418 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) 2419 { 2420 if (!ctxt) 2421 return (0); 2422 if (node == NULL) { 2423 fprintf(ctxt->output, "NULL\n"); 2424 return (0); 2425 } 2426 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) { 2427 #ifdef LIBXML_HTML_ENABLED 2428 if (node->type == XML_HTML_DOCUMENT_NODE) 2429 htmlDocDump(ctxt->output, (htmlDocPtr) node); 2430 else 2431 htmlNodeDumpFile(ctxt->output, ctxt->doc, node); 2432 #else 2433 if (node->type == XML_DOCUMENT_NODE) 2434 xmlDocDump(ctxt->output, (xmlDocPtr) node); 2435 else 2436 xmlElemDump(ctxt->output, ctxt->doc, node); 2437 #endif /* LIBXML_HTML_ENABLED */ 2438 } else { 2439 if (node->type == XML_DOCUMENT_NODE) 2440 xmlDocDump(ctxt->output, (xmlDocPtr) node); 2441 else 2442 xmlElemDump(ctxt->output, ctxt->doc, node); 2443 } 2444 fprintf(ctxt->output, "\n"); 2445 return (0); 2446 } 2447 #endif /* LIBXML_OUTPUT_ENABLED */ 2448 2449 /** 2450 * xmlShellLoad: 2451 * @ctxt: the shell context 2452 * @filename: the file name 2453 * @node: unused 2454 * @node2: unused 2455 * 2456 * Implements the XML shell function "load" 2457 * loads a new document specified by the filename 2458 * 2459 * Returns 0 or -1 if loading failed 2460 */ 2461 int 2462 xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, 2463 xmlNodePtr node ATTRIBUTE_UNUSED, 2464 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2465 { 2466 xmlDocPtr doc; 2467 int html = 0; 2468 2469 if ((ctxt == NULL) || (filename == NULL)) return(-1); 2470 if (ctxt->doc != NULL) 2471 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE); 2472 2473 if (html) { 2474 #ifdef LIBXML_HTML_ENABLED 2475 doc = htmlParseFile(filename, NULL); 2476 #else 2477 fprintf(ctxt->output, "HTML support not compiled in\n"); 2478 doc = NULL; 2479 #endif /* LIBXML_HTML_ENABLED */ 2480 } else { 2481 doc = xmlReadFile(filename,NULL,0); 2482 } 2483 if (doc != NULL) { 2484 if (ctxt->loaded == 1) { 2485 xmlFreeDoc(ctxt->doc); 2486 } 2487 ctxt->loaded = 1; 2488 #ifdef LIBXML_XPATH_ENABLED 2489 xmlXPathFreeContext(ctxt->pctxt); 2490 #endif /* LIBXML_XPATH_ENABLED */ 2491 xmlFree(ctxt->filename); 2492 ctxt->doc = doc; 2493 ctxt->node = (xmlNodePtr) doc; 2494 #ifdef LIBXML_XPATH_ENABLED 2495 ctxt->pctxt = xmlXPathNewContext(doc); 2496 #endif /* LIBXML_XPATH_ENABLED */ 2497 ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename); 2498 } else 2499 return (-1); 2500 return (0); 2501 } 2502 2503 #ifdef LIBXML_OUTPUT_ENABLED 2504 /** 2505 * xmlShellWrite: 2506 * @ctxt: the shell context 2507 * @filename: the file name 2508 * @node: a node in the tree 2509 * @node2: unused 2510 * 2511 * Implements the XML shell function "write" 2512 * Write the current node to the filename, it saves the serialization 2513 * of the subtree under the @node specified 2514 * 2515 * Returns 0 or -1 in case of error 2516 */ 2517 int 2518 xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node, 2519 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2520 { 2521 if (node == NULL) 2522 return (-1); 2523 if ((filename == NULL) || (filename[0] == 0)) { 2524 return (-1); 2525 } 2526 #ifdef W_OK 2527 if (access((char *) filename, W_OK)) { 2528 xmlGenericError(xmlGenericErrorContext, 2529 "Cannot write to %s\n", filename); 2530 return (-1); 2531 } 2532 #endif 2533 switch (node->type) { 2534 case XML_DOCUMENT_NODE: 2535 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) { 2536 xmlGenericError(xmlGenericErrorContext, 2537 "Failed to write to %s\n", filename); 2538 return (-1); 2539 } 2540 break; 2541 case XML_HTML_DOCUMENT_NODE: 2542 #ifdef LIBXML_HTML_ENABLED 2543 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) { 2544 xmlGenericError(xmlGenericErrorContext, 2545 "Failed to write to %s\n", filename); 2546 return (-1); 2547 } 2548 #else 2549 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) { 2550 xmlGenericError(xmlGenericErrorContext, 2551 "Failed to write to %s\n", filename); 2552 return (-1); 2553 } 2554 #endif /* LIBXML_HTML_ENABLED */ 2555 break; 2556 default:{ 2557 FILE *f; 2558 2559 f = fopen((char *) filename, "w"); 2560 if (f == NULL) { 2561 xmlGenericError(xmlGenericErrorContext, 2562 "Failed to write to %s\n", filename); 2563 return (-1); 2564 } 2565 xmlElemDump(f, ctxt->doc, node); 2566 fclose(f); 2567 } 2568 } 2569 return (0); 2570 } 2571 2572 /** 2573 * xmlShellSave: 2574 * @ctxt: the shell context 2575 * @filename: the file name (optional) 2576 * @node: unused 2577 * @node2: unused 2578 * 2579 * Implements the XML shell function "save" 2580 * Write the current document to the filename, or it's original name 2581 * 2582 * Returns 0 or -1 in case of error 2583 */ 2584 int 2585 xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, 2586 xmlNodePtr node ATTRIBUTE_UNUSED, 2587 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2588 { 2589 if ((ctxt == NULL) || (ctxt->doc == NULL)) 2590 return (-1); 2591 if ((filename == NULL) || (filename[0] == 0)) 2592 filename = ctxt->filename; 2593 if (filename == NULL) 2594 return (-1); 2595 #ifdef W_OK 2596 if (access((char *) filename, W_OK)) { 2597 xmlGenericError(xmlGenericErrorContext, 2598 "Cannot save to %s\n", filename); 2599 return (-1); 2600 } 2601 #endif 2602 switch (ctxt->doc->type) { 2603 case XML_DOCUMENT_NODE: 2604 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) { 2605 xmlGenericError(xmlGenericErrorContext, 2606 "Failed to save to %s\n", filename); 2607 } 2608 break; 2609 case XML_HTML_DOCUMENT_NODE: 2610 #ifdef LIBXML_HTML_ENABLED 2611 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) { 2612 xmlGenericError(xmlGenericErrorContext, 2613 "Failed to save to %s\n", filename); 2614 } 2615 #else 2616 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) { 2617 xmlGenericError(xmlGenericErrorContext, 2618 "Failed to save to %s\n", filename); 2619 } 2620 #endif /* LIBXML_HTML_ENABLED */ 2621 break; 2622 default: 2623 xmlGenericError(xmlGenericErrorContext, 2624 "To save to subparts of a document use the 'write' command\n"); 2625 return (-1); 2626 2627 } 2628 return (0); 2629 } 2630 #endif /* LIBXML_OUTPUT_ENABLED */ 2631 2632 #ifdef LIBXML_VALID_ENABLED 2633 /** 2634 * xmlShellValidate: 2635 * @ctxt: the shell context 2636 * @dtd: the DTD URI (optional) 2637 * @node: unused 2638 * @node2: unused 2639 * 2640 * Implements the XML shell function "validate" 2641 * Validate the document, if a DTD path is provided, then the validation 2642 * is done against the given DTD. 2643 * 2644 * Returns 0 or -1 in case of error 2645 */ 2646 int 2647 xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, 2648 xmlNodePtr node ATTRIBUTE_UNUSED, 2649 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2650 { 2651 xmlValidCtxt vctxt; 2652 int res = -1; 2653 2654 if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1); 2655 vctxt.userData = stderr; 2656 vctxt.error = (xmlValidityErrorFunc) fprintf; 2657 vctxt.warning = (xmlValidityWarningFunc) fprintf; 2658 2659 if ((dtd == NULL) || (dtd[0] == 0)) { 2660 res = xmlValidateDocument(&vctxt, ctxt->doc); 2661 } else { 2662 xmlDtdPtr subset; 2663 2664 subset = xmlParseDTD(NULL, (xmlChar *) dtd); 2665 if (subset != NULL) { 2666 res = xmlValidateDtd(&vctxt, ctxt->doc, subset); 2667 2668 xmlFreeDtd(subset); 2669 } 2670 } 2671 return (res); 2672 } 2673 #endif /* LIBXML_VALID_ENABLED */ 2674 2675 /** 2676 * xmlShellDu: 2677 * @ctxt: the shell context 2678 * @arg: unused 2679 * @tree: a node defining a subtree 2680 * @node2: unused 2681 * 2682 * Implements the XML shell function "du" 2683 * show the structure of the subtree under node @tree 2684 * If @tree is null, the command works on the current node. 2685 * 2686 * Returns 0 or -1 in case of error 2687 */ 2688 int 2689 xmlShellDu(xmlShellCtxtPtr ctxt, 2690 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree, 2691 xmlNodePtr node2 ATTRIBUTE_UNUSED) 2692 { 2693 xmlNodePtr node; 2694 int indent = 0, i; 2695 2696 if (!ctxt) 2697 return (-1); 2698 2699 if (tree == NULL) 2700 return (-1); 2701 node = tree; 2702 while (node != NULL) { 2703 if ((node->type == XML_DOCUMENT_NODE) || 2704 (node->type == XML_HTML_DOCUMENT_NODE)) { 2705 fprintf(ctxt->output, "/\n"); 2706 } else if (node->type == XML_ELEMENT_NODE) { 2707 for (i = 0; i < indent; i++) 2708 fprintf(ctxt->output, " "); 2709 if ((node->ns) && (node->ns->prefix)) 2710 fprintf(ctxt->output, "%s:", node->ns->prefix); 2711 fprintf(ctxt->output, "%s\n", node->name); 2712 } else { 2713 } 2714 2715 /* 2716 * Browse the full subtree, deep first 2717 */ 2718 2719 if ((node->type == XML_DOCUMENT_NODE) || 2720 (node->type == XML_HTML_DOCUMENT_NODE)) { 2721 node = ((xmlDocPtr) node)->children; 2722 } else if ((node->children != NULL) 2723 && (node->type != XML_ENTITY_REF_NODE)) { 2724 /* deep first */ 2725 node = node->children; 2726 indent++; 2727 } else if ((node != tree) && (node->next != NULL)) { 2728 /* then siblings */ 2729 node = node->next; 2730 } else if (node != tree) { 2731 /* go up to parents->next if needed */ 2732 while (node != tree) { 2733 if (node->parent != NULL) { 2734 node = node->parent; 2735 indent--; 2736 } 2737 if ((node != tree) && (node->next != NULL)) { 2738 node = node->next; 2739 break; 2740 } 2741 if (node->parent == NULL) { 2742 node = NULL; 2743 break; 2744 } 2745 if (node == tree) { 2746 node = NULL; 2747 break; 2748 } 2749 } 2750 /* exit condition */ 2751 if (node == tree) 2752 node = NULL; 2753 } else 2754 node = NULL; 2755 } 2756 return (0); 2757 } 2758 2759 /** 2760 * xmlShellPwd: 2761 * @ctxt: the shell context 2762 * @buffer: the output buffer 2763 * @node: a node 2764 * @node2: unused 2765 * 2766 * Implements the XML shell function "pwd" 2767 * Show the full path from the root to the node, if needed building 2768 * thumblers when similar elements exists at a given ancestor level. 2769 * The output is compatible with XPath commands. 2770 * 2771 * Returns 0 or -1 in case of error 2772 */ 2773 int 2774 xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer, 2775 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) 2776 { 2777 xmlChar *path; 2778 2779 if ((node == NULL) || (buffer == NULL)) 2780 return (-1); 2781 2782 path = xmlGetNodePath(node); 2783 if (path == NULL) 2784 return (-1); 2785 2786 /* 2787 * This test prevents buffer overflow, because this routine 2788 * is only called by xmlShell, in which the second argument is 2789 * 500 chars long. 2790 * It is a dirty hack before a cleaner solution is found. 2791 * Documentation should mention that the second argument must 2792 * be at least 500 chars long, and could be stripped if too long. 2793 */ 2794 snprintf(buffer, 499, "%s", path); 2795 buffer[499] = '0'; 2796 xmlFree(path); 2797 2798 return (0); 2799 } 2800 2801 /** 2802 * xmlShell: 2803 * @doc: the initial document 2804 * @filename: the output buffer 2805 * @input: the line reading function 2806 * @output: the output FILE*, defaults to stdout if NULL 2807 * 2808 * Implements the XML shell 2809 * This allow to load, validate, view, modify and save a document 2810 * using a environment similar to a UNIX commandline. 2811 */ 2812 void 2813 xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, 2814 FILE * output) 2815 { 2816 char prompt[500] = "/ > "; 2817 char *cmdline = NULL, *cur; 2818 char command[100]; 2819 char arg[400]; 2820 int i; 2821 xmlShellCtxtPtr ctxt; 2822 xmlXPathObjectPtr list; 2823 2824 if (doc == NULL) 2825 return; 2826 if (filename == NULL) 2827 return; 2828 if (input == NULL) 2829 return; 2830 if (output == NULL) 2831 output = stdout; 2832 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt)); 2833 if (ctxt == NULL) 2834 return; 2835 ctxt->loaded = 0; 2836 ctxt->doc = doc; 2837 ctxt->input = input; 2838 ctxt->output = output; 2839 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename); 2840 ctxt->node = (xmlNodePtr) ctxt->doc; 2841 2842 #ifdef LIBXML_XPATH_ENABLED 2843 ctxt->pctxt = xmlXPathNewContext(ctxt->doc); 2844 if (ctxt->pctxt == NULL) { 2845 xmlFree(ctxt); 2846 return; 2847 } 2848 #endif /* LIBXML_XPATH_ENABLED */ 2849 while (1) { 2850 if (ctxt->node == (xmlNodePtr) ctxt->doc) 2851 snprintf(prompt, sizeof(prompt), "%s > ", "/"); 2852 else if ((ctxt->node != NULL) && (ctxt->node->name) && 2853 (ctxt->node->ns) && (ctxt->node->ns->prefix)) 2854 snprintf(prompt, sizeof(prompt), "%s:%s > ", 2855 (ctxt->node->ns->prefix), ctxt->node->name); 2856 else if ((ctxt->node != NULL) && (ctxt->node->name)) 2857 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name); 2858 else 2859 snprintf(prompt, sizeof(prompt), "? > "); 2860 prompt[sizeof(prompt) - 1] = 0; 2861 2862 /* 2863 * Get a new command line 2864 */ 2865 cmdline = ctxt->input(prompt); 2866 if (cmdline == NULL) 2867 break; 2868 2869 /* 2870 * Parse the command itself 2871 */ 2872 cur = cmdline; 2873 while ((*cur == ' ') || (*cur == '\t')) 2874 cur++; 2875 i = 0; 2876 while ((*cur != ' ') && (*cur != '\t') && 2877 (*cur != '\n') && (*cur != '\r')) { 2878 if (*cur == 0) 2879 break; 2880 command[i++] = *cur++; 2881 } 2882 command[i] = 0; 2883 if (i == 0) 2884 continue; 2885 2886 /* 2887 * Parse the argument 2888 */ 2889 while ((*cur == ' ') || (*cur == '\t')) 2890 cur++; 2891 i = 0; 2892 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) { 2893 if (*cur == 0) 2894 break; 2895 arg[i++] = *cur++; 2896 } 2897 arg[i] = 0; 2898 2899 /* 2900 * start interpreting the command 2901 */ 2902 if (!strcmp(command, "exit")) 2903 break; 2904 if (!strcmp(command, "quit")) 2905 break; 2906 if (!strcmp(command, "bye")) 2907 break; 2908 if (!strcmp(command, "help")) { 2909 fprintf(ctxt->output, "\tbase display XML base of the node\n"); 2910 fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n"); 2911 fprintf(ctxt->output, "\tbye leave shell\n"); 2912 fprintf(ctxt->output, "\tcat [node] display node or current node\n"); 2913 fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n"); 2914 fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n"); 2915 fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n"); 2916 fprintf(ctxt->output, "\texit leave shell\n"); 2917 fprintf(ctxt->output, "\thelp display this help\n"); 2918 fprintf(ctxt->output, "\tfree display memory usage\n"); 2919 fprintf(ctxt->output, "\tload [name] load a new document with name\n"); 2920 fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n"); 2921 fprintf(ctxt->output, "\tset xml_fragment replace the current node content with the fragment parsed in context\n"); 2922 #ifdef LIBXML_XPATH_ENABLED 2923 fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n"); 2924 fprintf(ctxt->output, "\tsetns nsreg register a namespace to a prefix in the XPath evaluation context\n"); 2925 fprintf(ctxt->output, "\t format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n"); 2926 fprintf(ctxt->output, "\tsetrootns register all namespace found on the root element\n"); 2927 fprintf(ctxt->output, "\t the default namespace if any uses 'defaultns' prefix\n"); 2928 #endif /* LIBXML_XPATH_ENABLED */ 2929 fprintf(ctxt->output, "\tpwd display current working directory\n"); 2930 fprintf(ctxt->output, "\twhereis display absolute path of [path] or current working directory\n"); 2931 fprintf(ctxt->output, "\tquit leave shell\n"); 2932 #ifdef LIBXML_OUTPUT_ENABLED 2933 fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n"); 2934 fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n"); 2935 #endif /* LIBXML_OUTPUT_ENABLED */ 2936 #ifdef LIBXML_VALID_ENABLED 2937 fprintf(ctxt->output, "\tvalidate check the document for errors\n"); 2938 #endif /* LIBXML_VALID_ENABLED */ 2939 #ifdef LIBXML_SCHEMAS_ENABLED 2940 fprintf(ctxt->output, "\trelaxng rng validate the document against the Relax-NG schemas\n"); 2941 #endif 2942 fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n"); 2943 #ifdef LIBXML_VALID_ENABLED 2944 } else if (!strcmp(command, "validate")) { 2945 xmlShellValidate(ctxt, arg, NULL, NULL); 2946 #endif /* LIBXML_VALID_ENABLED */ 2947 } else if (!strcmp(command, "load")) { 2948 xmlShellLoad(ctxt, arg, NULL, NULL); 2949 #ifdef LIBXML_SCHEMAS_ENABLED 2950 } else if (!strcmp(command, "relaxng")) { 2951 xmlShellRNGValidate(ctxt, arg, NULL, NULL); 2952 #endif 2953 #ifdef LIBXML_OUTPUT_ENABLED 2954 } else if (!strcmp(command, "save")) { 2955 xmlShellSave(ctxt, arg, NULL, NULL); 2956 } else if (!strcmp(command, "write")) { 2957 if (arg[0] == 0) 2958 xmlGenericError(xmlGenericErrorContext, 2959 "Write command requires a filename argument\n"); 2960 else 2961 xmlShellWrite(ctxt, arg, ctxt->node, NULL); 2962 #endif /* LIBXML_OUTPUT_ENABLED */ 2963 } else if (!strcmp(command, "grep")) { 2964 xmlShellGrep(ctxt, arg, ctxt->node, NULL); 2965 } else if (!strcmp(command, "free")) { 2966 if (arg[0] == 0) { 2967 xmlMemShow(ctxt->output, 0); 2968 } else { 2969 int len = 0; 2970 2971 sscanf(arg, "%d", &len); 2972 xmlMemShow(ctxt->output, len); 2973 } 2974 } else if (!strcmp(command, "pwd")) { 2975 char dir[500]; 2976 2977 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL)) 2978 fprintf(ctxt->output, "%s\n", dir); 2979 } else if (!strcmp(command, "du")) { 2980 if (arg[0] == 0) { 2981 xmlShellDu(ctxt, NULL, ctxt->node, NULL); 2982 } else { 2983 ctxt->pctxt->node = ctxt->node; 2984 #ifdef LIBXML_XPATH_ENABLED 2985 ctxt->pctxt->node = ctxt->node; 2986 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); 2987 #else 2988 list = NULL; 2989 #endif /* LIBXML_XPATH_ENABLED */ 2990 if (list != NULL) { 2991 switch (list->type) { 2992 case XPATH_UNDEFINED: 2993 xmlGenericError(xmlGenericErrorContext, 2994 "%s: no such node\n", arg); 2995 break; 2996 case XPATH_NODESET:{ 2997 int indx; 2998 2999 if (list->nodesetval == NULL) 3000 break; 3001 3002 for (indx = 0; 3003 indx < list->nodesetval->nodeNr; 3004 indx++) 3005 xmlShellDu(ctxt, NULL, 3006 list->nodesetval-> 3007 nodeTab[indx], NULL); 3008 break; 3009 } 3010 case XPATH_BOOLEAN: 3011 xmlGenericError(xmlGenericErrorContext, 3012 "%s is a Boolean\n", arg); 3013 break; 3014 case XPATH_NUMBER: 3015 xmlGenericError(xmlGenericErrorContext, 3016 "%s is a number\n", arg); 3017 break; 3018 case XPATH_STRING: 3019 xmlGenericError(xmlGenericErrorContext, 3020 "%s is a string\n", arg); 3021 break; 3022 case XPATH_POINT: 3023 xmlGenericError(xmlGenericErrorContext, 3024 "%s is a point\n", arg); 3025 break; 3026 case XPATH_RANGE: 3027 xmlGenericError(xmlGenericErrorContext, 3028 "%s is a range\n", arg); 3029 break; 3030 case XPATH_LOCATIONSET: 3031 xmlGenericError(xmlGenericErrorContext, 3032 "%s is a range\n", arg); 3033 break; 3034 case XPATH_USERS: 3035 xmlGenericError(xmlGenericErrorContext, 3036 "%s is user-defined\n", arg); 3037 break; 3038 case XPATH_XSLT_TREE: 3039 xmlGenericError(xmlGenericErrorContext, 3040 "%s is an XSLT value tree\n", 3041 arg); 3042 break; 3043 } 3044 #ifdef LIBXML_XPATH_ENABLED 3045 xmlXPathFreeObject(list); 3046 #endif 3047 } else { 3048 xmlGenericError(xmlGenericErrorContext, 3049 "%s: no such node\n", arg); 3050 } 3051 ctxt->pctxt->node = NULL; 3052 } 3053 } else if (!strcmp(command, "base")) { 3054 xmlShellBase(ctxt, NULL, ctxt->node, NULL); 3055 } else if (!strcmp(command, "set")) { 3056 xmlShellSetContent(ctxt, arg, ctxt->node, NULL); 3057 #ifdef LIBXML_XPATH_ENABLED 3058 } else if (!strcmp(command, "setns")) { 3059 if (arg[0] == 0) { 3060 xmlGenericError(xmlGenericErrorContext, 3061 "setns: prefix=[nsuri] required\n"); 3062 } else { 3063 xmlShellRegisterNamespace(ctxt, arg, NULL, NULL); 3064 } 3065 } else if (!strcmp(command, "setrootns")) { 3066 xmlNodePtr root; 3067 3068 root = xmlDocGetRootElement(ctxt->doc); 3069 xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL); 3070 } else if (!strcmp(command, "xpath")) { 3071 if (arg[0] == 0) { 3072 xmlGenericError(xmlGenericErrorContext, 3073 "xpath: expression required\n"); 3074 } else { 3075 ctxt->pctxt->node = ctxt->node; 3076 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); 3077 xmlXPathDebugDumpObject(ctxt->output, list, 0); 3078 xmlXPathFreeObject(list); 3079 } 3080 #endif /* LIBXML_XPATH_ENABLED */ 3081 #ifdef LIBXML_TREE_ENABLED 3082 } else if (!strcmp(command, "setbase")) { 3083 xmlShellSetBase(ctxt, arg, ctxt->node, NULL); 3084 #endif 3085 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) { 3086 int dir = (!strcmp(command, "dir")); 3087 3088 if (arg[0] == 0) { 3089 if (dir) 3090 xmlShellDir(ctxt, NULL, ctxt->node, NULL); 3091 else 3092 xmlShellList(ctxt, NULL, ctxt->node, NULL); 3093 } else { 3094 ctxt->pctxt->node = ctxt->node; 3095 #ifdef LIBXML_XPATH_ENABLED 3096 ctxt->pctxt->node = ctxt->node; 3097 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); 3098 #else 3099 list = NULL; 3100 #endif /* LIBXML_XPATH_ENABLED */ 3101 if (list != NULL) { 3102 switch (list->type) { 3103 case XPATH_UNDEFINED: 3104 xmlGenericError(xmlGenericErrorContext, 3105 "%s: no such node\n", arg); 3106 break; 3107 case XPATH_NODESET:{ 3108 int indx; 3109 3110 if (list->nodesetval == NULL) 3111 break; 3112 3113 for (indx = 0; 3114 indx < list->nodesetval->nodeNr; 3115 indx++) { 3116 if (dir) 3117 xmlShellDir(ctxt, NULL, 3118 list->nodesetval-> 3119 nodeTab[indx], NULL); 3120 else 3121 xmlShellList(ctxt, NULL, 3122 list->nodesetval-> 3123 nodeTab[indx], NULL); 3124 } 3125 break; 3126 } 3127 case XPATH_BOOLEAN: 3128 xmlGenericError(xmlGenericErrorContext, 3129 "%s is a Boolean\n", arg); 3130 break; 3131 case XPATH_NUMBER: 3132 xmlGenericError(xmlGenericErrorContext, 3133 "%s is a number\n", arg); 3134 break; 3135 case XPATH_STRING: 3136 xmlGenericError(xmlGenericErrorContext, 3137 "%s is a string\n", arg); 3138 break; 3139 case XPATH_POINT: 3140 xmlGenericError(xmlGenericErrorContext, 3141 "%s is a point\n", arg); 3142 break; 3143 case XPATH_RANGE: 3144 xmlGenericError(xmlGenericErrorContext, 3145 "%s is a range\n", arg); 3146 break; 3147 case XPATH_LOCATIONSET: 3148 xmlGenericError(xmlGenericErrorContext, 3149 "%s is a range\n", arg); 3150 break; 3151 case XPATH_USERS: 3152 xmlGenericError(xmlGenericErrorContext, 3153 "%s is user-defined\n", arg); 3154 break; 3155 case XPATH_XSLT_TREE: 3156 xmlGenericError(xmlGenericErrorContext, 3157 "%s is an XSLT value tree\n", 3158 arg); 3159 break; 3160 } 3161 #ifdef LIBXML_XPATH_ENABLED 3162 xmlXPathFreeObject(list); 3163 #endif 3164 } else { 3165 xmlGenericError(xmlGenericErrorContext, 3166 "%s: no such node\n", arg); 3167 } 3168 ctxt->pctxt->node = NULL; 3169 } 3170 } else if (!strcmp(command, "whereis")) { 3171 char dir[500]; 3172 3173 if (arg[0] == 0) { 3174 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL)) 3175 fprintf(ctxt->output, "%s\n", dir); 3176 } else { 3177 ctxt->pctxt->node = ctxt->node; 3178 #ifdef LIBXML_XPATH_ENABLED 3179 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); 3180 #else 3181 list = NULL; 3182 #endif /* LIBXML_XPATH_ENABLED */ 3183 if (list != NULL) { 3184 switch (list->type) { 3185 case XPATH_UNDEFINED: 3186 xmlGenericError(xmlGenericErrorContext, 3187 "%s: no such node\n", arg); 3188 break; 3189 case XPATH_NODESET:{ 3190 int indx; 3191 3192 if (list->nodesetval == NULL) 3193 break; 3194 3195 for (indx = 0; 3196 indx < list->nodesetval->nodeNr; 3197 indx++) { 3198 if (!xmlShellPwd(ctxt, dir, list->nodesetval-> 3199 nodeTab[indx], NULL)) 3200 fprintf(ctxt->output, "%s\n", dir); 3201 } 3202 break; 3203 } 3204 case XPATH_BOOLEAN: 3205 xmlGenericError(xmlGenericErrorContext, 3206 "%s is a Boolean\n", arg); 3207 break; 3208 case XPATH_NUMBER: 3209 xmlGenericError(xmlGenericErrorContext, 3210 "%s is a number\n", arg); 3211 break; 3212 case XPATH_STRING: 3213 xmlGenericError(xmlGenericErrorContext, 3214 "%s is a string\n", arg); 3215 break; 3216 case XPATH_POINT: 3217 xmlGenericError(xmlGenericErrorContext, 3218 "%s is a point\n", arg); 3219 break; 3220 case XPATH_RANGE: 3221 xmlGenericError(xmlGenericErrorContext, 3222 "%s is a range\n", arg); 3223 break; 3224 case XPATH_LOCATIONSET: 3225 xmlGenericError(xmlGenericErrorContext, 3226 "%s is a range\n", arg); 3227 break; 3228 case XPATH_USERS: 3229 xmlGenericError(xmlGenericErrorContext, 3230 "%s is user-defined\n", arg); 3231 break; 3232 case XPATH_XSLT_TREE: 3233 xmlGenericError(xmlGenericErrorContext, 3234 "%s is an XSLT value tree\n", 3235 arg); 3236 break; 3237 } 3238 #ifdef LIBXML_XPATH_ENABLED 3239 xmlXPathFreeObject(list); 3240 #endif 3241 } else { 3242 xmlGenericError(xmlGenericErrorContext, 3243 "%s: no such node\n", arg); 3244 } 3245 ctxt->pctxt->node = NULL; 3246 } 3247 } else if (!strcmp(command, "cd")) { 3248 if (arg[0] == 0) { 3249 ctxt->node = (xmlNodePtr) ctxt->doc; 3250 } else { 3251 #ifdef LIBXML_XPATH_ENABLED 3252 int l; 3253 3254 ctxt->pctxt->node = ctxt->node; 3255 l = strlen(arg); 3256 if ((l >= 2) && (arg[l - 1] == '/')) 3257 arg[l - 1] = 0; 3258 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); 3259 #else 3260 list = NULL; 3261 #endif /* LIBXML_XPATH_ENABLED */ 3262 if (list != NULL) { 3263 switch (list->type) { 3264 case XPATH_UNDEFINED: 3265 xmlGenericError(xmlGenericErrorContext, 3266 "%s: no such node\n", arg); 3267 break; 3268 case XPATH_NODESET: 3269 if (list->nodesetval != NULL) { 3270 if (list->nodesetval->nodeNr == 1) { 3271 ctxt->node = list->nodesetval->nodeTab[0]; 3272 if ((ctxt->node != NULL) && 3273 (ctxt->node->type == 3274 XML_NAMESPACE_DECL)) { 3275 xmlGenericError(xmlGenericErrorContext, 3276 "cannot cd to namespace\n"); 3277 ctxt->node = NULL; 3278 } 3279 } else 3280 xmlGenericError(xmlGenericErrorContext, 3281 "%s is a %d Node Set\n", 3282 arg, 3283 list->nodesetval->nodeNr); 3284 } else 3285 xmlGenericError(xmlGenericErrorContext, 3286 "%s is an empty Node Set\n", 3287 arg); 3288 break; 3289 case XPATH_BOOLEAN: 3290 xmlGenericError(xmlGenericErrorContext, 3291 "%s is a Boolean\n", arg); 3292 break; 3293 case XPATH_NUMBER: 3294 xmlGenericError(xmlGenericErrorContext, 3295 "%s is a number\n", arg); 3296 break; 3297 case XPATH_STRING: 3298 xmlGenericError(xmlGenericErrorContext, 3299 "%s is a string\n", arg); 3300 break; 3301 case XPATH_POINT: 3302 xmlGenericError(xmlGenericErrorContext, 3303 "%s is a point\n", arg); 3304 break; 3305 case XPATH_RANGE: 3306 xmlGenericError(xmlGenericErrorContext, 3307 "%s is a range\n", arg); 3308 break; 3309 case XPATH_LOCATIONSET: 3310 xmlGenericError(xmlGenericErrorContext, 3311 "%s is a range\n", arg); 3312 break; 3313 case XPATH_USERS: 3314 xmlGenericError(xmlGenericErrorContext, 3315 "%s is user-defined\n", arg); 3316 break; 3317 case XPATH_XSLT_TREE: 3318 xmlGenericError(xmlGenericErrorContext, 3319 "%s is an XSLT value tree\n", 3320 arg); 3321 break; 3322 } 3323 #ifdef LIBXML_XPATH_ENABLED 3324 xmlXPathFreeObject(list); 3325 #endif 3326 } else { 3327 xmlGenericError(xmlGenericErrorContext, 3328 "%s: no such node\n", arg); 3329 } 3330 ctxt->pctxt->node = NULL; 3331 } 3332 #ifdef LIBXML_OUTPUT_ENABLED 3333 } else if (!strcmp(command, "cat")) { 3334 if (arg[0] == 0) { 3335 xmlShellCat(ctxt, NULL, ctxt->node, NULL); 3336 } else { 3337 ctxt->pctxt->node = ctxt->node; 3338 #ifdef LIBXML_XPATH_ENABLED 3339 ctxt->pctxt->node = ctxt->node; 3340 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); 3341 #else 3342 list = NULL; 3343 #endif /* LIBXML_XPATH_ENABLED */ 3344 if (list != NULL) { 3345 switch (list->type) { 3346 case XPATH_UNDEFINED: 3347 xmlGenericError(xmlGenericErrorContext, 3348 "%s: no such node\n", arg); 3349 break; 3350 case XPATH_NODESET:{ 3351 int indx; 3352 3353 if (list->nodesetval == NULL) 3354 break; 3355 3356 for (indx = 0; 3357 indx < list->nodesetval->nodeNr; 3358 indx++) { 3359 if (i > 0) 3360 fprintf(ctxt->output, " -------\n"); 3361 xmlShellCat(ctxt, NULL, 3362 list->nodesetval-> 3363 nodeTab[indx], NULL); 3364 } 3365 break; 3366 } 3367 case XPATH_BOOLEAN: 3368 xmlGenericError(xmlGenericErrorContext, 3369 "%s is a Boolean\n", arg); 3370 break; 3371 case XPATH_NUMBER: 3372 xmlGenericError(xmlGenericErrorContext, 3373 "%s is a number\n", arg); 3374 break; 3375 case XPATH_STRING: 3376 xmlGenericError(xmlGenericErrorContext, 3377 "%s is a string\n", arg); 3378 break; 3379 case XPATH_POINT: 3380 xmlGenericError(xmlGenericErrorContext, 3381 "%s is a point\n", arg); 3382 break; 3383 case XPATH_RANGE: 3384 xmlGenericError(xmlGenericErrorContext, 3385 "%s is a range\n", arg); 3386 break; 3387 case XPATH_LOCATIONSET: 3388 xmlGenericError(xmlGenericErrorContext, 3389 "%s is a range\n", arg); 3390 break; 3391 case XPATH_USERS: 3392 xmlGenericError(xmlGenericErrorContext, 3393 "%s is user-defined\n", arg); 3394 break; 3395 case XPATH_XSLT_TREE: 3396 xmlGenericError(xmlGenericErrorContext, 3397 "%s is an XSLT value tree\n", 3398 arg); 3399 break; 3400 } 3401 #ifdef LIBXML_XPATH_ENABLED 3402 xmlXPathFreeObject(list); 3403 #endif 3404 } else { 3405 xmlGenericError(xmlGenericErrorContext, 3406 "%s: no such node\n", arg); 3407 } 3408 ctxt->pctxt->node = NULL; 3409 } 3410 #endif /* LIBXML_OUTPUT_ENABLED */ 3411 } else { 3412 xmlGenericError(xmlGenericErrorContext, 3413 "Unknown command %s\n", command); 3414 } 3415 free(cmdline); /* not xmlFree here ! */ 3416 cmdline = NULL; 3417 } 3418 #ifdef LIBXML_XPATH_ENABLED 3419 xmlXPathFreeContext(ctxt->pctxt); 3420 #endif /* LIBXML_XPATH_ENABLED */ 3421 if (ctxt->loaded) { 3422 xmlFreeDoc(ctxt->doc); 3423 } 3424 if (ctxt->filename != NULL) 3425 xmlFree(ctxt->filename); 3426 xmlFree(ctxt); 3427 if (cmdline != NULL) 3428 free(cmdline); /* not xmlFree here ! */ 3429 } 3430 3431 #endif /* LIBXML_XPATH_ENABLED */ 3432 #define bottom_debugXML 3433 #include "elfgcchack.h" 3434 #endif /* LIBXML_DEBUG_ENABLED */