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