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