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