debugXML.c revision 7db3871bf58553461563241db0fffe71bf611c5e
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#include "libxml.h" 11#ifdef LIBXML_DEBUG_ENABLED 12 13#include <string.h> 14#ifdef HAVE_STDLIB_H 15#include <stdlib.h> 16#endif 17#ifdef HAVE_STRING_H 18#include <string.h> 19#endif 20#include <libxml/xmlmemory.h> 21#include <libxml/tree.h> 22#include <libxml/parser.h> 23#include <libxml/parserInternals.h> 24#include <libxml/valid.h> 25#include <libxml/debugXML.h> 26#include <libxml/HTMLtree.h> 27#include <libxml/HTMLparser.h> 28#include <libxml/xmlerror.h> 29#include <libxml/globals.h> 30 31/** 32 * xmlDebugDumpString: 33 * @output: the FILE * for the output 34 * @str: the string 35 * 36 * Dumps informations about the string, shorten it if necessary 37 */ 38void 39xmlDebugDumpString(FILE * output, const xmlChar * str) 40{ 41 int i; 42 43 if (output == NULL) 44 output = stdout; 45 if (str == NULL) { 46 fprintf(output, "(NULL)"); 47 return; 48 } 49 for (i = 0; i < 40; i++) 50 if (str[i] == 0) 51 return; 52 else if (IS_BLANK(str[i])) 53 fputc(' ', output); 54 else if (str[i] >= 0x80) 55 fprintf(output, "#%X", str[i]); 56 else 57 fputc(str[i], output); 58 fprintf(output, "..."); 59} 60 61static void 62xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) { 63 int i; 64 char shift[100]; 65 66 for (i = 0;((i < depth) && (i < 25));i++) 67 shift[2 * i] = shift[2 * i + 1] = ' '; 68 shift[2 * i] = shift[2 * i + 1] = 0; 69 70 fprintf(output, shift); 71 72 if (dtd == NULL) { 73 fprintf(output, "DTD node is NULL\n"); 74 return; 75 } 76 77 if (dtd->type != XML_DTD_NODE) { 78 fprintf(output, "PBM: not a DTD\n"); 79 return; 80 } 81 if (dtd->name != NULL) 82 fprintf(output, "DTD(%s)", dtd->name); 83 else 84 fprintf(output, "DTD"); 85 if (dtd->ExternalID != NULL) 86 fprintf(output, ", PUBLIC %s", dtd->ExternalID); 87 if (dtd->SystemID != NULL) 88 fprintf(output, ", SYSTEM %s", dtd->SystemID); 89 fprintf(output, "\n"); 90 /* 91 * Do a bit of checking 92 */ 93 if (dtd->parent == NULL) 94 fprintf(output, "PBM: DTD has no parent\n"); 95 if (dtd->doc == NULL) 96 fprintf(output, "PBM: DTD has no doc\n"); 97 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc)) 98 fprintf(output, "PBM: DTD doc differs from parent's one\n"); 99 if (dtd->prev == NULL) { 100 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd)) 101 fprintf(output, "PBM: DTD has no prev and not first of list\n"); 102 } else { 103 if (dtd->prev->next != (xmlNodePtr) dtd) 104 fprintf(output, "PBM: DTD prev->next : back link wrong\n"); 105 } 106 if (dtd->next == NULL) { 107 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd)) 108 fprintf(output, "PBM: DTD has no next and not last of list\n"); 109 } else { 110 if (dtd->next->prev != (xmlNodePtr) dtd) 111 fprintf(output, "PBM: DTD next->prev : forward link wrong\n"); 112 } 113} 114 115static void 116xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) { 117 int i; 118 char shift[100]; 119 120 for (i = 0;((i < depth) && (i < 25));i++) 121 shift[2 * i] = shift[2 * i + 1] = ' '; 122 shift[2 * i] = shift[2 * i + 1] = 0; 123 124 fprintf(output, shift); 125 126 if (attr == NULL) { 127 fprintf(output, "Attribute declaration is NULL\n"); 128 return; 129 } 130 if (attr->type != XML_ATTRIBUTE_DECL) { 131 fprintf(output, "PBM: not a Attr\n"); 132 return; 133 } 134 if (attr->name != NULL) 135 fprintf(output, "ATTRDECL(%s)", attr->name); 136 else 137 fprintf(output, "PBM ATTRDECL noname!!!"); 138 if (attr->elem != NULL) 139 fprintf(output, " for %s", attr->elem); 140 else 141 fprintf(output, " PBM noelem!!!"); 142 switch (attr->atype) { 143 case XML_ATTRIBUTE_CDATA: 144 fprintf(output, " CDATA"); 145 break; 146 case XML_ATTRIBUTE_ID: 147 fprintf(output, " ID"); 148 break; 149 case XML_ATTRIBUTE_IDREF: 150 fprintf(output, " IDREF"); 151 break; 152 case XML_ATTRIBUTE_IDREFS: 153 fprintf(output, " IDREFS"); 154 break; 155 case XML_ATTRIBUTE_ENTITY: 156 fprintf(output, " ENTITY"); 157 break; 158 case XML_ATTRIBUTE_ENTITIES: 159 fprintf(output, " ENTITIES"); 160 break; 161 case XML_ATTRIBUTE_NMTOKEN: 162 fprintf(output, " NMTOKEN"); 163 break; 164 case XML_ATTRIBUTE_NMTOKENS: 165 fprintf(output, " NMTOKENS"); 166 break; 167 case XML_ATTRIBUTE_ENUMERATION: 168 fprintf(output, " ENUMERATION"); 169 break; 170 case XML_ATTRIBUTE_NOTATION: 171 fprintf(output, " NOTATION "); 172 break; 173 } 174 if (attr->tree != NULL) { 175 int indx; 176 xmlEnumerationPtr cur = attr->tree; 177 178 for (indx = 0;indx < 5; indx++) { 179 if (indx != 0) 180 fprintf(output, "|%s", cur->name); 181 else 182 fprintf(output, " (%s", cur->name); 183 cur = cur->next; 184 if (cur == NULL) break; 185 } 186 if (cur == NULL) 187 fprintf(output, ")"); 188 else 189 fprintf(output, "...)"); 190 } 191 switch (attr->def) { 192 case XML_ATTRIBUTE_NONE: 193 break; 194 case XML_ATTRIBUTE_REQUIRED: 195 fprintf(output, " REQUIRED"); 196 break; 197 case XML_ATTRIBUTE_IMPLIED: 198 fprintf(output, " IMPLIED"); 199 break; 200 case XML_ATTRIBUTE_FIXED: 201 fprintf(output, " FIXED"); 202 break; 203 } 204 if (attr->defaultValue != NULL) { 205 fprintf(output, "\""); 206 xmlDebugDumpString(output, attr->defaultValue); 207 fprintf(output, "\""); 208 } 209 fprintf(output, "\n"); 210 211 /* 212 * Do a bit of checking 213 */ 214 if (attr->parent == NULL) 215 fprintf(output, "PBM: Attr has no parent\n"); 216 if (attr->doc == NULL) 217 fprintf(output, "PBM: Attr has no doc\n"); 218 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc)) 219 fprintf(output, "PBM: Attr doc differs from parent's one\n"); 220 if (attr->prev == NULL) { 221 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr)) 222 fprintf(output, "PBM: Attr has no prev and not first of list\n"); 223 } else { 224 if (attr->prev->next != (xmlNodePtr) attr) 225 fprintf(output, "PBM: Attr prev->next : back link wrong\n"); 226 } 227 if (attr->next == NULL) { 228 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr)) 229 fprintf(output, "PBM: Attr has no next and not last of list\n"); 230 } else { 231 if (attr->next->prev != (xmlNodePtr) attr) 232 fprintf(output, "PBM: Attr next->prev : forward link wrong\n"); 233 } 234} 235 236static void 237xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) { 238 int i; 239 char shift[100]; 240 241 for (i = 0;((i < depth) && (i < 25));i++) 242 shift[2 * i] = shift[2 * i + 1] = ' '; 243 shift[2 * i] = shift[2 * i + 1] = 0; 244 245 fprintf(output, shift); 246 247 if (elem == NULL) { 248 fprintf(output, "Element declaration is NULL\n"); 249 return; 250 } 251 if (elem->type != XML_ELEMENT_DECL) { 252 fprintf(output, "PBM: not a Elem\n"); 253 return; 254 } 255 if (elem->name != NULL) { 256 fprintf(output, "ELEMDECL("); 257 xmlDebugDumpString(output, elem->name); 258 fprintf(output, ")"); 259 } else 260 fprintf(output, "PBM ELEMDECL noname!!!"); 261 switch (elem->etype) { 262 case XML_ELEMENT_TYPE_UNDEFINED: 263 fprintf(output, ", UNDEFINED"); 264 break; 265 case XML_ELEMENT_TYPE_EMPTY: 266 fprintf(output, ", EMPTY"); 267 break; 268 case XML_ELEMENT_TYPE_ANY: 269 fprintf(output, ", ANY"); 270 break; 271 case XML_ELEMENT_TYPE_MIXED: 272 fprintf(output, ", MIXED "); 273 break; 274 case XML_ELEMENT_TYPE_ELEMENT: 275 fprintf(output, ", MIXED "); 276 break; 277 } 278 if ((elem->type != XML_ELEMENT_NODE) && 279 (elem->content != NULL)) { 280 char buf[5001]; 281 282 buf[0] = 0; 283 xmlSnprintfElementContent(buf, 5000, elem->content, 1); 284 buf[5000] = 0; 285 fprintf(output, "%s", buf); 286 } 287 fprintf(output, "\n"); 288 289 /* 290 * Do a bit of checking 291 */ 292 if (elem->parent == NULL) 293 fprintf(output, "PBM: Elem has no parent\n"); 294 if (elem->doc == NULL) 295 fprintf(output, "PBM: Elem has no doc\n"); 296 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc)) 297 fprintf(output, "PBM: Elem doc differs from parent's one\n"); 298 if (elem->prev == NULL) { 299 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem)) 300 fprintf(output, "PBM: Elem has no prev and not first of list\n"); 301 } else { 302 if (elem->prev->next != (xmlNodePtr) elem) 303 fprintf(output, "PBM: Elem prev->next : back link wrong\n"); 304 } 305 if (elem->next == NULL) { 306 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem)) 307 fprintf(output, "PBM: Elem has no next and not last of list\n"); 308 } else { 309 if (elem->next->prev != (xmlNodePtr) elem) 310 fprintf(output, "PBM: Elem next->prev : forward link wrong\n"); 311 } 312} 313 314static void 315xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) { 316 int i; 317 char shift[100]; 318 319 for (i = 0;((i < depth) && (i < 25));i++) 320 shift[2 * i] = shift[2 * i + 1] = ' '; 321 shift[2 * i] = shift[2 * i + 1] = 0; 322 323 fprintf(output, shift); 324 325 if (ent == NULL) { 326 fprintf(output, "Entity declaration is NULL\n"); 327 return; 328 } 329 if (ent->type != XML_ENTITY_DECL) { 330 fprintf(output, "PBM: not a Entity decl\n"); 331 return; 332 } 333 if (ent->name != NULL) { 334 fprintf(output, "ENTITYDECL("); 335 xmlDebugDumpString(output, ent->name); 336 fprintf(output, ")"); 337 } else 338 fprintf(output, "PBM ENTITYDECL noname!!!"); 339 switch (ent->etype) { 340 case XML_INTERNAL_GENERAL_ENTITY: 341 fprintf(output, ", internal\n"); 342 break; 343 case XML_EXTERNAL_GENERAL_PARSED_ENTITY: 344 fprintf(output, ", external parsed\n"); 345 break; 346 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: 347 fprintf(output, ", unparsed\n"); 348 break; 349 case XML_INTERNAL_PARAMETER_ENTITY: 350 fprintf(output, ", parameter\n"); 351 break; 352 case XML_EXTERNAL_PARAMETER_ENTITY: 353 fprintf(output, ", external parameter\n"); 354 break; 355 case XML_INTERNAL_PREDEFINED_ENTITY: 356 fprintf(output, ", predefined\n"); 357 break; 358 } 359 if (ent->ExternalID) { 360 fprintf(output, shift); 361 fprintf(output, " ExternalID=%s\n", ent->ExternalID); 362 } 363 if (ent->SystemID) { 364 fprintf(output, shift); 365 fprintf(output, " SystemID=%s\n", ent->SystemID); 366 } 367 if (ent->URI != NULL) { 368 fprintf(output, shift); 369 fprintf(output, " URI=%s\n", ent->URI); 370 } 371 if (ent->content) { 372 fprintf(output, shift); 373 fprintf(output, " content="); 374 xmlDebugDumpString(output, ent->content); 375 fprintf(output, "\n"); 376 } 377 378 /* 379 * Do a bit of checking 380 */ 381 if (ent->parent == NULL) 382 fprintf(output, "PBM: Ent has no parent\n"); 383 if (ent->doc == NULL) 384 fprintf(output, "PBM: Ent has no doc\n"); 385 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc)) 386 fprintf(output, "PBM: Ent doc differs from parent's one\n"); 387 if (ent->prev == NULL) { 388 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent)) 389 fprintf(output, "PBM: Ent has no prev and not first of list\n"); 390 } else { 391 if (ent->prev->next != (xmlNodePtr) ent) 392 fprintf(output, "PBM: Ent prev->next : back link wrong\n"); 393 } 394 if (ent->next == NULL) { 395 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent)) 396 fprintf(output, "PBM: Ent has no next and not last of list\n"); 397 } else { 398 if (ent->next->prev != (xmlNodePtr) ent) 399 fprintf(output, "PBM: Ent next->prev : forward link wrong\n"); 400 } 401} 402 403static void 404xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) { 405 int i; 406 char shift[100]; 407 408 for (i = 0;((i < depth) && (i < 25));i++) 409 shift[2 * i] = shift[2 * i + 1] = ' '; 410 shift[2 * i] = shift[2 * i + 1] = 0; 411 412 fprintf(output, shift); 413 414 if (ns == NULL) { 415 fprintf(output, "namespace node is NULL\n"); 416 return; 417 } 418 if (ns->type != XML_NAMESPACE_DECL) { 419 fprintf(output, "invalid namespace node %d\n", ns->type); 420 return; 421 } 422 if (ns->href == NULL) { 423 if (ns->prefix != NULL) 424 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix); 425 else 426 fprintf(output, "incomplete default namespace href=NULL\n"); 427 } else { 428 if (ns->prefix != NULL) 429 fprintf(output, "namespace %s href=", ns->prefix); 430 else 431 fprintf(output, "default namespace href="); 432 433 xmlDebugDumpString(output, ns->href); 434 fprintf(output, "\n"); 435 } 436} 437 438static void 439xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) { 440 while (ns != NULL) { 441 xmlDebugDumpNamespace(output, ns, depth); 442 ns = ns->next; 443 } 444} 445 446static void 447xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) { 448 int i; 449 char shift[100]; 450 451 for (i = 0;((i < depth) && (i < 25));i++) 452 shift[2 * i] = shift[2 * i + 1] = ' '; 453 shift[2 * i] = shift[2 * i + 1] = 0; 454 455 fprintf(output, shift); 456 457 if (ent == NULL) { 458 fprintf(output, "Entity is NULL\n"); 459 return; 460 } 461 switch (ent->etype) { 462 case XML_INTERNAL_GENERAL_ENTITY: 463 fprintf(output, "INTERNAL_GENERAL_ENTITY "); 464 break; 465 case XML_EXTERNAL_GENERAL_PARSED_ENTITY: 466 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY "); 467 break; 468 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: 469 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY "); 470 break; 471 case XML_INTERNAL_PARAMETER_ENTITY: 472 fprintf(output, "INTERNAL_PARAMETER_ENTITY "); 473 break; 474 case XML_EXTERNAL_PARAMETER_ENTITY: 475 fprintf(output, "EXTERNAL_PARAMETER_ENTITY "); 476 break; 477 default: 478 fprintf(output, "ENTITY_%d ! ", ent->etype); 479 } 480 fprintf(output, "%s\n", ent->name); 481 if (ent->ExternalID) { 482 fprintf(output, shift); 483 fprintf(output, "ExternalID=%s\n", ent->ExternalID); 484 } 485 if (ent->SystemID) { 486 fprintf(output, shift); 487 fprintf(output, "SystemID=%s\n", ent->SystemID); 488 } 489 if (ent->URI) { 490 fprintf(output, shift); 491 fprintf(output, "URI=%s\n", ent->URI); 492 } 493 if (ent->content) { 494 fprintf(output, shift); 495 fprintf(output, "content="); 496 xmlDebugDumpString(output, ent->content); 497 fprintf(output, "\n"); 498 } 499} 500 501/** 502 * xmlDebugDumpAttr: 503 * @output: the FILE * for the output 504 * @attr: the attribute 505 * @depth: the indentation level. 506 * 507 * Dumps debug information for the attribute 508 */ 509void 510xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) { 511 int i; 512 char shift[100]; 513 514 for (i = 0;((i < depth) && (i < 25));i++) 515 shift[2 * i] = shift[2 * i + 1] = ' '; 516 shift[2 * i] = shift[2 * i + 1] = 0; 517 518 fprintf(output, shift); 519 520 if (attr == NULL) { 521 fprintf(output, "Attr is NULL"); 522 return; 523 } 524 fprintf(output, "ATTRIBUTE "); 525 xmlDebugDumpString(output, attr->name); 526 fprintf(output, "\n"); 527 if (attr->children != NULL) 528 xmlDebugDumpNodeList(output, attr->children, depth + 1); 529 530 /* 531 * Do a bit of checking 532 */ 533 if (attr->parent == NULL) 534 fprintf(output, "PBM: Attr has no parent\n"); 535 if (attr->doc == NULL) 536 fprintf(output, "PBM: Attr has no doc\n"); 537 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc)) 538 fprintf(output, "PBM: Attr doc differs from parent's one\n"); 539 if (attr->prev == NULL) { 540 if ((attr->parent != NULL) && (attr->parent->properties != attr)) 541 fprintf(output, "PBM: Attr has no prev and not first of list\n"); 542 } else { 543 if (attr->prev->next != attr) 544 fprintf(output, "PBM: Attr prev->next : back link wrong\n"); 545 } 546 if (attr->next != NULL) { 547 if (attr->next->prev != attr) 548 fprintf(output, "PBM: Attr next->prev : forward link wrong\n"); 549 } 550} 551 552/** 553 * xmlDebugDumpAttrList: 554 * @output: the FILE * for the output 555 * @attr: the attribute list 556 * @depth: the indentation level. 557 * 558 * Dumps debug information for the attribute list 559 */ 560void 561xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth) 562{ 563 if (output == NULL) 564 output = stdout; 565 while (attr != NULL) { 566 xmlDebugDumpAttr(output, attr, depth); 567 attr = attr->next; 568 } 569} 570 571/** 572 * xmlDebugDumpOneNode: 573 * @output: the FILE * for the output 574 * @node: the node 575 * @depth: the indentation level. 576 * 577 * Dumps debug information for the element node, it is not recursive 578 */ 579void 580xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth) 581{ 582 int i; 583 char shift[100]; 584 585 if (output == NULL) 586 output = stdout; 587 for (i = 0; ((i < depth) && (i < 25)); i++) 588 shift[2 * i] = shift[2 * i + 1] = ' '; 589 shift[2 * i] = shift[2 * i + 1] = 0; 590 591 if (node == NULL) { 592 fprintf(output, shift); 593 fprintf(output, "node is NULL\n"); 594 return; 595 } 596 switch (node->type) { 597 case XML_ELEMENT_NODE: 598 fprintf(output, shift); 599 fprintf(output, "ELEMENT "); 600 if ((node->ns != NULL) && (node->ns->prefix != NULL)) { 601 xmlDebugDumpString(output, node->ns->prefix); 602 fprintf(output, ":"); 603 } 604 xmlDebugDumpString(output, node->name); 605 fprintf(output, "\n"); 606 break; 607 case XML_ATTRIBUTE_NODE: 608 fprintf(output, shift); 609 fprintf(output, "Error, ATTRIBUTE found here\n"); 610 break; 611 case XML_TEXT_NODE: 612 fprintf(output, shift); 613 if (node->name == (const xmlChar *) xmlStringTextNoenc) 614 fprintf(output, "TEXT no enc\n"); 615 else 616 fprintf(output, "TEXT\n"); 617 break; 618 case XML_CDATA_SECTION_NODE: 619 fprintf(output, shift); 620 fprintf(output, "CDATA_SECTION\n"); 621 break; 622 case XML_ENTITY_REF_NODE: 623 fprintf(output, shift); 624 fprintf(output, "ENTITY_REF(%s)\n", node->name); 625 break; 626 case XML_ENTITY_NODE: 627 fprintf(output, shift); 628 fprintf(output, "ENTITY\n"); 629 break; 630 case XML_PI_NODE: 631 fprintf(output, shift); 632 fprintf(output, "PI %s\n", node->name); 633 break; 634 case XML_COMMENT_NODE: 635 fprintf(output, shift); 636 fprintf(output, "COMMENT\n"); 637 break; 638 case XML_DOCUMENT_NODE: 639 case XML_HTML_DOCUMENT_NODE: 640 fprintf(output, shift); 641 fprintf(output, "Error, DOCUMENT found here\n"); 642 break; 643 case XML_DOCUMENT_TYPE_NODE: 644 fprintf(output, shift); 645 fprintf(output, "DOCUMENT_TYPE\n"); 646 break; 647 case XML_DOCUMENT_FRAG_NODE: 648 fprintf(output, shift); 649 fprintf(output, "DOCUMENT_FRAG\n"); 650 break; 651 case XML_NOTATION_NODE: 652 fprintf(output, shift); 653 fprintf(output, "NOTATION\n"); 654 break; 655 case XML_DTD_NODE: 656 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth); 657 return; 658 case XML_ELEMENT_DECL: 659 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth); 660 return; 661 case XML_ATTRIBUTE_DECL: 662 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth); 663 return; 664 case XML_ENTITY_DECL: 665 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth); 666 return; 667 case XML_NAMESPACE_DECL: 668 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth); 669 return; 670 case XML_XINCLUDE_START: 671 fprintf(output, shift); 672 fprintf(output, "INCLUDE START\n"); 673 return; 674 case XML_XINCLUDE_END: 675 fprintf(output, shift); 676 fprintf(output, "INCLUDE END\n"); 677 return; 678 default: 679 fprintf(output, shift); 680 fprintf(output, "NODE_%d !!!\n", node->type); 681 return; 682 } 683 if (node->doc == NULL) { 684 fprintf(output, shift); 685 fprintf(output, "doc == NULL !!!\n"); 686 } 687 if (node->nsDef != NULL) 688 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1); 689 if (node->properties != NULL) 690 xmlDebugDumpAttrList(output, node->properties, depth + 1); 691 if (node->type != XML_ENTITY_REF_NODE) { 692 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) { 693 shift[2 * i] = shift[2 * i + 1] = ' '; 694 shift[2 * i + 2] = shift[2 * i + 3] = 0; 695 fprintf(output, shift); 696 fprintf(output, "content="); 697#ifndef XML_USE_BUFFER_CONTENT 698 xmlDebugDumpString(output, node->content); 699#else 700 xmlDebugDumpString(output, xmlBufferContent(node->content)); 701#endif 702 fprintf(output, "\n"); 703 } 704 } else { 705 xmlEntityPtr ent; 706 707 ent = xmlGetDocEntity(node->doc, node->name); 708 if (ent != NULL) 709 xmlDebugDumpEntity(output, ent, depth + 1); 710 } 711 /* 712 * Do a bit of checking 713 */ 714 if (node->parent == NULL) 715 fprintf(output, "PBM: Node has no parent\n"); 716 if (node->doc == NULL) 717 fprintf(output, "PBM: Node has no doc\n"); 718 if ((node->parent != NULL) && (node->doc != node->parent->doc)) 719 fprintf(output, "PBM: Node doc differs from parent's one\n"); 720 if (node->prev == NULL) { 721 if ((node->parent != NULL) && (node->parent->children != node)) 722 fprintf(output, 723 "PBM: Node has no prev and not first of list\n"); 724 } else { 725 if (node->prev->next != node) 726 fprintf(output, "PBM: Node prev->next : back link wrong\n"); 727 } 728 if (node->next == NULL) { 729 if ((node->parent != NULL) && (node->parent->last != node)) 730 fprintf(output, 731 "PBM: Node has no next and not last of list\n"); 732 } else { 733 if (node->next->prev != node) 734 fprintf(output, "PBM: Node next->prev : forward link wrong\n"); 735 } 736} 737 738/** 739 * xmlDebugDumpNode: 740 * @output: the FILE * for the output 741 * @node: the node 742 * @depth: the indentation level. 743 * 744 * Dumps debug information for the element node, it is recursive 745 */ 746void 747xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth) 748{ 749 if (output == NULL) 750 output = stdout; 751 if (node == NULL) { 752 int i; 753 char shift[100]; 754 755 for (i = 0; ((i < depth) && (i < 25)); i++) 756 shift[2 * i] = shift[2 * i + 1] = ' '; 757 shift[2 * i] = shift[2 * i + 1] = 0; 758 759 fprintf(output, shift); 760 fprintf(output, "node is NULL\n"); 761 return; 762 } 763 xmlDebugDumpOneNode(output, node, depth); 764 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) 765 xmlDebugDumpNodeList(output, node->children, depth + 1); 766} 767 768/** 769 * xmlDebugDumpNodeList: 770 * @output: the FILE * for the output 771 * @node: the node list 772 * @depth: the indentation level. 773 * 774 * Dumps debug information for the list of element node, it is recursive 775 */ 776void 777xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth) 778{ 779 if (output == NULL) 780 output = stdout; 781 while (node != NULL) { 782 xmlDebugDumpNode(output, node, depth); 783 node = node->next; 784 } 785} 786 787 788/** 789 * xmlDebugDumpDocumentHead: 790 * @output: the FILE * for the output 791 * @doc: the document 792 * 793 * Dumps debug information cncerning the document, not recursive 794 */ 795void 796xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc) 797{ 798 if (output == NULL) 799 output = stdout; 800 if (doc == NULL) { 801 fprintf(output, "DOCUMENT == NULL !\n"); 802 return; 803 } 804 805 switch (doc->type) { 806 case XML_ELEMENT_NODE: 807 fprintf(output, "Error, ELEMENT found here "); 808 break; 809 case XML_ATTRIBUTE_NODE: 810 fprintf(output, "Error, ATTRIBUTE found here\n"); 811 break; 812 case XML_TEXT_NODE: 813 fprintf(output, "Error, TEXT\n"); 814 break; 815 case XML_CDATA_SECTION_NODE: 816 fprintf(output, "Error, CDATA_SECTION\n"); 817 break; 818 case XML_ENTITY_REF_NODE: 819 fprintf(output, "Error, ENTITY_REF\n"); 820 break; 821 case XML_ENTITY_NODE: 822 fprintf(output, "Error, ENTITY\n"); 823 break; 824 case XML_PI_NODE: 825 fprintf(output, "Error, PI\n"); 826 break; 827 case XML_COMMENT_NODE: 828 fprintf(output, "Error, COMMENT\n"); 829 break; 830 case XML_DOCUMENT_NODE: 831 fprintf(output, "DOCUMENT\n"); 832 break; 833 case XML_HTML_DOCUMENT_NODE: 834 fprintf(output, "HTML DOCUMENT\n"); 835 break; 836 case XML_DOCUMENT_TYPE_NODE: 837 fprintf(output, "Error, DOCUMENT_TYPE\n"); 838 break; 839 case XML_DOCUMENT_FRAG_NODE: 840 fprintf(output, "Error, DOCUMENT_FRAG\n"); 841 break; 842 case XML_NOTATION_NODE: 843 fprintf(output, "Error, NOTATION\n"); 844 break; 845 default: 846 fprintf(output, "NODE_%d\n", doc->type); 847 } 848 if (doc->name != NULL) { 849 fprintf(output, "name="); 850 xmlDebugDumpString(output, BAD_CAST doc->name); 851 fprintf(output, "\n"); 852 } 853 if (doc->version != NULL) { 854 fprintf(output, "version="); 855 xmlDebugDumpString(output, doc->version); 856 fprintf(output, "\n"); 857 } 858 if (doc->encoding != NULL) { 859 fprintf(output, "encoding="); 860 xmlDebugDumpString(output, doc->encoding); 861 fprintf(output, "\n"); 862 } 863 if (doc->URL != NULL) { 864 fprintf(output, "URL="); 865 xmlDebugDumpString(output, doc->URL); 866 fprintf(output, "\n"); 867 } 868 if (doc->standalone) 869 fprintf(output, "standalone=true\n"); 870 if (doc->oldNs != NULL) 871 xmlDebugDumpNamespaceList(output, doc->oldNs, 0); 872} 873 874/** 875 * xmlDebugDumpDocument: 876 * @output: the FILE * for the output 877 * @doc: the document 878 * 879 * Dumps debug information for the document, it's recursive 880 */ 881void 882xmlDebugDumpDocument(FILE * output, xmlDocPtr doc) 883{ 884 if (output == NULL) 885 output = stdout; 886 if (doc == NULL) { 887 fprintf(output, "DOCUMENT == NULL !\n"); 888 return; 889 } 890 xmlDebugDumpDocumentHead(output, doc); 891 if (((doc->type == XML_DOCUMENT_NODE) || 892 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL)) 893 xmlDebugDumpNodeList(output, doc->children, 1); 894} 895 896/** 897 * xmlDebugDumpDTD: 898 * @output: the FILE * for the output 899 * @dtd: the DTD 900 * 901 * Dumps debug information for the DTD 902 */ 903void 904xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd) 905{ 906 if (output == NULL) 907 output = stdout; 908 if (dtd == NULL) { 909 fprintf(output, "DTD is NULL\n"); 910 return; 911 } 912 if (dtd->type != XML_DTD_NODE) { 913 fprintf(output, "PBM: not a DTD\n"); 914 return; 915 } 916 if (dtd->name != NULL) 917 fprintf(output, "DTD(%s)", dtd->name); 918 else 919 fprintf(output, "DTD"); 920 if (dtd->ExternalID != NULL) 921 fprintf(output, ", PUBLIC %s", dtd->ExternalID); 922 if (dtd->SystemID != NULL) 923 fprintf(output, ", SYSTEM %s", dtd->SystemID); 924 fprintf(output, "\n"); 925 /* 926 * Do a bit of checking 927 */ 928 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc)) 929 fprintf(output, "PBM: DTD doc differs from parent's one\n"); 930 if (dtd->prev == NULL) { 931 if ((dtd->parent != NULL) 932 && (dtd->parent->children != (xmlNodePtr) dtd)) 933 fprintf(output, 934 "PBM: DTD has no prev and not first of list\n"); 935 } else { 936 if (dtd->prev->next != (xmlNodePtr) dtd) 937 fprintf(output, "PBM: DTD prev->next : back link wrong\n"); 938 } 939 if (dtd->next == NULL) { 940 if ((dtd->parent != NULL) 941 && (dtd->parent->last != (xmlNodePtr) dtd)) 942 fprintf(output, "PBM: DTD has no next and not last of list\n"); 943 } else { 944 if (dtd->next->prev != (xmlNodePtr) dtd) 945 fprintf(output, "PBM: DTD next->prev : forward link wrong\n"); 946 } 947 if (dtd->children == NULL) 948 fprintf(output, " DTD is empty\n"); 949 else 950 xmlDebugDumpNodeList(output, dtd->children, 1); 951} 952 953static void 954xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) { 955 if (cur == NULL) { 956 fprintf(output, "Entity is NULL"); 957 return; 958 } 959 fprintf(output, "%s : ", cur->name); 960 switch (cur->etype) { 961 case XML_INTERNAL_GENERAL_ENTITY: 962 fprintf(output, "INTERNAL GENERAL, "); 963 break; 964 case XML_EXTERNAL_GENERAL_PARSED_ENTITY: 965 fprintf(output, "EXTERNAL PARSED, "); 966 break; 967 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: 968 fprintf(output, "EXTERNAL UNPARSED, "); 969 break; 970 case XML_INTERNAL_PARAMETER_ENTITY: 971 fprintf(output, "INTERNAL PARAMETER, "); 972 break; 973 case XML_EXTERNAL_PARAMETER_ENTITY: 974 fprintf(output, "EXTERNAL PARAMETER, "); 975 break; 976 default: 977 fprintf(output, "UNKNOWN TYPE %d", 978 cur->etype); 979 } 980 if (cur->ExternalID != NULL) 981 fprintf(output, "ID \"%s\"", cur->ExternalID); 982 if (cur->SystemID != NULL) 983 fprintf(output, "SYSTEM \"%s\"", cur->SystemID); 984 if (cur->orig != NULL) 985 fprintf(output, "\n orig \"%s\"", cur->orig); 986 if ((cur->type != XML_ELEMENT_NODE) && 987 (cur->content != NULL)) 988 fprintf(output, "\n content \"%s\"", cur->content); 989 fprintf(output, "\n"); 990} 991 992/** 993 * xmlDebugDumpEntities: 994 * @output: the FILE * for the output 995 * @doc: the document 996 * 997 * Dumps debug information for all the entities in use by the document 998 */ 999void 1000xmlDebugDumpEntities(FILE * output, xmlDocPtr doc) 1001{ 1002 if (output == NULL) 1003 output = stdout; 1004 if (doc == NULL) { 1005 fprintf(output, "DOCUMENT == NULL !\n"); 1006 return; 1007 } 1008 1009 switch (doc->type) { 1010 case XML_ELEMENT_NODE: 1011 fprintf(output, "Error, ELEMENT found here "); 1012 break; 1013 case XML_ATTRIBUTE_NODE: 1014 fprintf(output, "Error, ATTRIBUTE found here\n"); 1015 break; 1016 case XML_TEXT_NODE: 1017 fprintf(output, "Error, TEXT\n"); 1018 break; 1019 case XML_CDATA_SECTION_NODE: 1020 fprintf(output, "Error, CDATA_SECTION\n"); 1021 break; 1022 case XML_ENTITY_REF_NODE: 1023 fprintf(output, "Error, ENTITY_REF\n"); 1024 break; 1025 case XML_ENTITY_NODE: 1026 fprintf(output, "Error, ENTITY\n"); 1027 break; 1028 case XML_PI_NODE: 1029 fprintf(output, "Error, PI\n"); 1030 break; 1031 case XML_COMMENT_NODE: 1032 fprintf(output, "Error, COMMENT\n"); 1033 break; 1034 case XML_DOCUMENT_NODE: 1035 fprintf(output, "DOCUMENT\n"); 1036 break; 1037 case XML_HTML_DOCUMENT_NODE: 1038 fprintf(output, "HTML DOCUMENT\n"); 1039 break; 1040 case XML_DOCUMENT_TYPE_NODE: 1041 fprintf(output, "Error, DOCUMENT_TYPE\n"); 1042 break; 1043 case XML_DOCUMENT_FRAG_NODE: 1044 fprintf(output, "Error, DOCUMENT_FRAG\n"); 1045 break; 1046 case XML_NOTATION_NODE: 1047 fprintf(output, "Error, NOTATION\n"); 1048 break; 1049 default: 1050 fprintf(output, "NODE_%d\n", doc->type); 1051 } 1052 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) { 1053 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 1054 doc->intSubset->entities; 1055 1056 fprintf(output, "Entities in internal subset\n"); 1057 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback, 1058 output); 1059 } else 1060 fprintf(output, "No entities in internal subset\n"); 1061 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) { 1062 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 1063 doc->extSubset->entities; 1064 1065 fprintf(output, "Entities in external subset\n"); 1066 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback, 1067 output); 1068 } else 1069 fprintf(output, "No entities in external subset\n"); 1070} 1071 1072/** 1073 * xmlLsCountNode: 1074 * @node: the node to count 1075 * 1076 * Count the children of @node. 1077 * 1078 * Returns the number of children of @node. 1079 */ 1080int 1081xmlLsCountNode(xmlNodePtr node) { 1082 int ret = 0; 1083 xmlNodePtr list = NULL; 1084 1085 if (node == NULL) 1086 return(0); 1087 1088 switch (node->type) { 1089 case XML_ELEMENT_NODE: 1090 list = node->children; 1091 break; 1092 case XML_DOCUMENT_NODE: 1093 case XML_HTML_DOCUMENT_NODE: 1094#ifdef LIBXML_DOCB_ENABLED 1095 case XML_DOCB_DOCUMENT_NODE: 1096#endif 1097 list = ((xmlDocPtr) node)->children; 1098 break; 1099 case XML_ATTRIBUTE_NODE: 1100 list = ((xmlAttrPtr) node)->children; 1101 break; 1102 case XML_TEXT_NODE: 1103 case XML_CDATA_SECTION_NODE: 1104 case XML_PI_NODE: 1105 case XML_COMMENT_NODE: 1106 if (node->content != NULL) { 1107#ifndef XML_USE_BUFFER_CONTENT 1108 ret = xmlStrlen(node->content); 1109#else 1110 ret = xmlBufferLength(node->content); 1111#endif 1112 } 1113 break; 1114 case XML_ENTITY_REF_NODE: 1115 case XML_DOCUMENT_TYPE_NODE: 1116 case XML_ENTITY_NODE: 1117 case XML_DOCUMENT_FRAG_NODE: 1118 case XML_NOTATION_NODE: 1119 case XML_DTD_NODE: 1120 case XML_ELEMENT_DECL: 1121 case XML_ATTRIBUTE_DECL: 1122 case XML_ENTITY_DECL: 1123 case XML_NAMESPACE_DECL: 1124 case XML_XINCLUDE_START: 1125 case XML_XINCLUDE_END: 1126 ret = 1; 1127 break; 1128 } 1129 for (;list != NULL;ret++) 1130 list = list->next; 1131 return(ret); 1132} 1133 1134/** 1135 * xmlLsOneNode: 1136 * @output: the FILE * for the output 1137 * @node: the node to dump 1138 * 1139 * Dump to @output the type and name of @node. 1140 */ 1141void 1142xmlLsOneNode(FILE *output, xmlNodePtr node) { 1143 if (node == NULL) { 1144 fprintf(output, "NULL\n"); 1145 return; 1146 } 1147 switch (node->type) { 1148 case XML_ELEMENT_NODE: 1149 fprintf(output, "-"); 1150 break; 1151 case XML_ATTRIBUTE_NODE: 1152 fprintf(output, "a"); 1153 break; 1154 case XML_TEXT_NODE: 1155 fprintf(output, "t"); 1156 break; 1157 case XML_CDATA_SECTION_NODE: 1158 fprintf(output, "c"); 1159 break; 1160 case XML_ENTITY_REF_NODE: 1161 fprintf(output, "e"); 1162 break; 1163 case XML_ENTITY_NODE: 1164 fprintf(output, "E"); 1165 break; 1166 case XML_PI_NODE: 1167 fprintf(output, "p"); 1168 break; 1169 case XML_COMMENT_NODE: 1170 fprintf(output, "c"); 1171 break; 1172 case XML_DOCUMENT_NODE: 1173 fprintf(output, "d"); 1174 break; 1175 case XML_HTML_DOCUMENT_NODE: 1176 fprintf(output, "h"); 1177 break; 1178 case XML_DOCUMENT_TYPE_NODE: 1179 fprintf(output, "T"); 1180 break; 1181 case XML_DOCUMENT_FRAG_NODE: 1182 fprintf(output, "F"); 1183 break; 1184 case XML_NOTATION_NODE: 1185 fprintf(output, "N"); 1186 break; 1187 case XML_NAMESPACE_DECL: 1188 fprintf(output, "n"); 1189 break; 1190 default: 1191 fprintf(output, "?"); 1192 } 1193 if (node->type != XML_NAMESPACE_DECL) { 1194 if (node->properties != NULL) 1195 fprintf(output, "a"); 1196 else 1197 fprintf(output, "-"); 1198 if (node->nsDef != NULL) 1199 fprintf(output, "n"); 1200 else 1201 fprintf(output, "-"); 1202 } 1203 1204 fprintf(output, " %8d ", xmlLsCountNode(node)); 1205 1206 switch (node->type) { 1207 case XML_ELEMENT_NODE: 1208 if (node->name != NULL) 1209 fprintf(output, "%s", node->name); 1210 break; 1211 case XML_ATTRIBUTE_NODE: 1212 if (node->name != NULL) 1213 fprintf(output, "%s", node->name); 1214 break; 1215 case XML_TEXT_NODE: 1216 if (node->content != NULL) { 1217#ifndef XML_USE_BUFFER_CONTENT 1218 xmlDebugDumpString(output, node->content); 1219#else 1220 xmlDebugDumpString(output, xmlBufferContent(node->content)); 1221#endif 1222 } 1223 break; 1224 case XML_CDATA_SECTION_NODE: 1225 break; 1226 case XML_ENTITY_REF_NODE: 1227 if (node->name != NULL) 1228 fprintf(output, "%s", node->name); 1229 break; 1230 case XML_ENTITY_NODE: 1231 if (node->name != NULL) 1232 fprintf(output, "%s", node->name); 1233 break; 1234 case XML_PI_NODE: 1235 if (node->name != NULL) 1236 fprintf(output, "%s", node->name); 1237 break; 1238 case XML_COMMENT_NODE: 1239 break; 1240 case XML_DOCUMENT_NODE: 1241 break; 1242 case XML_HTML_DOCUMENT_NODE: 1243 break; 1244 case XML_DOCUMENT_TYPE_NODE: 1245 break; 1246 case XML_DOCUMENT_FRAG_NODE: 1247 break; 1248 case XML_NOTATION_NODE: 1249 break; 1250 case XML_NAMESPACE_DECL: { 1251 xmlNsPtr ns = (xmlNsPtr) node; 1252 1253 if (ns->prefix == NULL) 1254 fprintf(output, "default -> %s", ns->href); 1255 else 1256 fprintf(output, "%s -> %s", ns->prefix, ns->href); 1257 break; 1258 } 1259 default: 1260 if (node->name != NULL) 1261 fprintf(output, "%s", node->name); 1262 } 1263 fprintf(output, "\n"); 1264} 1265 1266/** 1267 * xmlBoolToText: 1268 * @boolval: a bool to turn into text 1269 * 1270 * Convenient way to turn bool into text 1271 * 1272 * Returns a pointer to either "True" or "False" 1273 */ 1274const char * 1275xmlBoolToText(int boolval) 1276{ 1277 if (boolval) 1278 return("True"); 1279 else 1280 return("False"); 1281} 1282 1283/**************************************************************** 1284 * * 1285 * The XML shell related functions * 1286 * * 1287 ****************************************************************/ 1288 1289 1290 1291/* 1292 * TODO: Improvement/cleanups for the XML shell 1293 * - allow to shell out an editor on a subpart 1294 * - cleanup function registrations (with help) and calling 1295 * - provide registration routines 1296 */ 1297 1298/** 1299 * xmlShellPrintXPathError: 1300 * @errorType: valid xpath error id 1301 * @arg: the argument that cause xpath to fail 1302 * 1303 * Print the xpath error to libxml default error channel 1304 */ 1305void 1306xmlShellPrintXPathError(int errorType, const char *arg) 1307{ 1308 const char *default_arg = "Result"; 1309 1310 if (!arg) 1311 arg = default_arg; 1312 1313 switch (errorType) { 1314 case XPATH_UNDEFINED: 1315 xmlGenericError(xmlGenericErrorContext, 1316 "%s: no such node\n", arg); 1317 break; 1318 1319 case XPATH_BOOLEAN: 1320 xmlGenericError(xmlGenericErrorContext, 1321 "%s is a Boolean\n", arg); 1322 break; 1323 case XPATH_NUMBER: 1324 xmlGenericError(xmlGenericErrorContext, 1325 "%s is a number\n", arg); 1326 break; 1327 case XPATH_STRING: 1328 xmlGenericError(xmlGenericErrorContext, 1329 "%s is a string\n", arg); 1330 break; 1331 case XPATH_POINT: 1332 xmlGenericError(xmlGenericErrorContext, 1333 "%s is a point\n", arg); 1334 break; 1335 case XPATH_RANGE: 1336 xmlGenericError(xmlGenericErrorContext, 1337 "%s is a range\n", arg); 1338 break; 1339 case XPATH_LOCATIONSET: 1340 xmlGenericError(xmlGenericErrorContext, 1341 "%s is a range\n", arg); 1342 break; 1343 case XPATH_USERS: 1344 xmlGenericError(xmlGenericErrorContext, 1345 "%s is user-defined\n", arg); 1346 break; 1347 case XPATH_XSLT_TREE: 1348 xmlGenericError(xmlGenericErrorContext, 1349 "%s is an XSLT value tree\n", arg); 1350 break; 1351 } 1352 xmlGenericError(xmlGenericErrorContext, 1353 "Try casting the result string function (xpath builtin)\n", 1354 arg); 1355} 1356 1357 1358/** 1359 * xmlShellPrintNode: 1360 * @node : a non-null node to print to stdout 1361 * 1362 * Print node to stdout 1363 */ 1364void 1365xmlShellPrintNode(xmlNodePtr node) 1366{ 1367 if (!node) 1368 return; 1369 1370 if (node->type == XML_DOCUMENT_NODE) 1371 xmlDocDump(stdout, (xmlDocPtr) node); 1372 else if (node->type == XML_ATTRIBUTE_NODE) 1373 xmlDebugDumpAttrList(stdout, (xmlAttrPtr) node, 0); 1374 else 1375 xmlElemDump(stdout, node->doc, node); 1376 1377 fprintf(stdout, "\n"); 1378} 1379 1380 1381/** 1382 * xmlShellPrintXPathResult: 1383 * @list: a valid result generated by an xpath evaluation 1384 * 1385 * Prints result to stdout 1386 */ 1387void 1388xmlShellPrintXPathResult(xmlXPathObjectPtr list) 1389{ 1390 int i = 0; 1391 1392 if (list != NULL) { 1393 switch (list->type) { 1394 case XPATH_NODESET:{ 1395 int indx; 1396 1397 if (list->nodesetval) { 1398 for (indx = 0; indx < list->nodesetval->nodeNr; 1399 indx++) { 1400 if (i > 0) 1401 fprintf(stderr, " -------\n"); 1402 xmlShellPrintNode(list->nodesetval-> 1403 nodeTab[indx]); 1404 } 1405 } else { 1406 xmlGenericError(xmlGenericErrorContext, 1407 "Empty node set\n"); 1408 } 1409 break; 1410 } 1411 case XPATH_BOOLEAN: 1412 xmlGenericError(xmlGenericErrorContext, 1413 "Is a Boolean:%s\n", 1414 xmlBoolToText(list->boolval)); 1415 break; 1416 case XPATH_NUMBER: 1417 xmlGenericError(xmlGenericErrorContext, 1418 "Is a number:%0g\n", list->floatval); 1419 break; 1420 case XPATH_STRING: 1421 xmlGenericError(xmlGenericErrorContext, 1422 "Is a string:%s\n", list->stringval); 1423 break; 1424 1425 default: 1426 xmlShellPrintXPathError(list->type, NULL); 1427 } 1428 } 1429} 1430 1431/** 1432 * xmlShellList: 1433 * @ctxt: the shell context 1434 * @arg: unused 1435 * @node: a node 1436 * @node2: unused 1437 * 1438 * Implements the XML shell function "ls" 1439 * Does an Unix like listing of the given node (like a directory) 1440 * 1441 * Returns 0 1442 */ 1443int 1444xmlShellList(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, 1445 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, 1446 xmlNodePtr node2 ATTRIBUTE_UNUSED) 1447{ 1448 xmlNodePtr cur; 1449 if (node == NULL) { 1450 fprintf(stdout, "NULL\n"); 1451 return (0); 1452 } 1453 if ((node->type == XML_DOCUMENT_NODE) || 1454 (node->type == XML_HTML_DOCUMENT_NODE)) { 1455 cur = ((xmlDocPtr) node)->children; 1456 } else if (node->type == XML_NAMESPACE_DECL) { 1457 xmlLsOneNode(stdout, node); 1458 return (0); 1459 } else if (node->children != NULL) { 1460 cur = node->children; 1461 } else { 1462 xmlLsOneNode(stdout, node); 1463 return (0); 1464 } 1465 while (cur != NULL) { 1466 xmlLsOneNode(stdout, cur); 1467 cur = cur->next; 1468 } 1469 return (0); 1470} 1471 1472/** 1473 * xmlShellBase: 1474 * @ctxt: the shell context 1475 * @arg: unused 1476 * @node: a node 1477 * @node2: unused 1478 * 1479 * Implements the XML shell function "base" 1480 * dumps the current XML base of the node 1481 * 1482 * Returns 0 1483 */ 1484int 1485xmlShellBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, 1486 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, 1487 xmlNodePtr node2 ATTRIBUTE_UNUSED) 1488{ 1489 xmlChar *base; 1490 if (node == NULL) { 1491 fprintf(stdout, "NULL\n"); 1492 return (0); 1493 } 1494 1495 base = xmlNodeGetBase(node->doc, node); 1496 1497 if (base == NULL) { 1498 fprintf(stdout, " No base found !!!\n"); 1499 } else { 1500 fprintf(stdout, "%s\n", base); 1501 xmlFree(base); 1502 } 1503 return (0); 1504} 1505 1506/** 1507 * xmlShellSetBase: 1508 * @ctxt: the shell context 1509 * @arg: the new base 1510 * @node: a node 1511 * @node2: unused 1512 * 1513 * Implements the XML shell function "setbase" 1514 * change the current XML base of the node 1515 * 1516 * Returns 0 1517 */ 1518static int 1519xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, 1520 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, 1521 xmlNodePtr node2 ATTRIBUTE_UNUSED) 1522{ 1523 xmlNodeSetBase(node, (xmlChar*) arg); 1524 return (0); 1525} 1526 1527/** 1528 * xmlShellDir: 1529 * @ctxt: the shell context 1530 * @arg: unused 1531 * @node: a node 1532 * @node2: unused 1533 * 1534 * Implements the XML shell function "dir" 1535 * dumps informations about the node (namespace, attributes, content). 1536 * 1537 * Returns 0 1538 */ 1539int 1540xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, 1541 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, 1542 xmlNodePtr node2 ATTRIBUTE_UNUSED) 1543{ 1544 if (node == NULL) { 1545 fprintf(stdout, "NULL\n"); 1546 return (0); 1547 } 1548 if ((node->type == XML_DOCUMENT_NODE) || 1549 (node->type == XML_HTML_DOCUMENT_NODE)) { 1550 xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node); 1551 } else if (node->type == XML_ATTRIBUTE_NODE) { 1552 xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0); 1553 } else { 1554 xmlDebugDumpOneNode(stdout, node, 0); 1555 } 1556 return (0); 1557} 1558 1559/** 1560 * xmlShellCat: 1561 * @ctxt: the shell context 1562 * @arg: unused 1563 * @node: a node 1564 * @node2: unused 1565 * 1566 * Implements the XML shell function "cat" 1567 * dumps the serialization node content (XML or HTML). 1568 * 1569 * Returns 0 1570 */ 1571int 1572xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED, 1573 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) 1574{ 1575 if (node == NULL) { 1576 fprintf(stdout, "NULL\n"); 1577 return (0); 1578 } 1579 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) { 1580#ifdef LIBXML_HTML_ENABLED 1581 if (node->type == XML_HTML_DOCUMENT_NODE) 1582 htmlDocDump(stdout, (htmlDocPtr) node); 1583 else 1584 htmlNodeDumpFile(stdout, ctxt->doc, node); 1585#else 1586 if (node->type == XML_DOCUMENT_NODE) 1587 xmlDocDump(stdout, (xmlDocPtr) node); 1588 else 1589 xmlElemDump(stdout, ctxt->doc, node); 1590#endif /* LIBXML_HTML_ENABLED */ 1591 } else { 1592 if (node->type == XML_DOCUMENT_NODE) 1593 xmlDocDump(stdout, (xmlDocPtr) node); 1594 else 1595 xmlElemDump(stdout, ctxt->doc, node); 1596 } 1597 fprintf(stdout, "\n"); 1598 return (0); 1599} 1600 1601/** 1602 * xmlShellLoad: 1603 * @ctxt: the shell context 1604 * @filename: the file name 1605 * @node: unused 1606 * @node2: unused 1607 * 1608 * Implements the XML shell function "load" 1609 * loads a new document specified by the filename 1610 * 1611 * Returns 0 or -1 if loading failed 1612 */ 1613int 1614xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, 1615 xmlNodePtr node ATTRIBUTE_UNUSED, 1616 xmlNodePtr node2 ATTRIBUTE_UNUSED) 1617{ 1618 xmlDocPtr doc; 1619 int html = 0; 1620 1621 if (ctxt->doc != NULL) 1622 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE); 1623 1624 if (html) { 1625#ifdef LIBXML_HTML_ENABLED 1626 doc = htmlParseFile(filename, NULL); 1627#else 1628 fprintf(stdout, "HTML support not compiled in\n"); 1629 doc = NULL; 1630#endif /* LIBXML_HTML_ENABLED */ 1631 } else { 1632 doc = xmlParseFile(filename); 1633 } 1634 if (doc != NULL) { 1635 if (ctxt->loaded == 1) { 1636 xmlFreeDoc(ctxt->doc); 1637 } 1638 ctxt->loaded = 1; 1639#ifdef LIBXML_XPATH_ENABLED 1640 xmlXPathFreeContext(ctxt->pctxt); 1641#endif /* LIBXML_XPATH_ENABLED */ 1642 xmlFree(ctxt->filename); 1643 ctxt->doc = doc; 1644 ctxt->node = (xmlNodePtr) doc; 1645#ifdef LIBXML_XPATH_ENABLED 1646 ctxt->pctxt = xmlXPathNewContext(doc); 1647#endif /* LIBXML_XPATH_ENABLED */ 1648 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename); 1649 } else 1650 return (-1); 1651 return (0); 1652} 1653 1654/** 1655 * xmlShellWrite: 1656 * @ctxt: the shell context 1657 * @filename: the file name 1658 * @node: a node in the tree 1659 * @node2: unused 1660 * 1661 * Implements the XML shell function "write" 1662 * Write the current node to the filename, it saves the serialization 1663 * of the subtree under the @node specified 1664 * 1665 * Returns 0 or -1 in case of error 1666 */ 1667int 1668xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node, 1669 xmlNodePtr node2 ATTRIBUTE_UNUSED) 1670{ 1671 if (node == NULL) 1672 return (-1); 1673 if ((filename == NULL) || (filename[0] == 0)) { 1674 xmlGenericError(xmlGenericErrorContext, 1675 "Write command requires a filename argument\n"); 1676 return (-1); 1677 } 1678#ifdef W_OK 1679 if (access((char *) filename, W_OK)) { 1680 xmlGenericError(xmlGenericErrorContext, 1681 "Cannot write to %s\n", filename); 1682 return (-1); 1683 } 1684#endif 1685 switch (node->type) { 1686 case XML_DOCUMENT_NODE: 1687 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) { 1688 xmlGenericError(xmlGenericErrorContext, 1689 "Failed to write to %s\n", filename); 1690 return (-1); 1691 } 1692 break; 1693 case XML_HTML_DOCUMENT_NODE: 1694#ifdef LIBXML_HTML_ENABLED 1695 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) { 1696 xmlGenericError(xmlGenericErrorContext, 1697 "Failed to write to %s\n", filename); 1698 return (-1); 1699 } 1700#else 1701 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) { 1702 xmlGenericError(xmlGenericErrorContext, 1703 "Failed to write to %s\n", filename); 1704 return (-1); 1705 } 1706#endif /* LIBXML_HTML_ENABLED */ 1707 break; 1708 default:{ 1709 FILE *f; 1710 1711 f = fopen((char *) filename, "w"); 1712 if (f == NULL) { 1713 xmlGenericError(xmlGenericErrorContext, 1714 "Failed to write to %s\n", filename); 1715 return (-1); 1716 } 1717 xmlElemDump(f, ctxt->doc, node); 1718 fclose(f); 1719 } 1720 } 1721 return (0); 1722} 1723 1724/** 1725 * xmlShellSave: 1726 * @ctxt: the shell context 1727 * @filename: the file name (optional) 1728 * @node: unused 1729 * @node2: unused 1730 * 1731 * Implements the XML shell function "save" 1732 * Write the current document to the filename, or it's original name 1733 * 1734 * Returns 0 or -1 in case of error 1735 */ 1736int 1737xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, 1738 xmlNodePtr node ATTRIBUTE_UNUSED, 1739 xmlNodePtr node2 ATTRIBUTE_UNUSED) 1740{ 1741 if (ctxt->doc == NULL) 1742 return (-1); 1743 if ((filename == NULL) || (filename[0] == 0)) 1744 filename = ctxt->filename; 1745#ifdef W_OK 1746 if (access((char *) filename, W_OK)) { 1747 xmlGenericError(xmlGenericErrorContext, 1748 "Cannot save to %s\n", filename); 1749 return (-1); 1750 } 1751#endif 1752 switch (ctxt->doc->type) { 1753 case XML_DOCUMENT_NODE: 1754 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) { 1755 xmlGenericError(xmlGenericErrorContext, 1756 "Failed to save to %s\n", filename); 1757 } 1758 break; 1759 case XML_HTML_DOCUMENT_NODE: 1760#ifdef LIBXML_HTML_ENABLED 1761 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) { 1762 xmlGenericError(xmlGenericErrorContext, 1763 "Failed to save to %s\n", filename); 1764 } 1765#else 1766 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) { 1767 xmlGenericError(xmlGenericErrorContext, 1768 "Failed to save to %s\n", filename); 1769 } 1770#endif /* LIBXML_HTML_ENABLED */ 1771 break; 1772 default: 1773 xmlGenericError(xmlGenericErrorContext, 1774 "To save to subparts of a document use the 'write' command\n"); 1775 return (-1); 1776 1777 } 1778 return (0); 1779} 1780 1781/** 1782 * xmlShellValidate: 1783 * @ctxt: the shell context 1784 * @dtd: the DTD URI (optional) 1785 * @node: unused 1786 * @node2: unused 1787 * 1788 * Implements the XML shell function "validate" 1789 * Validate the document, if a DTD path is provided, then the validation 1790 * is done against the given DTD. 1791 * 1792 * Returns 0 or -1 in case of error 1793 */ 1794int 1795xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, 1796 xmlNodePtr node ATTRIBUTE_UNUSED, 1797 xmlNodePtr node2 ATTRIBUTE_UNUSED) 1798{ 1799 xmlValidCtxt vctxt; 1800 int res = -1; 1801 1802 vctxt.userData = stderr; 1803 vctxt.error = (xmlValidityErrorFunc) fprintf; 1804 vctxt.warning = (xmlValidityWarningFunc) fprintf; 1805 1806 if ((dtd == NULL) || (dtd[0] == 0)) { 1807 res = xmlValidateDocument(&vctxt, ctxt->doc); 1808 } else { 1809 xmlDtdPtr subset; 1810 1811 subset = xmlParseDTD(NULL, (xmlChar *) dtd); 1812 if (subset != NULL) { 1813 res = xmlValidateDtd(&vctxt, ctxt->doc, subset); 1814 1815 xmlFreeDtd(subset); 1816 } 1817 } 1818 return (res); 1819} 1820 1821/** 1822 * xmlShellDu: 1823 * @ctxt: the shell context 1824 * @arg: unused 1825 * @tree: a node defining a subtree 1826 * @node2: unused 1827 * 1828 * Implements the XML shell function "du" 1829 * show the structure of the subtree under node @tree 1830 * If @tree is null, the command works on the current node. 1831 * 1832 * Returns 0 or -1 in case of error 1833 */ 1834int 1835xmlShellDu(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, 1836 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree, 1837 xmlNodePtr node2 ATTRIBUTE_UNUSED) 1838{ 1839 xmlNodePtr node; 1840 int indent = 0, i; 1841 1842 if (tree == NULL) 1843 return (-1); 1844 node = tree; 1845 while (node != NULL) { 1846 if ((node->type == XML_DOCUMENT_NODE) || 1847 (node->type == XML_HTML_DOCUMENT_NODE)) { 1848 fprintf(stdout, "/\n"); 1849 } else if (node->type == XML_ELEMENT_NODE) { 1850 for (i = 0; i < indent; i++) 1851 fprintf(stdout, " "); 1852 fprintf(stdout, "%s\n", node->name); 1853 } else { 1854 } 1855 1856 /* 1857 * Browse the full subtree, deep first 1858 */ 1859 1860 if ((node->type == XML_DOCUMENT_NODE) || 1861 (node->type == XML_HTML_DOCUMENT_NODE)) { 1862 node = ((xmlDocPtr) node)->children; 1863 } else if ((node->children != NULL) 1864 && (node->type != XML_ENTITY_REF_NODE)) { 1865 /* deep first */ 1866 node = node->children; 1867 indent++; 1868 } else if ((node != tree) && (node->next != NULL)) { 1869 /* then siblings */ 1870 node = node->next; 1871 } else if (node != tree) { 1872 /* go up to parents->next if needed */ 1873 while (node != tree) { 1874 if (node->parent != NULL) { 1875 node = node->parent; 1876 indent--; 1877 } 1878 if ((node != tree) && (node->next != NULL)) { 1879 node = node->next; 1880 break; 1881 } 1882 if (node->parent == NULL) { 1883 node = NULL; 1884 break; 1885 } 1886 if (node == tree) { 1887 node = NULL; 1888 break; 1889 } 1890 } 1891 /* exit condition */ 1892 if (node == tree) 1893 node = NULL; 1894 } else 1895 node = NULL; 1896 } 1897 return (0); 1898} 1899 1900/** 1901 * xmlShellPwd: 1902 * @ctxt: the shell context 1903 * @buffer: the output buffer 1904 * @node: a node 1905 * @node2: unused 1906 * 1907 * Implements the XML shell function "pwd" 1908 * Show the full path from the root to the node, if needed building 1909 * thumblers when similar elements exists at a given ancestor level. 1910 * The output is compatible with XPath commands. 1911 * 1912 * Returns 0 or -1 in case of error 1913 */ 1914int 1915xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer, 1916 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) 1917{ 1918 xmlChar *path; 1919 1920 if (node == NULL) 1921 return (-1); 1922 1923 path = xmlGetNodePath(node); 1924 if (path == NULL) 1925 return (-1); 1926 1927 /* 1928 * This test prevents buffer overflow, because this routine 1929 * is only called by xmlShell, in which the second argument is 1930 * 500 chars long. 1931 * It is a dirty hack before a cleaner solution is found. 1932 * Documentation should mention that the second argument must 1933 * be at least 500 chars long, and could be stripped if too long. 1934 */ 1935 snprintf(buffer, 499, "%s", path); 1936 buffer[499] = '0'; 1937 xmlFree(path); 1938 1939 return (0); 1940} 1941 1942/** 1943 * xmlShell 1944 * @doc: the initial document 1945 * @filename: the output buffer 1946 * @input: the line reading function 1947 * @output: the output FILE* 1948 * 1949 * Implements the XML shell 1950 * This allow to load, validate, view, modify and save a document 1951 * using a environment similar to a UNIX commandline. 1952 */ 1953void 1954xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, 1955 FILE * output) 1956{ 1957 char prompt[500] = "/ > "; 1958 char *cmdline = NULL, *cur; 1959 int nbargs; 1960 char command[100]; 1961 char arg[400]; 1962 int i; 1963 xmlShellCtxtPtr ctxt; 1964 xmlXPathObjectPtr list; 1965 1966 if (doc == NULL) 1967 return; 1968 if (filename == NULL) 1969 return; 1970 if (input == NULL) 1971 return; 1972 if (output == NULL) 1973 return; 1974 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt)); 1975 if (ctxt == NULL) 1976 return; 1977 ctxt->loaded = 0; 1978 ctxt->doc = doc; 1979 ctxt->input = input; 1980 ctxt->output = output; 1981 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename); 1982 ctxt->node = (xmlNodePtr) ctxt->doc; 1983 1984#ifdef LIBXML_XPATH_ENABLED 1985 ctxt->pctxt = xmlXPathNewContext(ctxt->doc); 1986 if (ctxt->pctxt == NULL) { 1987 xmlFree(ctxt); 1988 return; 1989 } 1990#endif /* LIBXML_XPATH_ENABLED */ 1991 while (1) { 1992 if (ctxt->node == (xmlNodePtr) ctxt->doc) 1993 sprintf(prompt, "%s > ", "/"); 1994 else if (ctxt->node->name) 1995 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name); 1996 else 1997 sprintf(prompt, "? > "); 1998 prompt[sizeof(prompt) - 1] = 0; 1999 2000 /* 2001 * Get a new command line 2002 */ 2003 cmdline = ctxt->input(prompt); 2004 if (cmdline == NULL) 2005 break; 2006 2007 /* 2008 * Parse the command itself 2009 */ 2010 cur = cmdline; 2011 nbargs = 0; 2012 while ((*cur == ' ') || (*cur == '\t')) 2013 cur++; 2014 i = 0; 2015 while ((*cur != ' ') && (*cur != '\t') && 2016 (*cur != '\n') && (*cur != '\r')) { 2017 if (*cur == 0) 2018 break; 2019 command[i++] = *cur++; 2020 } 2021 command[i] = 0; 2022 if (i == 0) 2023 continue; 2024 nbargs++; 2025 2026 /* 2027 * Parse the argument 2028 */ 2029 while ((*cur == ' ') || (*cur == '\t')) 2030 cur++; 2031 i = 0; 2032 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) { 2033 if (*cur == 0) 2034 break; 2035 arg[i++] = *cur++; 2036 } 2037 arg[i] = 0; 2038 if (i != 0) 2039 nbargs++; 2040 2041 /* 2042 * start interpreting the command 2043 */ 2044 if (!strcmp(command, "exit")) 2045 break; 2046 if (!strcmp(command, "quit")) 2047 break; 2048 if (!strcmp(command, "bye")) 2049 break; 2050 if (!strcmp(command, "help")) { 2051 fprintf(stdout, "\tbase display XML base of the node\n"); 2052 fprintf(stdout, "\tsetbase URI change the XML base of the node\n"); 2053 fprintf(stdout, "\tbye leave shell\n"); 2054 fprintf(stdout, "\tcat [node] display node or current node\n"); 2055 fprintf(stdout, "\tcd [path] change directory to path or to root\n"); 2056 fprintf(stdout, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n"); 2057 fprintf(stdout, "\tdu [path] show the structure of the subtree under path or the current node\n"); 2058 fprintf(stdout, "\texit leave shell\n"); 2059 fprintf(stdout, "\thelp display this help\n"); 2060 fprintf(stdout, "\tfree display memory usage\n"); 2061 fprintf(stdout, "\tload [name] load a new document with name\n"); 2062 fprintf(stdout, "\tls [path] list contents of path or the current directory\n"); 2063#ifdef LIBXML_XPATH_ENABLED 2064 fprintf(stdout, "\txpath expr evaluate the XPath expression in that context and print the result\n"); 2065#endif /* LIBXML_XPATH_ENABLED */ 2066 fprintf(stdout, "\tpwd display current working directory\n"); 2067 fprintf(stdout, "\tquit leave shell\n"); 2068 fprintf(stdout, "\tsave [name] save this document to name or the original name\n"); 2069 fprintf(stdout, "\tvalidate check the document for errors\n"); 2070 fprintf(stdout, "\twrite [name] write the current node to the filename\n"); 2071 } else if (!strcmp(command, "validate")) { 2072 xmlShellValidate(ctxt, arg, NULL, NULL); 2073 } else if (!strcmp(command, "load")) { 2074 xmlShellLoad(ctxt, arg, NULL, NULL); 2075 } else if (!strcmp(command, "save")) { 2076 xmlShellSave(ctxt, arg, NULL, NULL); 2077 } else if (!strcmp(command, "write")) { 2078 xmlShellWrite(ctxt, arg, NULL, NULL); 2079 } else if (!strcmp(command, "free")) { 2080 if (arg[0] == 0) { 2081 xmlMemShow(stdout, 0); 2082 } else { 2083 int len = 0; 2084 2085 sscanf(arg, "%d", &len); 2086 xmlMemShow(stdout, len); 2087 } 2088 } else if (!strcmp(command, "pwd")) { 2089 char dir[500]; 2090 2091 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL)) 2092 fprintf(stdout, "%s\n", dir); 2093 } else if (!strcmp(command, "du")) { 2094 xmlShellDu(ctxt, NULL, ctxt->node, NULL); 2095 } else if (!strcmp(command, "base")) { 2096 xmlShellBase(ctxt, NULL, ctxt->node, NULL); 2097#ifdef LIBXML_XPATH_ENABLED 2098 } else if (!strcmp(command, "xpath")) { 2099 if (arg[0] == 0) { 2100 xmlGenericError(xmlGenericErrorContext, 2101 "xpath: expression required\n"); 2102 } else { 2103 ctxt->pctxt->node = ctxt->node; 2104 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); 2105 xmlXPathDebugDumpObject(stdout, list, 0); 2106 xmlXPathFreeObject(list); 2107 } 2108#endif /* LIBXML_XPATH_ENABLED */ 2109 } else if (!strcmp(command, "setbase")) { 2110 xmlShellSetBase(ctxt, arg, ctxt->node, NULL); 2111 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) { 2112 int dir = (!strcmp(command, "dir")); 2113 2114 if (arg[0] == 0) { 2115 if (dir) 2116 xmlShellDir(ctxt, NULL, ctxt->node, NULL); 2117 else 2118 xmlShellList(ctxt, NULL, ctxt->node, NULL); 2119 } else { 2120 ctxt->pctxt->node = ctxt->node; 2121#ifdef LIBXML_XPATH_ENABLED 2122 ctxt->pctxt->node = ctxt->node; 2123 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); 2124#else 2125 list = NULL; 2126#endif /* LIBXML_XPATH_ENABLED */ 2127 if (list != NULL) { 2128 switch (list->type) { 2129 case XPATH_UNDEFINED: 2130 xmlGenericError(xmlGenericErrorContext, 2131 "%s: no such node\n", arg); 2132 break; 2133 case XPATH_NODESET:{ 2134 int indx; 2135 2136 if (list->nodesetval == NULL) 2137 break; 2138 2139 for (indx = 0; 2140 indx < list->nodesetval->nodeNr; 2141 indx++) { 2142 if (dir) 2143 xmlShellDir(ctxt, NULL, 2144 list->nodesetval-> 2145 nodeTab[indx], NULL); 2146 else 2147 xmlShellList(ctxt, NULL, 2148 list->nodesetval-> 2149 nodeTab[indx], NULL); 2150 } 2151 break; 2152 } 2153 case XPATH_BOOLEAN: 2154 xmlGenericError(xmlGenericErrorContext, 2155 "%s is a Boolean\n", arg); 2156 break; 2157 case XPATH_NUMBER: 2158 xmlGenericError(xmlGenericErrorContext, 2159 "%s is a number\n", arg); 2160 break; 2161 case XPATH_STRING: 2162 xmlGenericError(xmlGenericErrorContext, 2163 "%s is a string\n", arg); 2164 break; 2165 case XPATH_POINT: 2166 xmlGenericError(xmlGenericErrorContext, 2167 "%s is a point\n", arg); 2168 break; 2169 case XPATH_RANGE: 2170 xmlGenericError(xmlGenericErrorContext, 2171 "%s is a range\n", arg); 2172 break; 2173 case XPATH_LOCATIONSET: 2174 xmlGenericError(xmlGenericErrorContext, 2175 "%s is a range\n", arg); 2176 break; 2177 case XPATH_USERS: 2178 xmlGenericError(xmlGenericErrorContext, 2179 "%s is user-defined\n", arg); 2180 break; 2181 case XPATH_XSLT_TREE: 2182 xmlGenericError(xmlGenericErrorContext, 2183 "%s is an XSLT value tree\n", 2184 arg); 2185 break; 2186 } 2187#ifdef LIBXML_XPATH_ENABLED 2188 xmlXPathFreeObject(list); 2189#endif 2190 } else { 2191 xmlGenericError(xmlGenericErrorContext, 2192 "%s: no such node\n", arg); 2193 } 2194 ctxt->pctxt->node = NULL; 2195 } 2196 } else if (!strcmp(command, "cd")) { 2197 if (arg[0] == 0) { 2198 ctxt->node = (xmlNodePtr) ctxt->doc; 2199 } else { 2200#ifdef LIBXML_XPATH_ENABLED 2201 ctxt->pctxt->node = ctxt->node; 2202 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); 2203#else 2204 list = NULL; 2205#endif /* LIBXML_XPATH_ENABLED */ 2206 if (list != NULL) { 2207 switch (list->type) { 2208 case XPATH_UNDEFINED: 2209 xmlGenericError(xmlGenericErrorContext, 2210 "%s: no such node\n", arg); 2211 break; 2212 case XPATH_NODESET: 2213 if (list->nodesetval != NULL) { 2214 if (list->nodesetval->nodeNr == 1) { 2215 ctxt->node = list->nodesetval->nodeTab[0]; 2216 } else 2217 xmlGenericError(xmlGenericErrorContext, 2218 "%s is a %d Node Set\n", 2219 arg, 2220 list->nodesetval->nodeNr); 2221 } else 2222 xmlGenericError(xmlGenericErrorContext, 2223 "%s is an empty Node Set\n", 2224 arg); 2225 break; 2226 case XPATH_BOOLEAN: 2227 xmlGenericError(xmlGenericErrorContext, 2228 "%s is a Boolean\n", arg); 2229 break; 2230 case XPATH_NUMBER: 2231 xmlGenericError(xmlGenericErrorContext, 2232 "%s is a number\n", arg); 2233 break; 2234 case XPATH_STRING: 2235 xmlGenericError(xmlGenericErrorContext, 2236 "%s is a string\n", arg); 2237 break; 2238 case XPATH_POINT: 2239 xmlGenericError(xmlGenericErrorContext, 2240 "%s is a point\n", arg); 2241 break; 2242 case XPATH_RANGE: 2243 xmlGenericError(xmlGenericErrorContext, 2244 "%s is a range\n", arg); 2245 break; 2246 case XPATH_LOCATIONSET: 2247 xmlGenericError(xmlGenericErrorContext, 2248 "%s is a range\n", arg); 2249 break; 2250 case XPATH_USERS: 2251 xmlGenericError(xmlGenericErrorContext, 2252 "%s is user-defined\n", arg); 2253 break; 2254 case XPATH_XSLT_TREE: 2255 xmlGenericError(xmlGenericErrorContext, 2256 "%s is an XSLT value tree\n", 2257 arg); 2258 break; 2259 } 2260#ifdef LIBXML_XPATH_ENABLED 2261 xmlXPathFreeObject(list); 2262#endif 2263 } else { 2264 xmlGenericError(xmlGenericErrorContext, 2265 "%s: no such node\n", arg); 2266 } 2267 ctxt->pctxt->node = NULL; 2268 } 2269 } else if (!strcmp(command, "cat")) { 2270 if (arg[0] == 0) { 2271 xmlShellCat(ctxt, NULL, ctxt->node, NULL); 2272 } else { 2273 ctxt->pctxt->node = ctxt->node; 2274#ifdef LIBXML_XPATH_ENABLED 2275 ctxt->pctxt->node = ctxt->node; 2276 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); 2277#else 2278 list = NULL; 2279#endif /* LIBXML_XPATH_ENABLED */ 2280 if (list != NULL) { 2281 switch (list->type) { 2282 case XPATH_UNDEFINED: 2283 xmlGenericError(xmlGenericErrorContext, 2284 "%s: no such node\n", arg); 2285 break; 2286 case XPATH_NODESET:{ 2287 int indx; 2288 2289 if (list->nodesetval == NULL) 2290 break; 2291 2292 for (indx = 0; 2293 indx < list->nodesetval->nodeNr; 2294 indx++) { 2295 if (i > 0) 2296 fprintf(stdout, " -------\n"); 2297 xmlShellCat(ctxt, NULL, 2298 list->nodesetval-> 2299 nodeTab[indx], NULL); 2300 } 2301 break; 2302 } 2303 case XPATH_BOOLEAN: 2304 xmlGenericError(xmlGenericErrorContext, 2305 "%s is a Boolean\n", arg); 2306 break; 2307 case XPATH_NUMBER: 2308 xmlGenericError(xmlGenericErrorContext, 2309 "%s is a number\n", arg); 2310 break; 2311 case XPATH_STRING: 2312 xmlGenericError(xmlGenericErrorContext, 2313 "%s is a string\n", arg); 2314 break; 2315 case XPATH_POINT: 2316 xmlGenericError(xmlGenericErrorContext, 2317 "%s is a point\n", arg); 2318 break; 2319 case XPATH_RANGE: 2320 xmlGenericError(xmlGenericErrorContext, 2321 "%s is a range\n", arg); 2322 break; 2323 case XPATH_LOCATIONSET: 2324 xmlGenericError(xmlGenericErrorContext, 2325 "%s is a range\n", arg); 2326 break; 2327 case XPATH_USERS: 2328 xmlGenericError(xmlGenericErrorContext, 2329 "%s is user-defined\n", arg); 2330 break; 2331 case XPATH_XSLT_TREE: 2332 xmlGenericError(xmlGenericErrorContext, 2333 "%s is an XSLT value tree\n", 2334 arg); 2335 break; 2336 } 2337#ifdef LIBXML_XPATH_ENABLED 2338 xmlXPathFreeObject(list); 2339#endif 2340 } else { 2341 xmlGenericError(xmlGenericErrorContext, 2342 "%s: no such node\n", arg); 2343 } 2344 ctxt->pctxt->node = NULL; 2345 } 2346 } else { 2347 xmlGenericError(xmlGenericErrorContext, 2348 "Unknown command %s\n", command); 2349 } 2350 free(cmdline); /* not xmlFree here ! */ 2351 } 2352#ifdef LIBXML_XPATH_ENABLED 2353 xmlXPathFreeContext(ctxt->pctxt); 2354#endif /* LIBXML_XPATH_ENABLED */ 2355 if (ctxt->loaded) { 2356 xmlFreeDoc(ctxt->doc); 2357 } 2358 if (ctxt->filename != NULL) 2359 xmlFree(ctxt->filename); 2360 xmlFree(ctxt); 2361 if (cmdline != NULL) 2362 free(cmdline); /* not xmlFree here ! */ 2363} 2364 2365#endif /* LIBXML_DEBUG_ENABLED */ 2366