Annotation of embedaddon/libxml2/xmlreader.c, revision 1.1
1.1 ! misho 1: /*
! 2: * xmlreader.c: implements the xmlTextReader streaming node API
! 3: *
! 4: * NOTE:
! 5: * XmlTextReader.Normalization Property won't be supported, since
! 6: * it makes the parser non compliant to the XML recommendation
! 7: *
! 8: * See Copyright for the status of this software.
! 9: *
! 10: * daniel@veillard.com
! 11: */
! 12:
! 13: /*
! 14: * TODOs:
! 15: * - XML Schemas validation
! 16: */
! 17: #define IN_LIBXML
! 18: #include "libxml.h"
! 19:
! 20: #ifdef LIBXML_READER_ENABLED
! 21: #include <string.h> /* for memset() only ! */
! 22: #include <stdarg.h>
! 23:
! 24: #ifdef HAVE_CTYPE_H
! 25: #include <ctype.h>
! 26: #endif
! 27: #ifdef HAVE_STDLIB_H
! 28: #include <stdlib.h>
! 29: #endif
! 30:
! 31: #include <libxml/xmlmemory.h>
! 32: #include <libxml/xmlIO.h>
! 33: #include <libxml/xmlreader.h>
! 34: #include <libxml/parserInternals.h>
! 35: #ifdef LIBXML_SCHEMAS_ENABLED
! 36: #include <libxml/relaxng.h>
! 37: #include <libxml/xmlschemas.h>
! 38: #endif
! 39: #include <libxml/uri.h>
! 40: #ifdef LIBXML_XINCLUDE_ENABLED
! 41: #include <libxml/xinclude.h>
! 42: #endif
! 43: #ifdef LIBXML_PATTERN_ENABLED
! 44: #include <libxml/pattern.h>
! 45: #endif
! 46:
! 47: #define MAX_ERR_MSG_SIZE 64000
! 48:
! 49: /*
! 50: * The following VA_COPY was coded following an example in
! 51: * the Samba project. It may not be sufficient for some
! 52: * esoteric implementations of va_list (i.e. it may need
! 53: * something involving a memcpy) but (hopefully) will be
! 54: * sufficient for libxml2.
! 55: */
! 56: #ifndef VA_COPY
! 57: #ifdef HAVE_VA_COPY
! 58: #define VA_COPY(dest, src) va_copy(dest, src)
! 59: #else
! 60: #ifdef HAVE___VA_COPY
! 61: #define VA_COPY(dest,src) __va_copy(dest, src)
! 62: #else
! 63: #define VA_COPY(dest,src) (dest) = (src)
! 64: #endif
! 65: #endif
! 66: #endif
! 67:
! 68: /* #define DEBUG_CALLBACKS */
! 69: /* #define DEBUG_READER */
! 70:
! 71: /**
! 72: * TODO:
! 73: *
! 74: * macro to flag unimplemented blocks
! 75: */
! 76: #define TODO \
! 77: xmlGenericError(xmlGenericErrorContext, \
! 78: "Unimplemented block at %s:%d\n", \
! 79: __FILE__, __LINE__);
! 80:
! 81: #ifdef DEBUG_READER
! 82: #define DUMP_READER xmlTextReaderDebug(reader);
! 83: #else
! 84: #define DUMP_READER
! 85: #endif
! 86:
! 87: #define CHUNK_SIZE 512
! 88: /************************************************************************
! 89: * *
! 90: * The parser: maps the Text Reader API on top of the existing *
! 91: * parsing routines building a tree *
! 92: * *
! 93: ************************************************************************/
! 94:
! 95: #define XML_TEXTREADER_INPUT 1
! 96: #define XML_TEXTREADER_CTXT 2
! 97:
! 98: typedef enum {
! 99: XML_TEXTREADER_NONE = -1,
! 100: XML_TEXTREADER_START= 0,
! 101: XML_TEXTREADER_ELEMENT= 1,
! 102: XML_TEXTREADER_END= 2,
! 103: XML_TEXTREADER_EMPTY= 3,
! 104: XML_TEXTREADER_BACKTRACK= 4,
! 105: XML_TEXTREADER_DONE= 5,
! 106: XML_TEXTREADER_ERROR= 6
! 107: } xmlTextReaderState;
! 108:
! 109: typedef enum {
! 110: XML_TEXTREADER_NOT_VALIDATE = 0,
! 111: XML_TEXTREADER_VALIDATE_DTD = 1,
! 112: XML_TEXTREADER_VALIDATE_RNG = 2,
! 113: XML_TEXTREADER_VALIDATE_XSD = 4
! 114: } xmlTextReaderValidate;
! 115:
! 116: struct _xmlTextReader {
! 117: int mode; /* the parsing mode */
! 118: xmlDocPtr doc; /* when walking an existing doc */
! 119: xmlTextReaderValidate validate;/* is there any validation */
! 120: int allocs; /* what structure were deallocated */
! 121: xmlTextReaderState state;
! 122: xmlParserCtxtPtr ctxt; /* the parser context */
! 123: xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
! 124: xmlParserInputBufferPtr input; /* the input */
! 125: startElementSAXFunc startElement;/* initial SAX callbacks */
! 126: endElementSAXFunc endElement; /* idem */
! 127: startElementNsSAX2Func startElementNs;/* idem */
! 128: endElementNsSAX2Func endElementNs; /* idem */
! 129: charactersSAXFunc characters;
! 130: cdataBlockSAXFunc cdataBlock;
! 131: unsigned int base; /* base of the segment in the input */
! 132: unsigned int cur; /* current position in the input */
! 133: xmlNodePtr node; /* current node */
! 134: xmlNodePtr curnode;/* current attribute node */
! 135: int depth; /* depth of the current node */
! 136: xmlNodePtr faketext;/* fake xmlNs chld */
! 137: int preserve;/* preserve the resulting document */
! 138: xmlBufferPtr buffer; /* used to return const xmlChar * */
! 139: xmlDictPtr dict; /* the context dictionnary */
! 140:
! 141: /* entity stack when traversing entities content */
! 142: xmlNodePtr ent; /* Current Entity Ref Node */
! 143: int entNr; /* Depth of the entities stack */
! 144: int entMax; /* Max depth of the entities stack */
! 145: xmlNodePtr *entTab; /* array of entities */
! 146:
! 147: /* error handling */
! 148: xmlTextReaderErrorFunc errorFunc; /* callback function */
! 149: void *errorFuncArg; /* callback function user argument */
! 150:
! 151: #ifdef LIBXML_SCHEMAS_ENABLED
! 152: /* Handling of RelaxNG validation */
! 153: xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
! 154: xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
! 155: int rngValidErrors;/* The number of errors detected */
! 156: xmlNodePtr rngFullNode; /* the node if RNG not progressive */
! 157: /* Handling of Schemas validation */
! 158: xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
! 159: xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
! 160: int xsdPreserveCtxt; /* 1 if the context was provided by the user */
! 161: int xsdValidErrors;/* The number of errors detected */
! 162: xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
! 163: #endif
! 164: #ifdef LIBXML_XINCLUDE_ENABLED
! 165: /* Handling of XInclude processing */
! 166: int xinclude; /* is xinclude asked for */
! 167: const xmlChar * xinclude_name; /* the xinclude name from dict */
! 168: xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
! 169: int in_xinclude; /* counts for xinclude */
! 170: #endif
! 171: #ifdef LIBXML_PATTERN_ENABLED
! 172: int patternNr; /* number of preserve patterns */
! 173: int patternMax; /* max preserve patterns */
! 174: xmlPatternPtr *patternTab; /* array of preserve patterns */
! 175: #endif
! 176: int preserves; /* level of preserves */
! 177: int parserFlags; /* the set of options set */
! 178: /* Structured error handling */
! 179: xmlStructuredErrorFunc sErrorFunc; /* callback function */
! 180: };
! 181:
! 182: #define NODE_IS_EMPTY 0x1
! 183: #define NODE_IS_PRESERVED 0x2
! 184: #define NODE_IS_SPRESERVED 0x4
! 185:
! 186: /**
! 187: * CONSTSTR:
! 188: *
! 189: * Macro used to return an interned string
! 190: */
! 191: #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
! 192: #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
! 193:
! 194: static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
! 195: static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
! 196:
! 197: /************************************************************************
! 198: * *
! 199: * Our own version of the freeing routines as we recycle nodes *
! 200: * *
! 201: ************************************************************************/
! 202: /**
! 203: * DICT_FREE:
! 204: * @str: a string
! 205: *
! 206: * Free a string if it is not owned by the "dict" dictionnary in the
! 207: * current scope
! 208: */
! 209: #define DICT_FREE(str) \
! 210: if ((str) && ((!dict) || \
! 211: (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
! 212: xmlFree((char *)(str));
! 213:
! 214: static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
! 215: static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
! 216:
! 217: /**
! 218: * xmlFreeID:
! 219: * @not: A id
! 220: *
! 221: * Deallocate the memory used by an id definition
! 222: */
! 223: static void
! 224: xmlFreeID(xmlIDPtr id) {
! 225: xmlDictPtr dict = NULL;
! 226:
! 227: if (id == NULL) return;
! 228:
! 229: if (id->doc != NULL)
! 230: dict = id->doc->dict;
! 231:
! 232: if (id->value != NULL)
! 233: DICT_FREE(id->value)
! 234: xmlFree(id);
! 235: }
! 236:
! 237: /**
! 238: * xmlTextReaderRemoveID:
! 239: * @doc: the document
! 240: * @attr: the attribute
! 241: *
! 242: * Remove the given attribute from the ID table maintained internally.
! 243: *
! 244: * Returns -1 if the lookup failed and 0 otherwise
! 245: */
! 246: static int
! 247: xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
! 248: xmlIDTablePtr table;
! 249: xmlIDPtr id;
! 250: xmlChar *ID;
! 251:
! 252: if (doc == NULL) return(-1);
! 253: if (attr == NULL) return(-1);
! 254: table = (xmlIDTablePtr) doc->ids;
! 255: if (table == NULL)
! 256: return(-1);
! 257:
! 258: ID = xmlNodeListGetString(doc, attr->children, 1);
! 259: if (ID == NULL)
! 260: return(-1);
! 261: id = xmlHashLookup(table, ID);
! 262: xmlFree(ID);
! 263: if (id == NULL || id->attr != attr) {
! 264: return(-1);
! 265: }
! 266: id->name = attr->name;
! 267: id->attr = NULL;
! 268: return(0);
! 269: }
! 270:
! 271: /**
! 272: * xmlTextReaderFreeProp:
! 273: * @reader: the xmlTextReaderPtr used
! 274: * @cur: the node
! 275: *
! 276: * Free a node.
! 277: */
! 278: static void
! 279: xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
! 280: xmlDictPtr dict;
! 281:
! 282: dict = reader->ctxt->dict;
! 283: if (cur == NULL) return;
! 284:
! 285: if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
! 286: xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
! 287:
! 288: /* Check for ID removal -> leading to invalid references ! */
! 289: if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
! 290: ((cur->parent->doc->intSubset != NULL) ||
! 291: (cur->parent->doc->extSubset != NULL))) {
! 292: if (xmlIsID(cur->parent->doc, cur->parent, cur))
! 293: xmlTextReaderRemoveID(cur->parent->doc, cur);
! 294: }
! 295: if (cur->children != NULL)
! 296: xmlTextReaderFreeNodeList(reader, cur->children);
! 297:
! 298: DICT_FREE(cur->name);
! 299: if ((reader != NULL) && (reader->ctxt != NULL) &&
! 300: (reader->ctxt->freeAttrsNr < 100)) {
! 301: cur->next = reader->ctxt->freeAttrs;
! 302: reader->ctxt->freeAttrs = cur;
! 303: reader->ctxt->freeAttrsNr++;
! 304: } else {
! 305: xmlFree(cur);
! 306: }
! 307: }
! 308:
! 309: /**
! 310: * xmlTextReaderFreePropList:
! 311: * @reader: the xmlTextReaderPtr used
! 312: * @cur: the first property in the list
! 313: *
! 314: * Free a property and all its siblings, all the children are freed too.
! 315: */
! 316: static void
! 317: xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
! 318: xmlAttrPtr next;
! 319: if (cur == NULL) return;
! 320: while (cur != NULL) {
! 321: next = cur->next;
! 322: xmlTextReaderFreeProp(reader, cur);
! 323: cur = next;
! 324: }
! 325: }
! 326:
! 327: /**
! 328: * xmlTextReaderFreeNodeList:
! 329: * @reader: the xmlTextReaderPtr used
! 330: * @cur: the first node in the list
! 331: *
! 332: * Free a node and all its siblings, this is a recursive behaviour, all
! 333: * the children are freed too.
! 334: */
! 335: static void
! 336: xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
! 337: xmlNodePtr next;
! 338: xmlDictPtr dict;
! 339:
! 340: dict = reader->ctxt->dict;
! 341: if (cur == NULL) return;
! 342: if (cur->type == XML_NAMESPACE_DECL) {
! 343: xmlFreeNsList((xmlNsPtr) cur);
! 344: return;
! 345: }
! 346: if ((cur->type == XML_DOCUMENT_NODE) ||
! 347: (cur->type == XML_HTML_DOCUMENT_NODE)) {
! 348: xmlFreeDoc((xmlDocPtr) cur);
! 349: return;
! 350: }
! 351: while (cur != NULL) {
! 352: next = cur->next;
! 353: /* unroll to speed up freeing the document */
! 354: if (cur->type != XML_DTD_NODE) {
! 355:
! 356: if ((cur->children != NULL) &&
! 357: (cur->type != XML_ENTITY_REF_NODE)) {
! 358: if (cur->children->parent == cur)
! 359: xmlTextReaderFreeNodeList(reader, cur->children);
! 360: cur->children = NULL;
! 361: }
! 362:
! 363: if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
! 364: xmlDeregisterNodeDefaultValue(cur);
! 365:
! 366: if (((cur->type == XML_ELEMENT_NODE) ||
! 367: (cur->type == XML_XINCLUDE_START) ||
! 368: (cur->type == XML_XINCLUDE_END)) &&
! 369: (cur->properties != NULL))
! 370: xmlTextReaderFreePropList(reader, cur->properties);
! 371: if ((cur->content != (xmlChar *) &(cur->properties)) &&
! 372: (cur->type != XML_ELEMENT_NODE) &&
! 373: (cur->type != XML_XINCLUDE_START) &&
! 374: (cur->type != XML_XINCLUDE_END) &&
! 375: (cur->type != XML_ENTITY_REF_NODE)) {
! 376: DICT_FREE(cur->content);
! 377: }
! 378: if (((cur->type == XML_ELEMENT_NODE) ||
! 379: (cur->type == XML_XINCLUDE_START) ||
! 380: (cur->type == XML_XINCLUDE_END)) &&
! 381: (cur->nsDef != NULL))
! 382: xmlFreeNsList(cur->nsDef);
! 383:
! 384: /*
! 385: * we don't free element names here they are interned now
! 386: */
! 387: if ((cur->type != XML_TEXT_NODE) &&
! 388: (cur->type != XML_COMMENT_NODE))
! 389: DICT_FREE(cur->name);
! 390: if (((cur->type == XML_ELEMENT_NODE) ||
! 391: (cur->type == XML_TEXT_NODE)) &&
! 392: (reader != NULL) && (reader->ctxt != NULL) &&
! 393: (reader->ctxt->freeElemsNr < 100)) {
! 394: cur->next = reader->ctxt->freeElems;
! 395: reader->ctxt->freeElems = cur;
! 396: reader->ctxt->freeElemsNr++;
! 397: } else {
! 398: xmlFree(cur);
! 399: }
! 400: }
! 401: cur = next;
! 402: }
! 403: }
! 404:
! 405: /**
! 406: * xmlTextReaderFreeNode:
! 407: * @reader: the xmlTextReaderPtr used
! 408: * @cur: the node
! 409: *
! 410: * Free a node, this is a recursive behaviour, all the children are freed too.
! 411: * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
! 412: */
! 413: static void
! 414: xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
! 415: xmlDictPtr dict;
! 416:
! 417: dict = reader->ctxt->dict;
! 418: if (cur->type == XML_DTD_NODE) {
! 419: xmlFreeDtd((xmlDtdPtr) cur);
! 420: return;
! 421: }
! 422: if (cur->type == XML_NAMESPACE_DECL) {
! 423: xmlFreeNs((xmlNsPtr) cur);
! 424: return;
! 425: }
! 426: if (cur->type == XML_ATTRIBUTE_NODE) {
! 427: xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
! 428: return;
! 429: }
! 430:
! 431: if ((cur->children != NULL) &&
! 432: (cur->type != XML_ENTITY_REF_NODE)) {
! 433: if (cur->children->parent == cur)
! 434: xmlTextReaderFreeNodeList(reader, cur->children);
! 435: cur->children = NULL;
! 436: }
! 437:
! 438: if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
! 439: xmlDeregisterNodeDefaultValue(cur);
! 440:
! 441: if (((cur->type == XML_ELEMENT_NODE) ||
! 442: (cur->type == XML_XINCLUDE_START) ||
! 443: (cur->type == XML_XINCLUDE_END)) &&
! 444: (cur->properties != NULL))
! 445: xmlTextReaderFreePropList(reader, cur->properties);
! 446: if ((cur->content != (xmlChar *) &(cur->properties)) &&
! 447: (cur->type != XML_ELEMENT_NODE) &&
! 448: (cur->type != XML_XINCLUDE_START) &&
! 449: (cur->type != XML_XINCLUDE_END) &&
! 450: (cur->type != XML_ENTITY_REF_NODE)) {
! 451: DICT_FREE(cur->content);
! 452: }
! 453: if (((cur->type == XML_ELEMENT_NODE) ||
! 454: (cur->type == XML_XINCLUDE_START) ||
! 455: (cur->type == XML_XINCLUDE_END)) &&
! 456: (cur->nsDef != NULL))
! 457: xmlFreeNsList(cur->nsDef);
! 458:
! 459: /*
! 460: * we don't free names here they are interned now
! 461: */
! 462: if ((cur->type != XML_TEXT_NODE) &&
! 463: (cur->type != XML_COMMENT_NODE))
! 464: DICT_FREE(cur->name);
! 465:
! 466: if (((cur->type == XML_ELEMENT_NODE) ||
! 467: (cur->type == XML_TEXT_NODE)) &&
! 468: (reader != NULL) && (reader->ctxt != NULL) &&
! 469: (reader->ctxt->freeElemsNr < 100)) {
! 470: cur->next = reader->ctxt->freeElems;
! 471: reader->ctxt->freeElems = cur;
! 472: reader->ctxt->freeElemsNr++;
! 473: } else {
! 474: xmlFree(cur);
! 475: }
! 476: }
! 477:
! 478: /**
! 479: * xmlTextReaderFreeIDTable:
! 480: * @table: An id table
! 481: *
! 482: * Deallocate the memory used by an ID hash table.
! 483: */
! 484: static void
! 485: xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
! 486: xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
! 487: }
! 488:
! 489: /**
! 490: * xmlTextReaderFreeDoc:
! 491: * @reader: the xmlTextReaderPtr used
! 492: * @cur: pointer to the document
! 493: *
! 494: * Free up all the structures used by a document, tree included.
! 495: */
! 496: static void
! 497: xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
! 498: xmlDtdPtr extSubset, intSubset;
! 499:
! 500: if (cur == NULL) return;
! 501:
! 502: if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
! 503: xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
! 504:
! 505: /*
! 506: * Do this before freeing the children list to avoid ID lookups
! 507: */
! 508: if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
! 509: cur->ids = NULL;
! 510: if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
! 511: cur->refs = NULL;
! 512: extSubset = cur->extSubset;
! 513: intSubset = cur->intSubset;
! 514: if (intSubset == extSubset)
! 515: extSubset = NULL;
! 516: if (extSubset != NULL) {
! 517: xmlUnlinkNode((xmlNodePtr) cur->extSubset);
! 518: cur->extSubset = NULL;
! 519: xmlFreeDtd(extSubset);
! 520: }
! 521: if (intSubset != NULL) {
! 522: xmlUnlinkNode((xmlNodePtr) cur->intSubset);
! 523: cur->intSubset = NULL;
! 524: xmlFreeDtd(intSubset);
! 525: }
! 526:
! 527: if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
! 528:
! 529: if (cur->version != NULL) xmlFree((char *) cur->version);
! 530: if (cur->name != NULL) xmlFree((char *) cur->name);
! 531: if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
! 532: if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
! 533: if (cur->URL != NULL) xmlFree((char *) cur->URL);
! 534: if (cur->dict != NULL) xmlDictFree(cur->dict);
! 535:
! 536: xmlFree(cur);
! 537: }
! 538:
! 539: /************************************************************************
! 540: * *
! 541: * The reader core parser *
! 542: * *
! 543: ************************************************************************/
! 544: #ifdef DEBUG_READER
! 545: static void
! 546: xmlTextReaderDebug(xmlTextReaderPtr reader) {
! 547: if ((reader == NULL) || (reader->ctxt == NULL)) {
! 548: fprintf(stderr, "xmlTextReader NULL\n");
! 549: return;
! 550: }
! 551: fprintf(stderr, "xmlTextReader: state %d depth %d ",
! 552: reader->state, reader->depth);
! 553: if (reader->node == NULL) {
! 554: fprintf(stderr, "node = NULL\n");
! 555: } else {
! 556: fprintf(stderr, "node %s\n", reader->node->name);
! 557: }
! 558: fprintf(stderr, " input: base %d, cur %d, depth %d: ",
! 559: reader->base, reader->cur, reader->ctxt->nodeNr);
! 560: if (reader->input->buffer == NULL) {
! 561: fprintf(stderr, "buffer is NULL\n");
! 562: } else {
! 563: #ifdef LIBXML_DEBUG_ENABLED
! 564: xmlDebugDumpString(stderr,
! 565: &reader->input->buffer->content[reader->cur]);
! 566: #endif
! 567: fprintf(stderr, "\n");
! 568: }
! 569: }
! 570: #endif
! 571:
! 572: /**
! 573: * xmlTextReaderEntPush:
! 574: * @reader: the xmlTextReaderPtr used
! 575: * @value: the entity reference node
! 576: *
! 577: * Pushes a new entity reference node on top of the entities stack
! 578: *
! 579: * Returns 0 in case of error, the index in the stack otherwise
! 580: */
! 581: static int
! 582: xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
! 583: {
! 584: if (reader->entMax <= 0) {
! 585: reader->entMax = 10;
! 586: reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
! 587: sizeof(reader->entTab[0]));
! 588: if (reader->entTab == NULL) {
! 589: xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
! 590: return (0);
! 591: }
! 592: }
! 593: if (reader->entNr >= reader->entMax) {
! 594: reader->entMax *= 2;
! 595: reader->entTab =
! 596: (xmlNodePtr *) xmlRealloc(reader->entTab,
! 597: reader->entMax *
! 598: sizeof(reader->entTab[0]));
! 599: if (reader->entTab == NULL) {
! 600: xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
! 601: return (0);
! 602: }
! 603: }
! 604: reader->entTab[reader->entNr] = value;
! 605: reader->ent = value;
! 606: return (reader->entNr++);
! 607: }
! 608:
! 609: /**
! 610: * xmlTextReaderEntPop:
! 611: * @reader: the xmlTextReaderPtr used
! 612: *
! 613: * Pops the top element entity from the entities stack
! 614: *
! 615: * Returns the entity just removed
! 616: */
! 617: static xmlNodePtr
! 618: xmlTextReaderEntPop(xmlTextReaderPtr reader)
! 619: {
! 620: xmlNodePtr ret;
! 621:
! 622: if (reader->entNr <= 0)
! 623: return (NULL);
! 624: reader->entNr--;
! 625: if (reader->entNr > 0)
! 626: reader->ent = reader->entTab[reader->entNr - 1];
! 627: else
! 628: reader->ent = NULL;
! 629: ret = reader->entTab[reader->entNr];
! 630: reader->entTab[reader->entNr] = NULL;
! 631: return (ret);
! 632: }
! 633:
! 634: /**
! 635: * xmlTextReaderStartElement:
! 636: * @ctx: the user data (XML parser context)
! 637: * @fullname: The element name, including namespace prefix
! 638: * @atts: An array of name/value attributes pairs, NULL terminated
! 639: *
! 640: * called when an opening tag has been processed.
! 641: */
! 642: static void
! 643: xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
! 644: const xmlChar **atts) {
! 645: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
! 646: xmlTextReaderPtr reader = ctxt->_private;
! 647:
! 648: #ifdef DEBUG_CALLBACKS
! 649: printf("xmlTextReaderStartElement(%s)\n", fullname);
! 650: #endif
! 651: if ((reader != NULL) && (reader->startElement != NULL)) {
! 652: reader->startElement(ctx, fullname, atts);
! 653: if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
! 654: (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
! 655: (ctxt->input->cur[1] == '>'))
! 656: ctxt->node->extra = NODE_IS_EMPTY;
! 657: }
! 658: if (reader != NULL)
! 659: reader->state = XML_TEXTREADER_ELEMENT;
! 660: }
! 661:
! 662: /**
! 663: * xmlTextReaderEndElement:
! 664: * @ctx: the user data (XML parser context)
! 665: * @fullname: The element name, including namespace prefix
! 666: *
! 667: * called when an ending tag has been processed.
! 668: */
! 669: static void
! 670: xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
! 671: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
! 672: xmlTextReaderPtr reader = ctxt->_private;
! 673:
! 674: #ifdef DEBUG_CALLBACKS
! 675: printf("xmlTextReaderEndElement(%s)\n", fullname);
! 676: #endif
! 677: if ((reader != NULL) && (reader->endElement != NULL)) {
! 678: reader->endElement(ctx, fullname);
! 679: }
! 680: }
! 681:
! 682: /**
! 683: * xmlTextReaderStartElementNs:
! 684: * @ctx: the user data (XML parser context)
! 685: * @localname: the local name of the element
! 686: * @prefix: the element namespace prefix if available
! 687: * @URI: the element namespace name if available
! 688: * @nb_namespaces: number of namespace definitions on that node
! 689: * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
! 690: * @nb_attributes: the number of attributes on that node
! 691: * nb_defaulted: the number of defaulted attributes.
! 692: * @attributes: pointer to the array of (localname/prefix/URI/value/end)
! 693: * attribute values.
! 694: *
! 695: * called when an opening tag has been processed.
! 696: */
! 697: static void
! 698: xmlTextReaderStartElementNs(void *ctx,
! 699: const xmlChar *localname,
! 700: const xmlChar *prefix,
! 701: const xmlChar *URI,
! 702: int nb_namespaces,
! 703: const xmlChar **namespaces,
! 704: int nb_attributes,
! 705: int nb_defaulted,
! 706: const xmlChar **attributes)
! 707: {
! 708: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
! 709: xmlTextReaderPtr reader = ctxt->_private;
! 710:
! 711: #ifdef DEBUG_CALLBACKS
! 712: printf("xmlTextReaderStartElementNs(%s)\n", localname);
! 713: #endif
! 714: if ((reader != NULL) && (reader->startElementNs != NULL)) {
! 715: reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
! 716: namespaces, nb_attributes, nb_defaulted,
! 717: attributes);
! 718: if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
! 719: (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
! 720: (ctxt->input->cur[1] == '>'))
! 721: ctxt->node->extra = NODE_IS_EMPTY;
! 722: }
! 723: if (reader != NULL)
! 724: reader->state = XML_TEXTREADER_ELEMENT;
! 725: }
! 726:
! 727: /**
! 728: * xmlTextReaderEndElementNs:
! 729: * @ctx: the user data (XML parser context)
! 730: * @localname: the local name of the element
! 731: * @prefix: the element namespace prefix if available
! 732: * @URI: the element namespace name if available
! 733: *
! 734: * called when an ending tag has been processed.
! 735: */
! 736: static void
! 737: xmlTextReaderEndElementNs(void *ctx,
! 738: const xmlChar * localname,
! 739: const xmlChar * prefix,
! 740: const xmlChar * URI)
! 741: {
! 742: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
! 743: xmlTextReaderPtr reader = ctxt->_private;
! 744:
! 745: #ifdef DEBUG_CALLBACKS
! 746: printf("xmlTextReaderEndElementNs(%s)\n", localname);
! 747: #endif
! 748: if ((reader != NULL) && (reader->endElementNs != NULL)) {
! 749: reader->endElementNs(ctx, localname, prefix, URI);
! 750: }
! 751: }
! 752:
! 753:
! 754: /**
! 755: * xmlTextReaderCharacters:
! 756: * @ctx: the user data (XML parser context)
! 757: * @ch: a xmlChar string
! 758: * @len: the number of xmlChar
! 759: *
! 760: * receiving some chars from the parser.
! 761: */
! 762: static void
! 763: xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
! 764: {
! 765: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
! 766: xmlTextReaderPtr reader = ctxt->_private;
! 767:
! 768: #ifdef DEBUG_CALLBACKS
! 769: printf("xmlTextReaderCharacters()\n");
! 770: #endif
! 771: if ((reader != NULL) && (reader->characters != NULL)) {
! 772: reader->characters(ctx, ch, len);
! 773: }
! 774: }
! 775:
! 776: /**
! 777: * xmlTextReaderCDataBlock:
! 778: * @ctx: the user data (XML parser context)
! 779: * @value: The pcdata content
! 780: * @len: the block length
! 781: *
! 782: * called when a pcdata block has been parsed
! 783: */
! 784: static void
! 785: xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
! 786: {
! 787: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
! 788: xmlTextReaderPtr reader = ctxt->_private;
! 789:
! 790: #ifdef DEBUG_CALLBACKS
! 791: printf("xmlTextReaderCDataBlock()\n");
! 792: #endif
! 793: if ((reader != NULL) && (reader->cdataBlock != NULL)) {
! 794: reader->cdataBlock(ctx, ch, len);
! 795: }
! 796: }
! 797:
! 798: /**
! 799: * xmlTextReaderPushData:
! 800: * @reader: the xmlTextReaderPtr used
! 801: *
! 802: * Push data down the progressive parser until a significant callback
! 803: * got raised.
! 804: *
! 805: * Returns -1 in case of failure, 0 otherwise
! 806: */
! 807: static int
! 808: xmlTextReaderPushData(xmlTextReaderPtr reader) {
! 809: xmlBufferPtr inbuf;
! 810: int val, s;
! 811: xmlTextReaderState oldstate;
! 812:
! 813: if ((reader->input == NULL) || (reader->input->buffer == NULL))
! 814: return(-1);
! 815:
! 816: oldstate = reader->state;
! 817: reader->state = XML_TEXTREADER_NONE;
! 818: inbuf = reader->input->buffer;
! 819:
! 820: while (reader->state == XML_TEXTREADER_NONE) {
! 821: if (inbuf->use < reader->cur + CHUNK_SIZE) {
! 822: /*
! 823: * Refill the buffer unless we are at the end of the stream
! 824: */
! 825: if (reader->mode != XML_TEXTREADER_MODE_EOF) {
! 826: val = xmlParserInputBufferRead(reader->input, 4096);
! 827: if ((val == 0) &&
! 828: (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
! 829: if (inbuf->use == reader->cur) {
! 830: reader->mode = XML_TEXTREADER_MODE_EOF;
! 831: reader->state = oldstate;
! 832: }
! 833: } else if (val < 0) {
! 834: reader->mode = XML_TEXTREADER_MODE_EOF;
! 835: reader->state = oldstate;
! 836: if ((oldstate != XML_TEXTREADER_START) ||
! 837: (reader->ctxt->myDoc != NULL))
! 838: return(val);
! 839: } else if (val == 0) {
! 840: /* mark the end of the stream and process the remains */
! 841: reader->mode = XML_TEXTREADER_MODE_EOF;
! 842: break;
! 843: }
! 844:
! 845: } else
! 846: break;
! 847: }
! 848: /*
! 849: * parse by block of CHUNK_SIZE bytes, various tests show that
! 850: * it's the best tradeoff at least on a 1.2GH Duron
! 851: */
! 852: if (inbuf->use >= reader->cur + CHUNK_SIZE) {
! 853: val = xmlParseChunk(reader->ctxt,
! 854: (const char *) &inbuf->content[reader->cur],
! 855: CHUNK_SIZE, 0);
! 856: reader->cur += CHUNK_SIZE;
! 857: if ((val != 0) || (reader->ctxt->wellFormed == 0))
! 858: return(-1);
! 859: } else {
! 860: s = inbuf->use - reader->cur;
! 861: val = xmlParseChunk(reader->ctxt,
! 862: (const char *) &inbuf->content[reader->cur],
! 863: s, 0);
! 864: reader->cur += s;
! 865: if ((val != 0) || (reader->ctxt->wellFormed == 0))
! 866: return(-1);
! 867: break;
! 868: }
! 869: }
! 870:
! 871: /*
! 872: * Discard the consumed input when needed and possible
! 873: */
! 874: if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
! 875: if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
! 876: if ((reader->cur >= 4096) &&
! 877: (inbuf->use - reader->cur <= CHUNK_SIZE)) {
! 878: val = xmlBufferShrink(inbuf, reader->cur);
! 879: if (val >= 0) {
! 880: reader->cur -= val;
! 881: }
! 882: }
! 883: }
! 884: }
! 885:
! 886: /*
! 887: * At the end of the stream signal that the work is done to the Push
! 888: * parser.
! 889: */
! 890: else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
! 891: if (reader->state != XML_TEXTREADER_DONE) {
! 892: s = inbuf->use - reader->cur;
! 893: val = xmlParseChunk(reader->ctxt,
! 894: (const char *) &inbuf->content[reader->cur],
! 895: s, 1);
! 896: reader->cur = inbuf->use;
! 897: reader->state = XML_TEXTREADER_DONE;
! 898: if ((val != 0) || (reader->ctxt->wellFormed == 0))
! 899: return(-1);
! 900: }
! 901: }
! 902: reader->state = oldstate;
! 903: return(0);
! 904: }
! 905:
! 906: #ifdef LIBXML_REGEXP_ENABLED
! 907: /**
! 908: * xmlTextReaderValidatePush:
! 909: * @reader: the xmlTextReaderPtr used
! 910: *
! 911: * Push the current node for validation
! 912: */
! 913: static void
! 914: xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
! 915: xmlNodePtr node = reader->node;
! 916:
! 917: #ifdef LIBXML_VALID_ENABLED
! 918: if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
! 919: (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
! 920: if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
! 921: reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
! 922: reader->ctxt->myDoc, node, node->name);
! 923: } else {
! 924: /* TODO use the BuildQName interface */
! 925: xmlChar *qname;
! 926:
! 927: qname = xmlStrdup(node->ns->prefix);
! 928: qname = xmlStrcat(qname, BAD_CAST ":");
! 929: qname = xmlStrcat(qname, node->name);
! 930: reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
! 931: reader->ctxt->myDoc, node, qname);
! 932: if (qname != NULL)
! 933: xmlFree(qname);
! 934: }
! 935: }
! 936: #endif /* LIBXML_VALID_ENABLED */
! 937: #ifdef LIBXML_SCHEMAS_ENABLED
! 938: if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
! 939: (reader->rngValidCtxt != NULL)) {
! 940: int ret;
! 941:
! 942: if (reader->rngFullNode != NULL) return;
! 943: ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
! 944: reader->ctxt->myDoc,
! 945: node);
! 946: if (ret == 0) {
! 947: /*
! 948: * this element requires a full tree
! 949: */
! 950: node = xmlTextReaderExpand(reader);
! 951: if (node == NULL) {
! 952: printf("Expand failed !\n");
! 953: ret = -1;
! 954: } else {
! 955: ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
! 956: reader->ctxt->myDoc,
! 957: node);
! 958: reader->rngFullNode = node;
! 959: }
! 960: }
! 961: if (ret != 1)
! 962: reader->rngValidErrors++;
! 963: }
! 964: #endif
! 965: }
! 966:
! 967: /**
! 968: * xmlTextReaderValidateCData:
! 969: * @reader: the xmlTextReaderPtr used
! 970: * @data: pointer to the CData
! 971: * @len: lenght of the CData block in bytes.
! 972: *
! 973: * Push some CData for validation
! 974: */
! 975: static void
! 976: xmlTextReaderValidateCData(xmlTextReaderPtr reader,
! 977: const xmlChar *data, int len) {
! 978: #ifdef LIBXML_VALID_ENABLED
! 979: if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
! 980: (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
! 981: reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
! 982: data, len);
! 983: }
! 984: #endif /* LIBXML_VALID_ENABLED */
! 985: #ifdef LIBXML_SCHEMAS_ENABLED
! 986: if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
! 987: (reader->rngValidCtxt != NULL)) {
! 988: int ret;
! 989:
! 990: if (reader->rngFullNode != NULL) return;
! 991: ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
! 992: if (ret != 1)
! 993: reader->rngValidErrors++;
! 994: }
! 995: #endif
! 996: }
! 997:
! 998: /**
! 999: * xmlTextReaderValidatePop:
! 1000: * @reader: the xmlTextReaderPtr used
! 1001: *
! 1002: * Pop the current node from validation
! 1003: */
! 1004: static void
! 1005: xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
! 1006: xmlNodePtr node = reader->node;
! 1007:
! 1008: #ifdef LIBXML_VALID_ENABLED
! 1009: if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
! 1010: (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
! 1011: if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
! 1012: reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
! 1013: reader->ctxt->myDoc, node, node->name);
! 1014: } else {
! 1015: /* TODO use the BuildQName interface */
! 1016: xmlChar *qname;
! 1017:
! 1018: qname = xmlStrdup(node->ns->prefix);
! 1019: qname = xmlStrcat(qname, BAD_CAST ":");
! 1020: qname = xmlStrcat(qname, node->name);
! 1021: reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
! 1022: reader->ctxt->myDoc, node, qname);
! 1023: if (qname != NULL)
! 1024: xmlFree(qname);
! 1025: }
! 1026: }
! 1027: #endif /* LIBXML_VALID_ENABLED */
! 1028: #ifdef LIBXML_SCHEMAS_ENABLED
! 1029: if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
! 1030: (reader->rngValidCtxt != NULL)) {
! 1031: int ret;
! 1032:
! 1033: if (reader->rngFullNode != NULL) {
! 1034: if (node == reader->rngFullNode)
! 1035: reader->rngFullNode = NULL;
! 1036: return;
! 1037: }
! 1038: ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
! 1039: reader->ctxt->myDoc,
! 1040: node);
! 1041: if (ret != 1)
! 1042: reader->rngValidErrors++;
! 1043: }
! 1044: #endif
! 1045: }
! 1046:
! 1047: /**
! 1048: * xmlTextReaderValidateEntity:
! 1049: * @reader: the xmlTextReaderPtr used
! 1050: *
! 1051: * Handle the validation when an entity reference is encountered and
! 1052: * entity substitution is not activated. As a result the parser interface
! 1053: * must walk through the entity and do the validation calls
! 1054: */
! 1055: static void
! 1056: xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
! 1057: xmlNodePtr oldnode = reader->node;
! 1058: xmlNodePtr node = reader->node;
! 1059: xmlParserCtxtPtr ctxt = reader->ctxt;
! 1060:
! 1061: do {
! 1062: if (node->type == XML_ENTITY_REF_NODE) {
! 1063: /*
! 1064: * Case where the underlying tree is not availble, lookup the entity
! 1065: * and walk it.
! 1066: */
! 1067: if ((node->children == NULL) && (ctxt->sax != NULL) &&
! 1068: (ctxt->sax->getEntity != NULL)) {
! 1069: node->children = (xmlNodePtr)
! 1070: ctxt->sax->getEntity(ctxt, node->name);
! 1071: }
! 1072:
! 1073: if ((node->children != NULL) &&
! 1074: (node->children->type == XML_ENTITY_DECL) &&
! 1075: (node->children->children != NULL)) {
! 1076: xmlTextReaderEntPush(reader, node);
! 1077: node = node->children->children;
! 1078: continue;
! 1079: } else {
! 1080: /*
! 1081: * The error has probably be raised already.
! 1082: */
! 1083: if (node == oldnode)
! 1084: break;
! 1085: node = node->next;
! 1086: }
! 1087: #ifdef LIBXML_REGEXP_ENABLED
! 1088: } else if (node->type == XML_ELEMENT_NODE) {
! 1089: reader->node = node;
! 1090: xmlTextReaderValidatePush(reader);
! 1091: } else if ((node->type == XML_TEXT_NODE) ||
! 1092: (node->type == XML_CDATA_SECTION_NODE)) {
! 1093: xmlTextReaderValidateCData(reader, node->content,
! 1094: xmlStrlen(node->content));
! 1095: #endif
! 1096: }
! 1097:
! 1098: /*
! 1099: * go to next node
! 1100: */
! 1101: if (node->children != NULL) {
! 1102: node = node->children;
! 1103: continue;
! 1104: } else if (node->type == XML_ELEMENT_NODE) {
! 1105: xmlTextReaderValidatePop(reader);
! 1106: }
! 1107: if (node->next != NULL) {
! 1108: node = node->next;
! 1109: continue;
! 1110: }
! 1111: do {
! 1112: node = node->parent;
! 1113: if (node->type == XML_ELEMENT_NODE) {
! 1114: xmlNodePtr tmp;
! 1115: if (reader->entNr == 0) {
! 1116: while ((tmp = node->last) != NULL) {
! 1117: if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
! 1118: xmlUnlinkNode(tmp);
! 1119: xmlTextReaderFreeNode(reader, tmp);
! 1120: } else
! 1121: break;
! 1122: }
! 1123: }
! 1124: reader->node = node;
! 1125: xmlTextReaderValidatePop(reader);
! 1126: }
! 1127: if ((node->type == XML_ENTITY_DECL) &&
! 1128: (reader->ent != NULL) && (reader->ent->children == node)) {
! 1129: node = xmlTextReaderEntPop(reader);
! 1130: }
! 1131: if (node == oldnode)
! 1132: break;
! 1133: if (node->next != NULL) {
! 1134: node = node->next;
! 1135: break;
! 1136: }
! 1137: } while ((node != NULL) && (node != oldnode));
! 1138: } while ((node != NULL) && (node != oldnode));
! 1139: reader->node = oldnode;
! 1140: }
! 1141: #endif /* LIBXML_REGEXP_ENABLED */
! 1142:
! 1143:
! 1144: /**
! 1145: * xmlTextReaderGetSuccessor:
! 1146: * @cur: the current node
! 1147: *
! 1148: * Get the successor of a node if available.
! 1149: *
! 1150: * Returns the successor node or NULL
! 1151: */
! 1152: static xmlNodePtr
! 1153: xmlTextReaderGetSuccessor(xmlNodePtr cur) {
! 1154: if (cur == NULL) return(NULL) ; /* ERROR */
! 1155: if (cur->next != NULL) return(cur->next) ;
! 1156: do {
! 1157: cur = cur->parent;
! 1158: if (cur == NULL) break;
! 1159: if (cur->next != NULL) return(cur->next);
! 1160: } while (cur != NULL);
! 1161: return(cur);
! 1162: }
! 1163:
! 1164: /**
! 1165: * xmlTextReaderDoExpand:
! 1166: * @reader: the xmlTextReaderPtr used
! 1167: *
! 1168: * Makes sure that the current node is fully read as well as all its
! 1169: * descendant. It means the full DOM subtree must be available at the
! 1170: * end of the call.
! 1171: *
! 1172: * Returns 1 if the node was expanded successfully, 0 if there is no more
! 1173: * nodes to read, or -1 in case of error
! 1174: */
! 1175: static int
! 1176: xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
! 1177: int val;
! 1178:
! 1179: if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
! 1180: return(-1);
! 1181: do {
! 1182: if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
! 1183:
! 1184: if (xmlTextReaderGetSuccessor(reader->node) != NULL)
! 1185: return(1);
! 1186: if (reader->ctxt->nodeNr < reader->depth)
! 1187: return(1);
! 1188: if (reader->mode == XML_TEXTREADER_MODE_EOF)
! 1189: return(1);
! 1190: val = xmlTextReaderPushData(reader);
! 1191: if (val < 0){
! 1192: reader->mode = XML_TEXTREADER_MODE_ERROR;
! 1193: return(-1);
! 1194: }
! 1195: } while(reader->mode != XML_TEXTREADER_MODE_EOF);
! 1196: return(1);
! 1197: }
! 1198:
! 1199: /**
! 1200: * xmlTextReaderCollectSiblings:
! 1201: * @node: the first child
! 1202: *
! 1203: * Traverse depth-first through all sibling nodes and their children
! 1204: * nodes and concatenate their content. This is an auxiliary function
! 1205: * to xmlTextReaderReadString.
! 1206: *
! 1207: * Returns a string containing the content, or NULL in case of error.
! 1208: */
! 1209: static xmlChar *
! 1210: xmlTextReaderCollectSiblings(xmlNodePtr node)
! 1211: {
! 1212: xmlBufferPtr buffer;
! 1213: xmlChar *ret;
! 1214:
! 1215: buffer = xmlBufferCreate();
! 1216: if (buffer == NULL)
! 1217: return NULL;
! 1218:
! 1219: for ( ; node != NULL; node = node->next) {
! 1220: switch (node->type) {
! 1221: case XML_TEXT_NODE:
! 1222: case XML_CDATA_SECTION_NODE:
! 1223: xmlBufferCat(buffer, node->content);
! 1224: break;
! 1225: case XML_ELEMENT_NODE: {
! 1226: xmlChar *tmp;
! 1227:
! 1228: tmp = xmlTextReaderCollectSiblings(node->children);
! 1229: xmlBufferCat(buffer, tmp);
! 1230: xmlFree(tmp);
! 1231: break;
! 1232: }
! 1233: default:
! 1234: break;
! 1235: }
! 1236: }
! 1237: ret = buffer->content;
! 1238: buffer->content = NULL;
! 1239: xmlBufferFree(buffer);
! 1240: return(ret);
! 1241: }
! 1242:
! 1243: /**
! 1244: * xmlTextReaderRead:
! 1245: * @reader: the xmlTextReaderPtr used
! 1246: *
! 1247: * Moves the position of the current instance to the next node in
! 1248: * the stream, exposing its properties.
! 1249: *
! 1250: * Returns 1 if the node was read successfully, 0 if there is no more
! 1251: * nodes to read, or -1 in case of error
! 1252: */
! 1253: int
! 1254: xmlTextReaderRead(xmlTextReaderPtr reader) {
! 1255: int val, olddepth = 0;
! 1256: xmlTextReaderState oldstate = XML_TEXTREADER_START;
! 1257: xmlNodePtr oldnode = NULL;
! 1258:
! 1259:
! 1260: if (reader == NULL)
! 1261: return(-1);
! 1262: reader->curnode = NULL;
! 1263: if (reader->doc != NULL)
! 1264: return(xmlTextReaderReadTree(reader));
! 1265: if (reader->ctxt == NULL)
! 1266: return(-1);
! 1267: if (reader->ctxt->wellFormed != 1)
! 1268: return(-1);
! 1269:
! 1270: #ifdef DEBUG_READER
! 1271: fprintf(stderr, "\nREAD ");
! 1272: DUMP_READER
! 1273: #endif
! 1274: if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
! 1275: reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
! 1276: /*
! 1277: * Initial state
! 1278: */
! 1279: do {
! 1280: val = xmlTextReaderPushData(reader);
! 1281: if (val < 0){
! 1282: reader->mode = XML_TEXTREADER_MODE_ERROR;
! 1283: reader->state = XML_TEXTREADER_ERROR;
! 1284: return(-1);
! 1285: }
! 1286: } while ((reader->ctxt->node == NULL) &&
! 1287: ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
! 1288: (reader->state != XML_TEXTREADER_DONE)));
! 1289: if (reader->ctxt->node == NULL) {
! 1290: if (reader->ctxt->myDoc != NULL) {
! 1291: reader->node = reader->ctxt->myDoc->children;
! 1292: }
! 1293: if (reader->node == NULL){
! 1294: reader->mode = XML_TEXTREADER_MODE_ERROR;
! 1295: reader->state = XML_TEXTREADER_ERROR;
! 1296: return(-1);
! 1297: }
! 1298: reader->state = XML_TEXTREADER_ELEMENT;
! 1299: } else {
! 1300: if (reader->ctxt->myDoc != NULL) {
! 1301: reader->node = reader->ctxt->myDoc->children;
! 1302: }
! 1303: if (reader->node == NULL)
! 1304: reader->node = reader->ctxt->nodeTab[0];
! 1305: reader->state = XML_TEXTREADER_ELEMENT;
! 1306: }
! 1307: reader->depth = 0;
! 1308: reader->ctxt->parseMode = XML_PARSE_READER;
! 1309: goto node_found;
! 1310: }
! 1311: oldstate = reader->state;
! 1312: olddepth = reader->ctxt->nodeNr;
! 1313: oldnode = reader->node;
! 1314:
! 1315: get_next_node:
! 1316: if (reader->node == NULL) {
! 1317: if (reader->mode == XML_TEXTREADER_MODE_EOF)
! 1318: return(0);
! 1319: else
! 1320: return(-1);
! 1321: }
! 1322:
! 1323: /*
! 1324: * If we are not backtracking on ancestors or examined nodes,
! 1325: * that the parser didn't finished or that we arent at the end
! 1326: * of stream, continue processing.
! 1327: */
! 1328: while ((reader->node != NULL) && (reader->node->next == NULL) &&
! 1329: (reader->ctxt->nodeNr == olddepth) &&
! 1330: ((oldstate == XML_TEXTREADER_BACKTRACK) ||
! 1331: (reader->node->children == NULL) ||
! 1332: (reader->node->type == XML_ENTITY_REF_NODE) ||
! 1333: ((reader->node->children != NULL) &&
! 1334: (reader->node->children->type == XML_TEXT_NODE) &&
! 1335: (reader->node->children->next == NULL)) ||
! 1336: (reader->node->type == XML_DTD_NODE) ||
! 1337: (reader->node->type == XML_DOCUMENT_NODE) ||
! 1338: (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
! 1339: ((reader->ctxt->node == NULL) ||
! 1340: (reader->ctxt->node == reader->node) ||
! 1341: (reader->ctxt->node == reader->node->parent)) &&
! 1342: (reader->ctxt->instate != XML_PARSER_EOF)) {
! 1343: val = xmlTextReaderPushData(reader);
! 1344: if (val < 0){
! 1345: reader->mode = XML_TEXTREADER_MODE_ERROR;
! 1346: reader->state = XML_TEXTREADER_ERROR;
! 1347: return(-1);
! 1348: }
! 1349: if (reader->node == NULL)
! 1350: goto node_end;
! 1351: }
! 1352: if (oldstate != XML_TEXTREADER_BACKTRACK) {
! 1353: if ((reader->node->children != NULL) &&
! 1354: (reader->node->type != XML_ENTITY_REF_NODE) &&
! 1355: (reader->node->type != XML_XINCLUDE_START) &&
! 1356: (reader->node->type != XML_DTD_NODE)) {
! 1357: reader->node = reader->node->children;
! 1358: reader->depth++;
! 1359: reader->state = XML_TEXTREADER_ELEMENT;
! 1360: goto node_found;
! 1361: }
! 1362: }
! 1363: if (reader->node->next != NULL) {
! 1364: if ((oldstate == XML_TEXTREADER_ELEMENT) &&
! 1365: (reader->node->type == XML_ELEMENT_NODE) &&
! 1366: (reader->node->children == NULL) &&
! 1367: ((reader->node->extra & NODE_IS_EMPTY) == 0)
! 1368: #ifdef LIBXML_XINCLUDE_ENABLED
! 1369: && (reader->in_xinclude <= 0)
! 1370: #endif
! 1371: ) {
! 1372: reader->state = XML_TEXTREADER_END;
! 1373: goto node_found;
! 1374: }
! 1375: #ifdef LIBXML_REGEXP_ENABLED
! 1376: if ((reader->validate) &&
! 1377: (reader->node->type == XML_ELEMENT_NODE))
! 1378: xmlTextReaderValidatePop(reader);
! 1379: #endif /* LIBXML_REGEXP_ENABLED */
! 1380: if ((reader->preserves > 0) &&
! 1381: (reader->node->extra & NODE_IS_SPRESERVED))
! 1382: reader->preserves--;
! 1383: reader->node = reader->node->next;
! 1384: reader->state = XML_TEXTREADER_ELEMENT;
! 1385:
! 1386: /*
! 1387: * Cleanup of the old node
! 1388: */
! 1389: if ((reader->preserves == 0) &&
! 1390: #ifdef LIBXML_XINCLUDE_ENABLED
! 1391: (reader->in_xinclude == 0) &&
! 1392: #endif
! 1393: (reader->entNr == 0) &&
! 1394: (reader->node->prev != NULL) &&
! 1395: (reader->node->prev->type != XML_DTD_NODE) &&
! 1396: (reader->entNr == 0)) {
! 1397: xmlNodePtr tmp = reader->node->prev;
! 1398: if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
! 1399: xmlUnlinkNode(tmp);
! 1400: xmlTextReaderFreeNode(reader, tmp);
! 1401: }
! 1402: }
! 1403:
! 1404: goto node_found;
! 1405: }
! 1406: if ((oldstate == XML_TEXTREADER_ELEMENT) &&
! 1407: (reader->node->type == XML_ELEMENT_NODE) &&
! 1408: (reader->node->children == NULL) &&
! 1409: ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
! 1410: reader->state = XML_TEXTREADER_END;
! 1411: goto node_found;
! 1412: }
! 1413: #ifdef LIBXML_REGEXP_ENABLED
! 1414: if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
! 1415: xmlTextReaderValidatePop(reader);
! 1416: #endif /* LIBXML_REGEXP_ENABLED */
! 1417: if ((reader->preserves > 0) &&
! 1418: (reader->node->extra & NODE_IS_SPRESERVED))
! 1419: reader->preserves--;
! 1420: reader->node = reader->node->parent;
! 1421: if ((reader->node == NULL) ||
! 1422: (reader->node->type == XML_DOCUMENT_NODE) ||
! 1423: #ifdef LIBXML_DOCB_ENABLED
! 1424: (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
! 1425: #endif
! 1426: (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
! 1427: if (reader->mode != XML_TEXTREADER_MODE_EOF) {
! 1428: val = xmlParseChunk(reader->ctxt, "", 0, 1);
! 1429: reader->state = XML_TEXTREADER_DONE;
! 1430: if (val != 0)
! 1431: return(-1);
! 1432: }
! 1433: reader->node = NULL;
! 1434: reader->depth = -1;
! 1435:
! 1436: /*
! 1437: * Cleanup of the old node
! 1438: */
! 1439: if ((oldnode != NULL) && (reader->preserves == 0) &&
! 1440: #ifdef LIBXML_XINCLUDE_ENABLED
! 1441: (reader->in_xinclude == 0) &&
! 1442: #endif
! 1443: (reader->entNr == 0) &&
! 1444: (oldnode->type != XML_DTD_NODE) &&
! 1445: ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
! 1446: (reader->entNr == 0)) {
! 1447: xmlUnlinkNode(oldnode);
! 1448: xmlTextReaderFreeNode(reader, oldnode);
! 1449: }
! 1450:
! 1451: goto node_end;
! 1452: }
! 1453: if ((reader->preserves == 0) &&
! 1454: #ifdef LIBXML_XINCLUDE_ENABLED
! 1455: (reader->in_xinclude == 0) &&
! 1456: #endif
! 1457: (reader->entNr == 0) &&
! 1458: (reader->node->last != NULL) &&
! 1459: ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
! 1460: xmlNodePtr tmp = reader->node->last;
! 1461: xmlUnlinkNode(tmp);
! 1462: xmlTextReaderFreeNode(reader, tmp);
! 1463: }
! 1464: reader->depth--;
! 1465: reader->state = XML_TEXTREADER_BACKTRACK;
! 1466:
! 1467: node_found:
! 1468: DUMP_READER
! 1469:
! 1470: /*
! 1471: * If we are in the middle of a piece of CDATA make sure it's finished
! 1472: */
! 1473: if ((reader->node != NULL) &&
! 1474: (reader->node->next == NULL) &&
! 1475: ((reader->node->type == XML_TEXT_NODE) ||
! 1476: (reader->node->type == XML_CDATA_SECTION_NODE))) {
! 1477: if (xmlTextReaderExpand(reader) == NULL)
! 1478: return -1;
! 1479: }
! 1480:
! 1481: #ifdef LIBXML_XINCLUDE_ENABLED
! 1482: /*
! 1483: * Handle XInclude if asked for
! 1484: */
! 1485: if ((reader->xinclude) && (reader->node != NULL) &&
! 1486: (reader->node->type == XML_ELEMENT_NODE) &&
! 1487: (reader->node->ns != NULL) &&
! 1488: ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
! 1489: (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
! 1490: if (reader->xincctxt == NULL) {
! 1491: reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
! 1492: xmlXIncludeSetFlags(reader->xincctxt,
! 1493: reader->parserFlags & (~XML_PARSE_NOXINCNODE));
! 1494: }
! 1495: /*
! 1496: * expand that node and process it
! 1497: */
! 1498: if (xmlTextReaderExpand(reader) == NULL)
! 1499: return -1;
! 1500: xmlXIncludeProcessNode(reader->xincctxt, reader->node);
! 1501: }
! 1502: if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
! 1503: reader->in_xinclude++;
! 1504: goto get_next_node;
! 1505: }
! 1506: if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
! 1507: reader->in_xinclude--;
! 1508: goto get_next_node;
! 1509: }
! 1510: #endif
! 1511: /*
! 1512: * Handle entities enter and exit when in entity replacement mode
! 1513: */
! 1514: if ((reader->node != NULL) &&
! 1515: (reader->node->type == XML_ENTITY_REF_NODE) &&
! 1516: (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
! 1517: /*
! 1518: * Case where the underlying tree is not availble, lookup the entity
! 1519: * and walk it.
! 1520: */
! 1521: if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
! 1522: (reader->ctxt->sax->getEntity != NULL)) {
! 1523: reader->node->children = (xmlNodePtr)
! 1524: reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
! 1525: }
! 1526:
! 1527: if ((reader->node->children != NULL) &&
! 1528: (reader->node->children->type == XML_ENTITY_DECL) &&
! 1529: (reader->node->children->children != NULL)) {
! 1530: xmlTextReaderEntPush(reader, reader->node);
! 1531: reader->node = reader->node->children->children;
! 1532: }
! 1533: #ifdef LIBXML_REGEXP_ENABLED
! 1534: } else if ((reader->node != NULL) &&
! 1535: (reader->node->type == XML_ENTITY_REF_NODE) &&
! 1536: (reader->ctxt != NULL) && (reader->validate)) {
! 1537: xmlTextReaderValidateEntity(reader);
! 1538: #endif /* LIBXML_REGEXP_ENABLED */
! 1539: }
! 1540: if ((reader->node != NULL) &&
! 1541: (reader->node->type == XML_ENTITY_DECL) &&
! 1542: (reader->ent != NULL) && (reader->ent->children == reader->node)) {
! 1543: reader->node = xmlTextReaderEntPop(reader);
! 1544: reader->depth++;
! 1545: goto get_next_node;
! 1546: }
! 1547: #ifdef LIBXML_REGEXP_ENABLED
! 1548: if ((reader->validate) && (reader->node != NULL)) {
! 1549: xmlNodePtr node = reader->node;
! 1550:
! 1551: if ((node->type == XML_ELEMENT_NODE) &&
! 1552: ((reader->state != XML_TEXTREADER_END) &&
! 1553: (reader->state != XML_TEXTREADER_BACKTRACK))) {
! 1554: xmlTextReaderValidatePush(reader);
! 1555: } else if ((node->type == XML_TEXT_NODE) ||
! 1556: (node->type == XML_CDATA_SECTION_NODE)) {
! 1557: xmlTextReaderValidateCData(reader, node->content,
! 1558: xmlStrlen(node->content));
! 1559: }
! 1560: }
! 1561: #endif /* LIBXML_REGEXP_ENABLED */
! 1562: #ifdef LIBXML_PATTERN_ENABLED
! 1563: if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
! 1564: (reader->state != XML_TEXTREADER_BACKTRACK)) {
! 1565: int i;
! 1566: for (i = 0;i < reader->patternNr;i++) {
! 1567: if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
! 1568: xmlTextReaderPreserve(reader);
! 1569: break;
! 1570: }
! 1571: }
! 1572: }
! 1573: #endif /* LIBXML_PATTERN_ENABLED */
! 1574: #ifdef LIBXML_SCHEMAS_ENABLED
! 1575: if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
! 1576: (reader->xsdValidErrors == 0) &&
! 1577: (reader->xsdValidCtxt != NULL)) {
! 1578: reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
! 1579: }
! 1580: #endif /* LIBXML_PATTERN_ENABLED */
! 1581: return(1);
! 1582: node_end:
! 1583: reader->state = XML_TEXTREADER_DONE;
! 1584: return(0);
! 1585: }
! 1586:
! 1587: /**
! 1588: * xmlTextReaderReadState:
! 1589: * @reader: the xmlTextReaderPtr used
! 1590: *
! 1591: * Gets the read state of the reader.
! 1592: *
! 1593: * Returns the state value, or -1 in case of error
! 1594: */
! 1595: int
! 1596: xmlTextReaderReadState(xmlTextReaderPtr reader) {
! 1597: if (reader == NULL)
! 1598: return(-1);
! 1599: return(reader->mode);
! 1600: }
! 1601:
! 1602: /**
! 1603: * xmlTextReaderExpand:
! 1604: * @reader: the xmlTextReaderPtr used
! 1605: *
! 1606: * Reads the contents of the current node and the full subtree. It then makes
! 1607: * the subtree available until the next xmlTextReaderRead() call
! 1608: *
! 1609: * Returns a node pointer valid until the next xmlTextReaderRead() call
! 1610: * or NULL in case of error.
! 1611: */
! 1612: xmlNodePtr
! 1613: xmlTextReaderExpand(xmlTextReaderPtr reader) {
! 1614: if ((reader == NULL) || (reader->node == NULL))
! 1615: return(NULL);
! 1616: if (reader->doc != NULL)
! 1617: return(reader->node);
! 1618: if (reader->ctxt == NULL)
! 1619: return(NULL);
! 1620: if (xmlTextReaderDoExpand(reader) < 0)
! 1621: return(NULL);
! 1622: return(reader->node);
! 1623: }
! 1624:
! 1625: /**
! 1626: * xmlTextReaderNext:
! 1627: * @reader: the xmlTextReaderPtr used
! 1628: *
! 1629: * Skip to the node following the current one in document order while
! 1630: * avoiding the subtree if any.
! 1631: *
! 1632: * Returns 1 if the node was read successfully, 0 if there is no more
! 1633: * nodes to read, or -1 in case of error
! 1634: */
! 1635: int
! 1636: xmlTextReaderNext(xmlTextReaderPtr reader) {
! 1637: int ret;
! 1638: xmlNodePtr cur;
! 1639:
! 1640: if (reader == NULL)
! 1641: return(-1);
! 1642: if (reader->doc != NULL)
! 1643: return(xmlTextReaderNextTree(reader));
! 1644: cur = reader->node;
! 1645: if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
! 1646: return(xmlTextReaderRead(reader));
! 1647: if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
! 1648: return(xmlTextReaderRead(reader));
! 1649: if (cur->extra & NODE_IS_EMPTY)
! 1650: return(xmlTextReaderRead(reader));
! 1651: do {
! 1652: ret = xmlTextReaderRead(reader);
! 1653: if (ret != 1)
! 1654: return(ret);
! 1655: } while (reader->node != cur);
! 1656: return(xmlTextReaderRead(reader));
! 1657: }
! 1658:
! 1659: #ifdef LIBXML_WRITER_ENABLED
! 1660: /**
! 1661: * xmlTextReaderReadInnerXml:
! 1662: * @reader: the xmlTextReaderPtr used
! 1663: *
! 1664: * Reads the contents of the current node, including child nodes and markup.
! 1665: *
! 1666: * Returns a string containing the XML content, or NULL if the current node
! 1667: * is neither an element nor attribute, or has no child nodes. The
! 1668: * string must be deallocated by the caller.
! 1669: */
! 1670: xmlChar *
! 1671: xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
! 1672: {
! 1673: xmlChar *resbuf;
! 1674: xmlNodePtr node, cur_node;
! 1675: xmlBufferPtr buff, buff2;
! 1676: xmlDocPtr doc;
! 1677:
! 1678: if (xmlTextReaderExpand(reader) == NULL) {
! 1679: return NULL;
! 1680: }
! 1681: doc = reader->doc;
! 1682: buff = xmlBufferCreate();
! 1683: for (cur_node = reader->node->children; cur_node != NULL;
! 1684: cur_node = cur_node->next) {
! 1685: node = xmlDocCopyNode(cur_node, doc, 1);
! 1686: buff2 = xmlBufferCreate();
! 1687: if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
! 1688: xmlFreeNode(node);
! 1689: xmlBufferFree(buff2);
! 1690: xmlBufferFree(buff);
! 1691: return NULL;
! 1692: }
! 1693: xmlBufferCat(buff, buff2->content);
! 1694: xmlFreeNode(node);
! 1695: xmlBufferFree(buff2);
! 1696: }
! 1697: resbuf = buff->content;
! 1698: buff->content = NULL;
! 1699:
! 1700: xmlBufferFree(buff);
! 1701: return resbuf;
! 1702: }
! 1703: #endif
! 1704:
! 1705: #ifdef LIBXML_WRITER_ENABLED
! 1706: /**
! 1707: * xmlTextReaderReadOuterXml:
! 1708: * @reader: the xmlTextReaderPtr used
! 1709: *
! 1710: * Reads the contents of the current node, including child nodes and markup.
! 1711: *
! 1712: * Returns a string containing the node and any XML content, or NULL if the
! 1713: * current node cannot be serialized. The string must be deallocated
! 1714: * by the caller.
! 1715: */
! 1716: xmlChar *
! 1717: xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
! 1718: {
! 1719: xmlChar *resbuf;
! 1720: xmlNodePtr node;
! 1721: xmlBufferPtr buff;
! 1722: xmlDocPtr doc;
! 1723:
! 1724: node = reader->node;
! 1725: doc = reader->doc;
! 1726: if (xmlTextReaderExpand(reader) == NULL) {
! 1727: return NULL;
! 1728: }
! 1729: if (node->type == XML_DTD_NODE) {
! 1730: node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
! 1731: } else {
! 1732: node = xmlDocCopyNode(node, doc, 1);
! 1733: }
! 1734: buff = xmlBufferCreate();
! 1735: if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
! 1736: xmlFreeNode(node);
! 1737: xmlBufferFree(buff);
! 1738: return NULL;
! 1739: }
! 1740:
! 1741: resbuf = buff->content;
! 1742: buff->content = NULL;
! 1743:
! 1744: xmlFreeNode(node);
! 1745: xmlBufferFree(buff);
! 1746: return resbuf;
! 1747: }
! 1748: #endif
! 1749:
! 1750: /**
! 1751: * xmlTextReaderReadString:
! 1752: * @reader: the xmlTextReaderPtr used
! 1753: *
! 1754: * Reads the contents of an element or a text node as a string.
! 1755: *
! 1756: * Returns a string containing the contents of the Element or Text node,
! 1757: * or NULL if the reader is positioned on any other type of node.
! 1758: * The string must be deallocated by the caller.
! 1759: */
! 1760: xmlChar *
! 1761: xmlTextReaderReadString(xmlTextReaderPtr reader)
! 1762: {
! 1763: xmlNodePtr node;
! 1764:
! 1765: if ((reader == NULL) || (reader->node == NULL))
! 1766: return(NULL);
! 1767:
! 1768: node = (reader->curnode != NULL) ? reader->curnode : reader->node;
! 1769: switch (node->type) {
! 1770: case XML_TEXT_NODE:
! 1771: if (node->content != NULL)
! 1772: return(xmlStrdup(node->content));
! 1773: break;
! 1774: case XML_ELEMENT_NODE:
! 1775: if (xmlTextReaderDoExpand(reader) != -1) {
! 1776: return xmlTextReaderCollectSiblings(node->children);
! 1777: }
! 1778: case XML_ATTRIBUTE_NODE:
! 1779: TODO
! 1780: break;
! 1781: default:
! 1782: break;
! 1783: }
! 1784: return(NULL);
! 1785: }
! 1786:
! 1787: #if 0
! 1788: /**
! 1789: * xmlTextReaderReadBase64:
! 1790: * @reader: the xmlTextReaderPtr used
! 1791: * @array: a byte array to store the content.
! 1792: * @offset: the zero-based index into array where the method should
! 1793: * begin to write.
! 1794: * @len: the number of bytes to write.
! 1795: *
! 1796: * Reads and decodes the Base64 encoded contents of an element and
! 1797: * stores the result in a byte buffer.
! 1798: *
! 1799: * Returns the number of bytes written to array, or zero if the current
! 1800: * instance is not positioned on an element or -1 in case of error.
! 1801: */
! 1802: int
! 1803: xmlTextReaderReadBase64(xmlTextReaderPtr reader,
! 1804: unsigned char *array ATTRIBUTE_UNUSED,
! 1805: int offset ATTRIBUTE_UNUSED,
! 1806: int len ATTRIBUTE_UNUSED) {
! 1807: if ((reader == NULL) || (reader->ctxt == NULL))
! 1808: return(-1);
! 1809: if (reader->ctxt->wellFormed != 1)
! 1810: return(-1);
! 1811:
! 1812: if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
! 1813: return(0);
! 1814: TODO
! 1815: return(0);
! 1816: }
! 1817:
! 1818: /**
! 1819: * xmlTextReaderReadBinHex:
! 1820: * @reader: the xmlTextReaderPtr used
! 1821: * @array: a byte array to store the content.
! 1822: * @offset: the zero-based index into array where the method should
! 1823: * begin to write.
! 1824: * @len: the number of bytes to write.
! 1825: *
! 1826: * Reads and decodes the BinHex encoded contents of an element and
! 1827: * stores the result in a byte buffer.
! 1828: *
! 1829: * Returns the number of bytes written to array, or zero if the current
! 1830: * instance is not positioned on an element or -1 in case of error.
! 1831: */
! 1832: int
! 1833: xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
! 1834: unsigned char *array ATTRIBUTE_UNUSED,
! 1835: int offset ATTRIBUTE_UNUSED,
! 1836: int len ATTRIBUTE_UNUSED) {
! 1837: if ((reader == NULL) || (reader->ctxt == NULL))
! 1838: return(-1);
! 1839: if (reader->ctxt->wellFormed != 1)
! 1840: return(-1);
! 1841:
! 1842: if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
! 1843: return(0);
! 1844: TODO
! 1845: return(0);
! 1846: }
! 1847: #endif
! 1848:
! 1849: /************************************************************************
! 1850: * *
! 1851: * Operating on a preparsed tree *
! 1852: * *
! 1853: ************************************************************************/
! 1854: static int
! 1855: xmlTextReaderNextTree(xmlTextReaderPtr reader)
! 1856: {
! 1857: if (reader == NULL)
! 1858: return(-1);
! 1859:
! 1860: if (reader->state == XML_TEXTREADER_END)
! 1861: return(0);
! 1862:
! 1863: if (reader->node == NULL) {
! 1864: if (reader->doc->children == NULL) {
! 1865: reader->state = XML_TEXTREADER_END;
! 1866: return(0);
! 1867: }
! 1868:
! 1869: reader->node = reader->doc->children;
! 1870: reader->state = XML_TEXTREADER_START;
! 1871: return(1);
! 1872: }
! 1873:
! 1874: if (reader->state != XML_TEXTREADER_BACKTRACK) {
! 1875: /* Here removed traversal to child, because we want to skip the subtree,
! 1876: replace with traversal to sibling to skip subtree */
! 1877: if (reader->node->next != 0) {
! 1878: /* Move to sibling if present,skipping sub-tree */
! 1879: reader->node = reader->node->next;
! 1880: reader->state = XML_TEXTREADER_START;
! 1881: return(1);
! 1882: }
! 1883:
! 1884: /* if reader->node->next is NULL mean no subtree for current node,
! 1885: so need to move to sibling of parent node if present */
! 1886: if ((reader->node->type == XML_ELEMENT_NODE) ||
! 1887: (reader->node->type == XML_ATTRIBUTE_NODE)) {
! 1888: reader->state = XML_TEXTREADER_BACKTRACK;
! 1889: /* This will move to parent if present */
! 1890: xmlTextReaderRead(reader);
! 1891: }
! 1892: }
! 1893:
! 1894: if (reader->node->next != 0) {
! 1895: reader->node = reader->node->next;
! 1896: reader->state = XML_TEXTREADER_START;
! 1897: return(1);
! 1898: }
! 1899:
! 1900: if (reader->node->parent != 0) {
! 1901: if (reader->node->parent->type == XML_DOCUMENT_NODE) {
! 1902: reader->state = XML_TEXTREADER_END;
! 1903: return(0);
! 1904: }
! 1905:
! 1906: reader->node = reader->node->parent;
! 1907: reader->depth--;
! 1908: reader->state = XML_TEXTREADER_BACKTRACK;
! 1909: /* Repeat process to move to sibling of parent node if present */
! 1910: xmlTextReaderNextTree(reader);
! 1911: }
! 1912:
! 1913: reader->state = XML_TEXTREADER_END;
! 1914:
! 1915: return(1);
! 1916: }
! 1917:
! 1918: /**
! 1919: * xmlTextReaderReadTree:
! 1920: * @reader: the xmlTextReaderPtr used
! 1921: *
! 1922: * Moves the position of the current instance to the next node in
! 1923: * the stream, exposing its properties.
! 1924: *
! 1925: * Returns 1 if the node was read successfully, 0 if there is no more
! 1926: * nodes to read, or -1 in case of error
! 1927: */
! 1928: static int
! 1929: xmlTextReaderReadTree(xmlTextReaderPtr reader) {
! 1930: if (reader->state == XML_TEXTREADER_END)
! 1931: return(0);
! 1932:
! 1933: next_node:
! 1934: if (reader->node == NULL) {
! 1935: if (reader->doc->children == NULL) {
! 1936: reader->state = XML_TEXTREADER_END;
! 1937: return(0);
! 1938: }
! 1939:
! 1940: reader->node = reader->doc->children;
! 1941: reader->state = XML_TEXTREADER_START;
! 1942: goto found_node;
! 1943: }
! 1944:
! 1945: if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
! 1946: (reader->node->type != XML_DTD_NODE) &&
! 1947: (reader->node->type != XML_XINCLUDE_START) &&
! 1948: (reader->node->type != XML_ENTITY_REF_NODE)) {
! 1949: if (reader->node->children != NULL) {
! 1950: reader->node = reader->node->children;
! 1951: reader->depth++;
! 1952: reader->state = XML_TEXTREADER_START;
! 1953: goto found_node;
! 1954: }
! 1955:
! 1956: if (reader->node->type == XML_ATTRIBUTE_NODE) {
! 1957: reader->state = XML_TEXTREADER_BACKTRACK;
! 1958: goto found_node;
! 1959: }
! 1960: }
! 1961:
! 1962: if (reader->node->next != NULL) {
! 1963: reader->node = reader->node->next;
! 1964: reader->state = XML_TEXTREADER_START;
! 1965: goto found_node;
! 1966: }
! 1967:
! 1968: if (reader->node->parent != NULL) {
! 1969: if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
! 1970: (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
! 1971: reader->state = XML_TEXTREADER_END;
! 1972: return(0);
! 1973: }
! 1974:
! 1975: reader->node = reader->node->parent;
! 1976: reader->depth--;
! 1977: reader->state = XML_TEXTREADER_BACKTRACK;
! 1978: goto found_node;
! 1979: }
! 1980:
! 1981: reader->state = XML_TEXTREADER_END;
! 1982:
! 1983: found_node:
! 1984: if ((reader->node->type == XML_XINCLUDE_START) ||
! 1985: (reader->node->type == XML_XINCLUDE_END))
! 1986: goto next_node;
! 1987:
! 1988: return(1);
! 1989: }
! 1990:
! 1991: /**
! 1992: * xmlTextReaderNextSibling:
! 1993: * @reader: the xmlTextReaderPtr used
! 1994: *
! 1995: * Skip to the node following the current one in document order while
! 1996: * avoiding the subtree if any.
! 1997: * Currently implemented only for Readers built on a document
! 1998: *
! 1999: * Returns 1 if the node was read successfully, 0 if there is no more
! 2000: * nodes to read, or -1 in case of error
! 2001: */
! 2002: int
! 2003: xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
! 2004: if (reader == NULL)
! 2005: return(-1);
! 2006: if (reader->doc == NULL) {
! 2007: /* TODO */
! 2008: return(-1);
! 2009: }
! 2010:
! 2011: if (reader->state == XML_TEXTREADER_END)
! 2012: return(0);
! 2013:
! 2014: if (reader->node == NULL)
! 2015: return(xmlTextReaderNextTree(reader));
! 2016:
! 2017: if (reader->node->next != NULL) {
! 2018: reader->node = reader->node->next;
! 2019: reader->state = XML_TEXTREADER_START;
! 2020: return(1);
! 2021: }
! 2022:
! 2023: return(0);
! 2024: }
! 2025:
! 2026: /************************************************************************
! 2027: * *
! 2028: * Constructor and destructors *
! 2029: * *
! 2030: ************************************************************************/
! 2031: /**
! 2032: * xmlNewTextReader:
! 2033: * @input: the xmlParserInputBufferPtr used to read data
! 2034: * @URI: the URI information for the source if available
! 2035: *
! 2036: * Create an xmlTextReader structure fed with @input
! 2037: *
! 2038: * Returns the new xmlTextReaderPtr or NULL in case of error
! 2039: */
! 2040: xmlTextReaderPtr
! 2041: xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
! 2042: xmlTextReaderPtr ret;
! 2043:
! 2044: if (input == NULL)
! 2045: return(NULL);
! 2046: ret = xmlMalloc(sizeof(xmlTextReader));
! 2047: if (ret == NULL) {
! 2048: xmlGenericError(xmlGenericErrorContext,
! 2049: "xmlNewTextReader : malloc failed\n");
! 2050: return(NULL);
! 2051: }
! 2052: memset(ret, 0, sizeof(xmlTextReader));
! 2053: ret->doc = NULL;
! 2054: ret->entTab = NULL;
! 2055: ret->entMax = 0;
! 2056: ret->entNr = 0;
! 2057: ret->input = input;
! 2058: ret->buffer = xmlBufferCreateSize(100);
! 2059: if (ret->buffer == NULL) {
! 2060: xmlFree(ret);
! 2061: xmlGenericError(xmlGenericErrorContext,
! 2062: "xmlNewTextReader : malloc failed\n");
! 2063: return(NULL);
! 2064: }
! 2065: ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
! 2066: if (ret->sax == NULL) {
! 2067: xmlBufferFree(ret->buffer);
! 2068: xmlFree(ret);
! 2069: xmlGenericError(xmlGenericErrorContext,
! 2070: "xmlNewTextReader : malloc failed\n");
! 2071: return(NULL);
! 2072: }
! 2073: xmlSAXVersion(ret->sax, 2);
! 2074: ret->startElement = ret->sax->startElement;
! 2075: ret->sax->startElement = xmlTextReaderStartElement;
! 2076: ret->endElement = ret->sax->endElement;
! 2077: ret->sax->endElement = xmlTextReaderEndElement;
! 2078: #ifdef LIBXML_SAX1_ENABLED
! 2079: if (ret->sax->initialized == XML_SAX2_MAGIC) {
! 2080: #endif /* LIBXML_SAX1_ENABLED */
! 2081: ret->startElementNs = ret->sax->startElementNs;
! 2082: ret->sax->startElementNs = xmlTextReaderStartElementNs;
! 2083: ret->endElementNs = ret->sax->endElementNs;
! 2084: ret->sax->endElementNs = xmlTextReaderEndElementNs;
! 2085: #ifdef LIBXML_SAX1_ENABLED
! 2086: } else {
! 2087: ret->startElementNs = NULL;
! 2088: ret->endElementNs = NULL;
! 2089: }
! 2090: #endif /* LIBXML_SAX1_ENABLED */
! 2091: ret->characters = ret->sax->characters;
! 2092: ret->sax->characters = xmlTextReaderCharacters;
! 2093: ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
! 2094: ret->cdataBlock = ret->sax->cdataBlock;
! 2095: ret->sax->cdataBlock = xmlTextReaderCDataBlock;
! 2096:
! 2097: ret->mode = XML_TEXTREADER_MODE_INITIAL;
! 2098: ret->node = NULL;
! 2099: ret->curnode = NULL;
! 2100: if (ret->input->buffer->use < 4) {
! 2101: xmlParserInputBufferRead(input, 4);
! 2102: }
! 2103: if (ret->input->buffer->use >= 4) {
! 2104: ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
! 2105: (const char *) ret->input->buffer->content, 4, URI);
! 2106: ret->base = 0;
! 2107: ret->cur = 4;
! 2108: } else {
! 2109: ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
! 2110: ret->base = 0;
! 2111: ret->cur = 0;
! 2112: }
! 2113:
! 2114: if (ret->ctxt == NULL) {
! 2115: xmlGenericError(xmlGenericErrorContext,
! 2116: "xmlNewTextReader : malloc failed\n");
! 2117: xmlBufferFree(ret->buffer);
! 2118: xmlFree(ret->sax);
! 2119: xmlFree(ret);
! 2120: return(NULL);
! 2121: }
! 2122: ret->ctxt->parseMode = XML_PARSE_READER;
! 2123: ret->ctxt->_private = ret;
! 2124: ret->ctxt->linenumbers = 1;
! 2125: ret->ctxt->dictNames = 1;
! 2126: ret->allocs = XML_TEXTREADER_CTXT;
! 2127: /*
! 2128: * use the parser dictionnary to allocate all elements and attributes names
! 2129: */
! 2130: ret->ctxt->docdict = 1;
! 2131: ret->dict = ret->ctxt->dict;
! 2132: #ifdef LIBXML_XINCLUDE_ENABLED
! 2133: ret->xinclude = 0;
! 2134: #endif
! 2135: #ifdef LIBXML_PATTERN_ENABLED
! 2136: ret->patternMax = 0;
! 2137: ret->patternTab = NULL;
! 2138: #endif
! 2139: return(ret);
! 2140: }
! 2141:
! 2142: /**
! 2143: * xmlNewTextReaderFilename:
! 2144: * @URI: the URI of the resource to process
! 2145: *
! 2146: * Create an xmlTextReader structure fed with the resource at @URI
! 2147: *
! 2148: * Returns the new xmlTextReaderPtr or NULL in case of error
! 2149: */
! 2150: xmlTextReaderPtr
! 2151: xmlNewTextReaderFilename(const char *URI) {
! 2152: xmlParserInputBufferPtr input;
! 2153: xmlTextReaderPtr ret;
! 2154: char *directory = NULL;
! 2155:
! 2156: input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
! 2157: if (input == NULL)
! 2158: return(NULL);
! 2159: ret = xmlNewTextReader(input, URI);
! 2160: if (ret == NULL) {
! 2161: xmlFreeParserInputBuffer(input);
! 2162: return(NULL);
! 2163: }
! 2164: ret->allocs |= XML_TEXTREADER_INPUT;
! 2165: if (ret->ctxt->directory == NULL)
! 2166: directory = xmlParserGetDirectory(URI);
! 2167: if ((ret->ctxt->directory == NULL) && (directory != NULL))
! 2168: ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
! 2169: if (directory != NULL)
! 2170: xmlFree(directory);
! 2171: return(ret);
! 2172: }
! 2173:
! 2174: /**
! 2175: * xmlFreeTextReader:
! 2176: * @reader: the xmlTextReaderPtr
! 2177: *
! 2178: * Deallocate all the resources associated to the reader
! 2179: */
! 2180: void
! 2181: xmlFreeTextReader(xmlTextReaderPtr reader) {
! 2182: if (reader == NULL)
! 2183: return;
! 2184: #ifdef LIBXML_SCHEMAS_ENABLED
! 2185: if (reader->rngSchemas != NULL) {
! 2186: xmlRelaxNGFree(reader->rngSchemas);
! 2187: reader->rngSchemas = NULL;
! 2188: }
! 2189: if (reader->rngValidCtxt != NULL) {
! 2190: xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
! 2191: reader->rngValidCtxt = NULL;
! 2192: }
! 2193: if (reader->xsdPlug != NULL) {
! 2194: xmlSchemaSAXUnplug(reader->xsdPlug);
! 2195: reader->xsdPlug = NULL;
! 2196: }
! 2197: if (reader->xsdValidCtxt != NULL) {
! 2198: if (! reader->xsdPreserveCtxt)
! 2199: xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
! 2200: reader->xsdValidCtxt = NULL;
! 2201: }
! 2202: if (reader->xsdSchemas != NULL) {
! 2203: xmlSchemaFree(reader->xsdSchemas);
! 2204: reader->xsdSchemas = NULL;
! 2205: }
! 2206: #endif
! 2207: #ifdef LIBXML_XINCLUDE_ENABLED
! 2208: if (reader->xincctxt != NULL)
! 2209: xmlXIncludeFreeContext(reader->xincctxt);
! 2210: #endif
! 2211: #ifdef LIBXML_PATTERN_ENABLED
! 2212: if (reader->patternTab != NULL) {
! 2213: int i;
! 2214: for (i = 0;i < reader->patternNr;i++) {
! 2215: if (reader->patternTab[i] != NULL)
! 2216: xmlFreePattern(reader->patternTab[i]);
! 2217: }
! 2218: xmlFree(reader->patternTab);
! 2219: }
! 2220: #endif
! 2221: if (reader->faketext != NULL) {
! 2222: xmlFreeNode(reader->faketext);
! 2223: }
! 2224: if (reader->ctxt != NULL) {
! 2225: if (reader->dict == reader->ctxt->dict)
! 2226: reader->dict = NULL;
! 2227: if (reader->ctxt->myDoc != NULL) {
! 2228: if (reader->preserve == 0)
! 2229: xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
! 2230: reader->ctxt->myDoc = NULL;
! 2231: }
! 2232: if ((reader->ctxt->vctxt.vstateTab != NULL) &&
! 2233: (reader->ctxt->vctxt.vstateMax > 0)){
! 2234: xmlFree(reader->ctxt->vctxt.vstateTab);
! 2235: reader->ctxt->vctxt.vstateTab = NULL;
! 2236: reader->ctxt->vctxt.vstateMax = 0;
! 2237: }
! 2238: if (reader->allocs & XML_TEXTREADER_CTXT)
! 2239: xmlFreeParserCtxt(reader->ctxt);
! 2240: }
! 2241: if (reader->sax != NULL)
! 2242: xmlFree(reader->sax);
! 2243: if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
! 2244: xmlFreeParserInputBuffer(reader->input);
! 2245: if (reader->buffer != NULL)
! 2246: xmlBufferFree(reader->buffer);
! 2247: if (reader->entTab != NULL)
! 2248: xmlFree(reader->entTab);
! 2249: if (reader->dict != NULL)
! 2250: xmlDictFree(reader->dict);
! 2251: xmlFree(reader);
! 2252: }
! 2253:
! 2254: /************************************************************************
! 2255: * *
! 2256: * Methods for XmlTextReader *
! 2257: * *
! 2258: ************************************************************************/
! 2259: /**
! 2260: * xmlTextReaderClose:
! 2261: * @reader: the xmlTextReaderPtr used
! 2262: *
! 2263: * This method releases any resources allocated by the current instance
! 2264: * changes the state to Closed and close any underlying input.
! 2265: *
! 2266: * Returns 0 or -1 in case of error
! 2267: */
! 2268: int
! 2269: xmlTextReaderClose(xmlTextReaderPtr reader) {
! 2270: if (reader == NULL)
! 2271: return(-1);
! 2272: reader->node = NULL;
! 2273: reader->curnode = NULL;
! 2274: reader->mode = XML_TEXTREADER_MODE_CLOSED;
! 2275: if (reader->ctxt != NULL) {
! 2276: xmlStopParser(reader->ctxt);
! 2277: if (reader->ctxt->myDoc != NULL) {
! 2278: if (reader->preserve == 0)
! 2279: xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
! 2280: reader->ctxt->myDoc = NULL;
! 2281: }
! 2282: }
! 2283: if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
! 2284: xmlFreeParserInputBuffer(reader->input);
! 2285: reader->allocs -= XML_TEXTREADER_INPUT;
! 2286: }
! 2287: return(0);
! 2288: }
! 2289:
! 2290: /**
! 2291: * xmlTextReaderGetAttributeNo:
! 2292: * @reader: the xmlTextReaderPtr used
! 2293: * @no: the zero-based index of the attribute relative to the containing element
! 2294: *
! 2295: * Provides the value of the attribute with the specified index relative
! 2296: * to the containing element.
! 2297: *
! 2298: * Returns a string containing the value of the specified attribute, or NULL
! 2299: * in case of error. The string must be deallocated by the caller.
! 2300: */
! 2301: xmlChar *
! 2302: xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
! 2303: xmlChar *ret;
! 2304: int i;
! 2305: xmlAttrPtr cur;
! 2306: xmlNsPtr ns;
! 2307:
! 2308: if (reader == NULL)
! 2309: return(NULL);
! 2310: if (reader->node == NULL)
! 2311: return(NULL);
! 2312: if (reader->curnode != NULL)
! 2313: return(NULL);
! 2314: /* TODO: handle the xmlDecl */
! 2315: if (reader->node->type != XML_ELEMENT_NODE)
! 2316: return(NULL);
! 2317:
! 2318: ns = reader->node->nsDef;
! 2319: for (i = 0;(i < no) && (ns != NULL);i++) {
! 2320: ns = ns->next;
! 2321: }
! 2322: if (ns != NULL)
! 2323: return(xmlStrdup(ns->href));
! 2324:
! 2325: cur = reader->node->properties;
! 2326: if (cur == NULL)
! 2327: return(NULL);
! 2328: for (;i < no;i++) {
! 2329: cur = cur->next;
! 2330: if (cur == NULL)
! 2331: return(NULL);
! 2332: }
! 2333: /* TODO walk the DTD if present */
! 2334:
! 2335: ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
! 2336: if (ret == NULL) return(xmlStrdup((xmlChar *)""));
! 2337: return(ret);
! 2338: }
! 2339:
! 2340: /**
! 2341: * xmlTextReaderGetAttribute:
! 2342: * @reader: the xmlTextReaderPtr used
! 2343: * @name: the qualified name of the attribute.
! 2344: *
! 2345: * Provides the value of the attribute with the specified qualified name.
! 2346: *
! 2347: * Returns a string containing the value of the specified attribute, or NULL
! 2348: * in case of error. The string must be deallocated by the caller.
! 2349: */
! 2350: xmlChar *
! 2351: xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
! 2352: xmlChar *prefix = NULL;
! 2353: xmlChar *localname;
! 2354: xmlNsPtr ns;
! 2355: xmlChar *ret = NULL;
! 2356:
! 2357: if ((reader == NULL) || (name == NULL))
! 2358: return(NULL);
! 2359: if (reader->node == NULL)
! 2360: return(NULL);
! 2361: if (reader->curnode != NULL)
! 2362: return(NULL);
! 2363:
! 2364: /* TODO: handle the xmlDecl */
! 2365: if (reader->node->type != XML_ELEMENT_NODE)
! 2366: return(NULL);
! 2367:
! 2368: localname = xmlSplitQName2(name, &prefix);
! 2369: if (localname == NULL) {
! 2370: /*
! 2371: * Namespace default decl
! 2372: */
! 2373: if (xmlStrEqual(name, BAD_CAST "xmlns")) {
! 2374: ns = reader->node->nsDef;
! 2375: while (ns != NULL) {
! 2376: if (ns->prefix == NULL) {
! 2377: return(xmlStrdup(ns->href));
! 2378: }
! 2379: ns = ns->next;
! 2380: }
! 2381: return NULL;
! 2382: }
! 2383: return(xmlGetNoNsProp(reader->node, name));
! 2384: }
! 2385:
! 2386: /*
! 2387: * Namespace default decl
! 2388: */
! 2389: if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
! 2390: ns = reader->node->nsDef;
! 2391: while (ns != NULL) {
! 2392: if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
! 2393: ret = xmlStrdup(ns->href);
! 2394: break;
! 2395: }
! 2396: ns = ns->next;
! 2397: }
! 2398: } else {
! 2399: ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
! 2400: if (ns != NULL)
! 2401: ret = xmlGetNsProp(reader->node, localname, ns->href);
! 2402: }
! 2403:
! 2404: xmlFree(localname);
! 2405: if (prefix != NULL)
! 2406: xmlFree(prefix);
! 2407: return(ret);
! 2408: }
! 2409:
! 2410:
! 2411: /**
! 2412: * xmlTextReaderGetAttributeNs:
! 2413: * @reader: the xmlTextReaderPtr used
! 2414: * @localName: the local name of the attribute.
! 2415: * @namespaceURI: the namespace URI of the attribute.
! 2416: *
! 2417: * Provides the value of the specified attribute
! 2418: *
! 2419: * Returns a string containing the value of the specified attribute, or NULL
! 2420: * in case of error. The string must be deallocated by the caller.
! 2421: */
! 2422: xmlChar *
! 2423: xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
! 2424: const xmlChar *namespaceURI) {
! 2425: xmlChar *prefix = NULL;
! 2426: xmlNsPtr ns;
! 2427:
! 2428: if ((reader == NULL) || (localName == NULL))
! 2429: return(NULL);
! 2430: if (reader->node == NULL)
! 2431: return(NULL);
! 2432: if (reader->curnode != NULL)
! 2433: return(NULL);
! 2434:
! 2435: /* TODO: handle the xmlDecl */
! 2436: if (reader->node->type != XML_ELEMENT_NODE)
! 2437: return(NULL);
! 2438:
! 2439: if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
! 2440: if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
! 2441: prefix = BAD_CAST localName;
! 2442: }
! 2443: ns = reader->node->nsDef;
! 2444: while (ns != NULL) {
! 2445: if ((prefix == NULL && ns->prefix == NULL) ||
! 2446: ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
! 2447: return xmlStrdup(ns->href);
! 2448: }
! 2449: ns = ns->next;
! 2450: }
! 2451: return NULL;
! 2452: }
! 2453:
! 2454: return(xmlGetNsProp(reader->node, localName, namespaceURI));
! 2455: }
! 2456:
! 2457: /**
! 2458: * xmlTextReaderGetRemainder:
! 2459: * @reader: the xmlTextReaderPtr used
! 2460: *
! 2461: * Method to get the remainder of the buffered XML. this method stops the
! 2462: * parser, set its state to End Of File and return the input stream with
! 2463: * what is left that the parser did not use.
! 2464: *
! 2465: * The implementation is not good, the parser certainly procgressed past
! 2466: * what's left in reader->input, and there is an allocation problem. Best
! 2467: * would be to rewrite it differently.
! 2468: *
! 2469: * Returns the xmlParserInputBufferPtr attached to the XML or NULL
! 2470: * in case of error.
! 2471: */
! 2472: xmlParserInputBufferPtr
! 2473: xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
! 2474: xmlParserInputBufferPtr ret = NULL;
! 2475:
! 2476: if (reader == NULL)
! 2477: return(NULL);
! 2478: if (reader->node == NULL)
! 2479: return(NULL);
! 2480:
! 2481: reader->node = NULL;
! 2482: reader->curnode = NULL;
! 2483: reader->mode = XML_TEXTREADER_MODE_EOF;
! 2484: if (reader->ctxt != NULL) {
! 2485: xmlStopParser(reader->ctxt);
! 2486: if (reader->ctxt->myDoc != NULL) {
! 2487: if (reader->preserve == 0)
! 2488: xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
! 2489: reader->ctxt->myDoc = NULL;
! 2490: }
! 2491: }
! 2492: if (reader->allocs & XML_TEXTREADER_INPUT) {
! 2493: ret = reader->input;
! 2494: reader->input = NULL;
! 2495: reader->allocs -= XML_TEXTREADER_INPUT;
! 2496: } else {
! 2497: /*
! 2498: * Hum, one may need to duplicate the data structure because
! 2499: * without reference counting the input may be freed twice:
! 2500: * - by the layer which allocated it.
! 2501: * - by the layer to which would have been returned to.
! 2502: */
! 2503: TODO
! 2504: return(NULL);
! 2505: }
! 2506: return(ret);
! 2507: }
! 2508:
! 2509: /**
! 2510: * xmlTextReaderLookupNamespace:
! 2511: * @reader: the xmlTextReaderPtr used
! 2512: * @prefix: the prefix whose namespace URI is to be resolved. To return
! 2513: * the default namespace, specify NULL
! 2514: *
! 2515: * Resolves a namespace prefix in the scope of the current element.
! 2516: *
! 2517: * Returns a string containing the namespace URI to which the prefix maps
! 2518: * or NULL in case of error. The string must be deallocated by the caller.
! 2519: */
! 2520: xmlChar *
! 2521: xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
! 2522: xmlNsPtr ns;
! 2523:
! 2524: if (reader == NULL)
! 2525: return(NULL);
! 2526: if (reader->node == NULL)
! 2527: return(NULL);
! 2528:
! 2529: ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
! 2530: if (ns == NULL)
! 2531: return(NULL);
! 2532: return(xmlStrdup(ns->href));
! 2533: }
! 2534:
! 2535: /**
! 2536: * xmlTextReaderMoveToAttributeNo:
! 2537: * @reader: the xmlTextReaderPtr used
! 2538: * @no: the zero-based index of the attribute relative to the containing
! 2539: * element.
! 2540: *
! 2541: * Moves the position of the current instance to the attribute with
! 2542: * the specified index relative to the containing element.
! 2543: *
! 2544: * Returns 1 in case of success, -1 in case of error, 0 if not found
! 2545: */
! 2546: int
! 2547: xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
! 2548: int i;
! 2549: xmlAttrPtr cur;
! 2550: xmlNsPtr ns;
! 2551:
! 2552: if (reader == NULL)
! 2553: return(-1);
! 2554: if (reader->node == NULL)
! 2555: return(-1);
! 2556: /* TODO: handle the xmlDecl */
! 2557: if (reader->node->type != XML_ELEMENT_NODE)
! 2558: return(-1);
! 2559:
! 2560: reader->curnode = NULL;
! 2561:
! 2562: ns = reader->node->nsDef;
! 2563: for (i = 0;(i < no) && (ns != NULL);i++) {
! 2564: ns = ns->next;
! 2565: }
! 2566: if (ns != NULL) {
! 2567: reader->curnode = (xmlNodePtr) ns;
! 2568: return(1);
! 2569: }
! 2570:
! 2571: cur = reader->node->properties;
! 2572: if (cur == NULL)
! 2573: return(0);
! 2574: for (;i < no;i++) {
! 2575: cur = cur->next;
! 2576: if (cur == NULL)
! 2577: return(0);
! 2578: }
! 2579: /* TODO walk the DTD if present */
! 2580:
! 2581: reader->curnode = (xmlNodePtr) cur;
! 2582: return(1);
! 2583: }
! 2584:
! 2585: /**
! 2586: * xmlTextReaderMoveToAttribute:
! 2587: * @reader: the xmlTextReaderPtr used
! 2588: * @name: the qualified name of the attribute.
! 2589: *
! 2590: * Moves the position of the current instance to the attribute with
! 2591: * the specified qualified name.
! 2592: *
! 2593: * Returns 1 in case of success, -1 in case of error, 0 if not found
! 2594: */
! 2595: int
! 2596: xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
! 2597: xmlChar *prefix = NULL;
! 2598: xmlChar *localname;
! 2599: xmlNsPtr ns;
! 2600: xmlAttrPtr prop;
! 2601:
! 2602: if ((reader == NULL) || (name == NULL))
! 2603: return(-1);
! 2604: if (reader->node == NULL)
! 2605: return(-1);
! 2606:
! 2607: /* TODO: handle the xmlDecl */
! 2608: if (reader->node->type != XML_ELEMENT_NODE)
! 2609: return(0);
! 2610:
! 2611: localname = xmlSplitQName2(name, &prefix);
! 2612: if (localname == NULL) {
! 2613: /*
! 2614: * Namespace default decl
! 2615: */
! 2616: if (xmlStrEqual(name, BAD_CAST "xmlns")) {
! 2617: ns = reader->node->nsDef;
! 2618: while (ns != NULL) {
! 2619: if (ns->prefix == NULL) {
! 2620: reader->curnode = (xmlNodePtr) ns;
! 2621: return(1);
! 2622: }
! 2623: ns = ns->next;
! 2624: }
! 2625: return(0);
! 2626: }
! 2627:
! 2628: prop = reader->node->properties;
! 2629: while (prop != NULL) {
! 2630: /*
! 2631: * One need to have
! 2632: * - same attribute names
! 2633: * - and the attribute carrying that namespace
! 2634: */
! 2635: if ((xmlStrEqual(prop->name, name)) &&
! 2636: ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
! 2637: reader->curnode = (xmlNodePtr) prop;
! 2638: return(1);
! 2639: }
! 2640: prop = prop->next;
! 2641: }
! 2642: return(0);
! 2643: }
! 2644:
! 2645: /*
! 2646: * Namespace default decl
! 2647: */
! 2648: if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
! 2649: ns = reader->node->nsDef;
! 2650: while (ns != NULL) {
! 2651: if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
! 2652: reader->curnode = (xmlNodePtr) ns;
! 2653: goto found;
! 2654: }
! 2655: ns = ns->next;
! 2656: }
! 2657: goto not_found;
! 2658: }
! 2659: prop = reader->node->properties;
! 2660: while (prop != NULL) {
! 2661: /*
! 2662: * One need to have
! 2663: * - same attribute names
! 2664: * - and the attribute carrying that namespace
! 2665: */
! 2666: if ((xmlStrEqual(prop->name, localname)) &&
! 2667: (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
! 2668: reader->curnode = (xmlNodePtr) prop;
! 2669: goto found;
! 2670: }
! 2671: prop = prop->next;
! 2672: }
! 2673: not_found:
! 2674: if (localname != NULL)
! 2675: xmlFree(localname);
! 2676: if (prefix != NULL)
! 2677: xmlFree(prefix);
! 2678: return(0);
! 2679:
! 2680: found:
! 2681: if (localname != NULL)
! 2682: xmlFree(localname);
! 2683: if (prefix != NULL)
! 2684: xmlFree(prefix);
! 2685: return(1);
! 2686: }
! 2687:
! 2688: /**
! 2689: * xmlTextReaderMoveToAttributeNs:
! 2690: * @reader: the xmlTextReaderPtr used
! 2691: * @localName: the local name of the attribute.
! 2692: * @namespaceURI: the namespace URI of the attribute.
! 2693: *
! 2694: * Moves the position of the current instance to the attribute with the
! 2695: * specified local name and namespace URI.
! 2696: *
! 2697: * Returns 1 in case of success, -1 in case of error, 0 if not found
! 2698: */
! 2699: int
! 2700: xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
! 2701: const xmlChar *localName, const xmlChar *namespaceURI) {
! 2702: xmlAttrPtr prop;
! 2703: xmlNodePtr node;
! 2704: xmlNsPtr ns;
! 2705: xmlChar *prefix = NULL;
! 2706:
! 2707: if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
! 2708: return(-1);
! 2709: if (reader->node == NULL)
! 2710: return(-1);
! 2711: if (reader->node->type != XML_ELEMENT_NODE)
! 2712: return(0);
! 2713: node = reader->node;
! 2714:
! 2715: if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
! 2716: if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
! 2717: prefix = BAD_CAST localName;
! 2718: }
! 2719: ns = reader->node->nsDef;
! 2720: while (ns != NULL) {
! 2721: if ((prefix == NULL && ns->prefix == NULL) ||
! 2722: ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
! 2723: reader->curnode = (xmlNodePtr) ns;
! 2724: return(1);
! 2725: }
! 2726: ns = ns->next;
! 2727: }
! 2728: return(0);
! 2729: }
! 2730:
! 2731: prop = node->properties;
! 2732: while (prop != NULL) {
! 2733: /*
! 2734: * One need to have
! 2735: * - same attribute names
! 2736: * - and the attribute carrying that namespace
! 2737: */
! 2738: if (xmlStrEqual(prop->name, localName) &&
! 2739: ((prop->ns != NULL) &&
! 2740: (xmlStrEqual(prop->ns->href, namespaceURI)))) {
! 2741: reader->curnode = (xmlNodePtr) prop;
! 2742: return(1);
! 2743: }
! 2744: prop = prop->next;
! 2745: }
! 2746: return(0);
! 2747: }
! 2748:
! 2749: /**
! 2750: * xmlTextReaderMoveToFirstAttribute:
! 2751: * @reader: the xmlTextReaderPtr used
! 2752: *
! 2753: * Moves the position of the current instance to the first attribute
! 2754: * associated with the current node.
! 2755: *
! 2756: * Returns 1 in case of success, -1 in case of error, 0 if not found
! 2757: */
! 2758: int
! 2759: xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
! 2760: if (reader == NULL)
! 2761: return(-1);
! 2762: if (reader->node == NULL)
! 2763: return(-1);
! 2764: if (reader->node->type != XML_ELEMENT_NODE)
! 2765: return(0);
! 2766:
! 2767: if (reader->node->nsDef != NULL) {
! 2768: reader->curnode = (xmlNodePtr) reader->node->nsDef;
! 2769: return(1);
! 2770: }
! 2771: if (reader->node->properties != NULL) {
! 2772: reader->curnode = (xmlNodePtr) reader->node->properties;
! 2773: return(1);
! 2774: }
! 2775: return(0);
! 2776: }
! 2777:
! 2778: /**
! 2779: * xmlTextReaderMoveToNextAttribute:
! 2780: * @reader: the xmlTextReaderPtr used
! 2781: *
! 2782: * Moves the position of the current instance to the next attribute
! 2783: * associated with the current node.
! 2784: *
! 2785: * Returns 1 in case of success, -1 in case of error, 0 if not found
! 2786: */
! 2787: int
! 2788: xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
! 2789: if (reader == NULL)
! 2790: return(-1);
! 2791: if (reader->node == NULL)
! 2792: return(-1);
! 2793: if (reader->node->type != XML_ELEMENT_NODE)
! 2794: return(0);
! 2795: if (reader->curnode == NULL)
! 2796: return(xmlTextReaderMoveToFirstAttribute(reader));
! 2797:
! 2798: if (reader->curnode->type == XML_NAMESPACE_DECL) {
! 2799: xmlNsPtr ns = (xmlNsPtr) reader->curnode;
! 2800: if (ns->next != NULL) {
! 2801: reader->curnode = (xmlNodePtr) ns->next;
! 2802: return(1);
! 2803: }
! 2804: if (reader->node->properties != NULL) {
! 2805: reader->curnode = (xmlNodePtr) reader->node->properties;
! 2806: return(1);
! 2807: }
! 2808: return(0);
! 2809: } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
! 2810: (reader->curnode->next != NULL)) {
! 2811: reader->curnode = reader->curnode->next;
! 2812: return(1);
! 2813: }
! 2814: return(0);
! 2815: }
! 2816:
! 2817: /**
! 2818: * xmlTextReaderMoveToElement:
! 2819: * @reader: the xmlTextReaderPtr used
! 2820: *
! 2821: * Moves the position of the current instance to the node that
! 2822: * contains the current Attribute node.
! 2823: *
! 2824: * Returns 1 in case of success, -1 in case of error, 0 if not moved
! 2825: */
! 2826: int
! 2827: xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
! 2828: if (reader == NULL)
! 2829: return(-1);
! 2830: if (reader->node == NULL)
! 2831: return(-1);
! 2832: if (reader->node->type != XML_ELEMENT_NODE)
! 2833: return(0);
! 2834: if (reader->curnode != NULL) {
! 2835: reader->curnode = NULL;
! 2836: return(1);
! 2837: }
! 2838: return(0);
! 2839: }
! 2840:
! 2841: /**
! 2842: * xmlTextReaderReadAttributeValue:
! 2843: * @reader: the xmlTextReaderPtr used
! 2844: *
! 2845: * Parses an attribute value into one or more Text and EntityReference nodes.
! 2846: *
! 2847: * Returns 1 in case of success, 0 if the reader was not positionned on an
! 2848: * ttribute node or all the attribute values have been read, or -1
! 2849: * in case of error.
! 2850: */
! 2851: int
! 2852: xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
! 2853: if (reader == NULL)
! 2854: return(-1);
! 2855: if (reader->node == NULL)
! 2856: return(-1);
! 2857: if (reader->curnode == NULL)
! 2858: return(0);
! 2859: if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
! 2860: if (reader->curnode->children == NULL)
! 2861: return(0);
! 2862: reader->curnode = reader->curnode->children;
! 2863: } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
! 2864: xmlNsPtr ns = (xmlNsPtr) reader->curnode;
! 2865:
! 2866: if (reader->faketext == NULL) {
! 2867: reader->faketext = xmlNewDocText(reader->node->doc,
! 2868: ns->href);
! 2869: } else {
! 2870: if ((reader->faketext->content != NULL) &&
! 2871: (reader->faketext->content !=
! 2872: (xmlChar *) &(reader->faketext->properties)))
! 2873: xmlFree(reader->faketext->content);
! 2874: reader->faketext->content = xmlStrdup(ns->href);
! 2875: }
! 2876: reader->curnode = reader->faketext;
! 2877: } else {
! 2878: if (reader->curnode->next == NULL)
! 2879: return(0);
! 2880: reader->curnode = reader->curnode->next;
! 2881: }
! 2882: return(1);
! 2883: }
! 2884:
! 2885: /**
! 2886: * xmlTextReaderConstEncoding:
! 2887: * @reader: the xmlTextReaderPtr used
! 2888: *
! 2889: * Determine the encoding of the document being read.
! 2890: *
! 2891: * Returns a string containing the encoding of the document or NULL in
! 2892: * case of error. The string is deallocated with the reader.
! 2893: */
! 2894: const xmlChar *
! 2895: xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
! 2896: xmlDocPtr doc = NULL;
! 2897: if (reader == NULL)
! 2898: return(NULL);
! 2899: if (reader->doc != NULL)
! 2900: doc = reader->doc;
! 2901: else if (reader->ctxt != NULL)
! 2902: doc = reader->ctxt->myDoc;
! 2903: if (doc == NULL)
! 2904: return(NULL);
! 2905:
! 2906: if (doc->encoding == NULL)
! 2907: return(NULL);
! 2908: else
! 2909: return(CONSTSTR(doc->encoding));
! 2910: }
! 2911:
! 2912:
! 2913: /************************************************************************
! 2914: * *
! 2915: * Acces API to the current node *
! 2916: * *
! 2917: ************************************************************************/
! 2918: /**
! 2919: * xmlTextReaderAttributeCount:
! 2920: * @reader: the xmlTextReaderPtr used
! 2921: *
! 2922: * Provides the number of attributes of the current node
! 2923: *
! 2924: * Returns 0 i no attributes, -1 in case of error or the attribute count
! 2925: */
! 2926: int
! 2927: xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
! 2928: int ret;
! 2929: xmlAttrPtr attr;
! 2930: xmlNsPtr ns;
! 2931: xmlNodePtr node;
! 2932:
! 2933: if (reader == NULL)
! 2934: return(-1);
! 2935: if (reader->node == NULL)
! 2936: return(0);
! 2937:
! 2938: if (reader->curnode != NULL)
! 2939: node = reader->curnode;
! 2940: else
! 2941: node = reader->node;
! 2942:
! 2943: if (node->type != XML_ELEMENT_NODE)
! 2944: return(0);
! 2945: if ((reader->state == XML_TEXTREADER_END) ||
! 2946: (reader->state == XML_TEXTREADER_BACKTRACK))
! 2947: return(0);
! 2948: ret = 0;
! 2949: attr = node->properties;
! 2950: while (attr != NULL) {
! 2951: ret++;
! 2952: attr = attr->next;
! 2953: }
! 2954: ns = node->nsDef;
! 2955: while (ns != NULL) {
! 2956: ret++;
! 2957: ns = ns->next;
! 2958: }
! 2959: return(ret);
! 2960: }
! 2961:
! 2962: /**
! 2963: * xmlTextReaderNodeType:
! 2964: * @reader: the xmlTextReaderPtr used
! 2965: *
! 2966: * Get the node type of the current node
! 2967: * Reference:
! 2968: * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
! 2969: *
! 2970: * Returns the xmlNodeType of the current node or -1 in case of error
! 2971: */
! 2972: int
! 2973: xmlTextReaderNodeType(xmlTextReaderPtr reader) {
! 2974: xmlNodePtr node;
! 2975:
! 2976: if (reader == NULL)
! 2977: return(-1);
! 2978: if (reader->node == NULL)
! 2979: return(XML_READER_TYPE_NONE);
! 2980: if (reader->curnode != NULL)
! 2981: node = reader->curnode;
! 2982: else
! 2983: node = reader->node;
! 2984: switch (node->type) {
! 2985: case XML_ELEMENT_NODE:
! 2986: if ((reader->state == XML_TEXTREADER_END) ||
! 2987: (reader->state == XML_TEXTREADER_BACKTRACK))
! 2988: return(XML_READER_TYPE_END_ELEMENT);
! 2989: return(XML_READER_TYPE_ELEMENT);
! 2990: case XML_NAMESPACE_DECL:
! 2991: case XML_ATTRIBUTE_NODE:
! 2992: return(XML_READER_TYPE_ATTRIBUTE);
! 2993: case XML_TEXT_NODE:
! 2994: if (xmlIsBlankNode(reader->node)) {
! 2995: if (xmlNodeGetSpacePreserve(reader->node))
! 2996: return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
! 2997: else
! 2998: return(XML_READER_TYPE_WHITESPACE);
! 2999: } else {
! 3000: return(XML_READER_TYPE_TEXT);
! 3001: }
! 3002: case XML_CDATA_SECTION_NODE:
! 3003: return(XML_READER_TYPE_CDATA);
! 3004: case XML_ENTITY_REF_NODE:
! 3005: return(XML_READER_TYPE_ENTITY_REFERENCE);
! 3006: case XML_ENTITY_NODE:
! 3007: return(XML_READER_TYPE_ENTITY);
! 3008: case XML_PI_NODE:
! 3009: return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
! 3010: case XML_COMMENT_NODE:
! 3011: return(XML_READER_TYPE_COMMENT);
! 3012: case XML_DOCUMENT_NODE:
! 3013: case XML_HTML_DOCUMENT_NODE:
! 3014: #ifdef LIBXML_DOCB_ENABLED
! 3015: case XML_DOCB_DOCUMENT_NODE:
! 3016: #endif
! 3017: return(XML_READER_TYPE_DOCUMENT);
! 3018: case XML_DOCUMENT_FRAG_NODE:
! 3019: return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
! 3020: case XML_NOTATION_NODE:
! 3021: return(XML_READER_TYPE_NOTATION);
! 3022: case XML_DOCUMENT_TYPE_NODE:
! 3023: case XML_DTD_NODE:
! 3024: return(XML_READER_TYPE_DOCUMENT_TYPE);
! 3025:
! 3026: case XML_ELEMENT_DECL:
! 3027: case XML_ATTRIBUTE_DECL:
! 3028: case XML_ENTITY_DECL:
! 3029: case XML_XINCLUDE_START:
! 3030: case XML_XINCLUDE_END:
! 3031: return(XML_READER_TYPE_NONE);
! 3032: }
! 3033: return(-1);
! 3034: }
! 3035:
! 3036: /**
! 3037: * xmlTextReaderIsEmptyElement:
! 3038: * @reader: the xmlTextReaderPtr used
! 3039: *
! 3040: * Check if the current node is empty
! 3041: *
! 3042: * Returns 1 if empty, 0 if not and -1 in case of error
! 3043: */
! 3044: int
! 3045: xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
! 3046: if ((reader == NULL) || (reader->node == NULL))
! 3047: return(-1);
! 3048: if (reader->node->type != XML_ELEMENT_NODE)
! 3049: return(0);
! 3050: if (reader->curnode != NULL)
! 3051: return(0);
! 3052: if (reader->node->children != NULL)
! 3053: return(0);
! 3054: if (reader->state == XML_TEXTREADER_END)
! 3055: return(0);
! 3056: if (reader->doc != NULL)
! 3057: return(1);
! 3058: #ifdef LIBXML_XINCLUDE_ENABLED
! 3059: if (reader->in_xinclude > 0)
! 3060: return(1);
! 3061: #endif
! 3062: return((reader->node->extra & NODE_IS_EMPTY) != 0);
! 3063: }
! 3064:
! 3065: /**
! 3066: * xmlTextReaderLocalName:
! 3067: * @reader: the xmlTextReaderPtr used
! 3068: *
! 3069: * The local name of the node.
! 3070: *
! 3071: * Returns the local name or NULL if not available,
! 3072: * if non NULL it need to be freed by the caller.
! 3073: */
! 3074: xmlChar *
! 3075: xmlTextReaderLocalName(xmlTextReaderPtr reader) {
! 3076: xmlNodePtr node;
! 3077: if ((reader == NULL) || (reader->node == NULL))
! 3078: return(NULL);
! 3079: if (reader->curnode != NULL)
! 3080: node = reader->curnode;
! 3081: else
! 3082: node = reader->node;
! 3083: if (node->type == XML_NAMESPACE_DECL) {
! 3084: xmlNsPtr ns = (xmlNsPtr) node;
! 3085: if (ns->prefix == NULL)
! 3086: return(xmlStrdup(BAD_CAST "xmlns"));
! 3087: else
! 3088: return(xmlStrdup(ns->prefix));
! 3089: }
! 3090: if ((node->type != XML_ELEMENT_NODE) &&
! 3091: (node->type != XML_ATTRIBUTE_NODE))
! 3092: return(xmlTextReaderName(reader));
! 3093: return(xmlStrdup(node->name));
! 3094: }
! 3095:
! 3096: /**
! 3097: * xmlTextReaderConstLocalName:
! 3098: * @reader: the xmlTextReaderPtr used
! 3099: *
! 3100: * The local name of the node.
! 3101: *
! 3102: * Returns the local name or NULL if not available, the
! 3103: * string will be deallocated with the reader.
! 3104: */
! 3105: const xmlChar *
! 3106: xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
! 3107: xmlNodePtr node;
! 3108: if ((reader == NULL) || (reader->node == NULL))
! 3109: return(NULL);
! 3110: if (reader->curnode != NULL)
! 3111: node = reader->curnode;
! 3112: else
! 3113: node = reader->node;
! 3114: if (node->type == XML_NAMESPACE_DECL) {
! 3115: xmlNsPtr ns = (xmlNsPtr) node;
! 3116: if (ns->prefix == NULL)
! 3117: return(CONSTSTR(BAD_CAST "xmlns"));
! 3118: else
! 3119: return(ns->prefix);
! 3120: }
! 3121: if ((node->type != XML_ELEMENT_NODE) &&
! 3122: (node->type != XML_ATTRIBUTE_NODE))
! 3123: return(xmlTextReaderConstName(reader));
! 3124: return(node->name);
! 3125: }
! 3126:
! 3127: /**
! 3128: * xmlTextReaderName:
! 3129: * @reader: the xmlTextReaderPtr used
! 3130: *
! 3131: * The qualified name of the node, equal to Prefix :LocalName.
! 3132: *
! 3133: * Returns the local name or NULL if not available,
! 3134: * if non NULL it need to be freed by the caller.
! 3135: */
! 3136: xmlChar *
! 3137: xmlTextReaderName(xmlTextReaderPtr reader) {
! 3138: xmlNodePtr node;
! 3139: xmlChar *ret;
! 3140:
! 3141: if ((reader == NULL) || (reader->node == NULL))
! 3142: return(NULL);
! 3143: if (reader->curnode != NULL)
! 3144: node = reader->curnode;
! 3145: else
! 3146: node = reader->node;
! 3147: switch (node->type) {
! 3148: case XML_ELEMENT_NODE:
! 3149: case XML_ATTRIBUTE_NODE:
! 3150: if ((node->ns == NULL) ||
! 3151: (node->ns->prefix == NULL))
! 3152: return(xmlStrdup(node->name));
! 3153:
! 3154: ret = xmlStrdup(node->ns->prefix);
! 3155: ret = xmlStrcat(ret, BAD_CAST ":");
! 3156: ret = xmlStrcat(ret, node->name);
! 3157: return(ret);
! 3158: case XML_TEXT_NODE:
! 3159: return(xmlStrdup(BAD_CAST "#text"));
! 3160: case XML_CDATA_SECTION_NODE:
! 3161: return(xmlStrdup(BAD_CAST "#cdata-section"));
! 3162: case XML_ENTITY_NODE:
! 3163: case XML_ENTITY_REF_NODE:
! 3164: return(xmlStrdup(node->name));
! 3165: case XML_PI_NODE:
! 3166: return(xmlStrdup(node->name));
! 3167: case XML_COMMENT_NODE:
! 3168: return(xmlStrdup(BAD_CAST "#comment"));
! 3169: case XML_DOCUMENT_NODE:
! 3170: case XML_HTML_DOCUMENT_NODE:
! 3171: #ifdef LIBXML_DOCB_ENABLED
! 3172: case XML_DOCB_DOCUMENT_NODE:
! 3173: #endif
! 3174: return(xmlStrdup(BAD_CAST "#document"));
! 3175: case XML_DOCUMENT_FRAG_NODE:
! 3176: return(xmlStrdup(BAD_CAST "#document-fragment"));
! 3177: case XML_NOTATION_NODE:
! 3178: return(xmlStrdup(node->name));
! 3179: case XML_DOCUMENT_TYPE_NODE:
! 3180: case XML_DTD_NODE:
! 3181: return(xmlStrdup(node->name));
! 3182: case XML_NAMESPACE_DECL: {
! 3183: xmlNsPtr ns = (xmlNsPtr) node;
! 3184:
! 3185: ret = xmlStrdup(BAD_CAST "xmlns");
! 3186: if (ns->prefix == NULL)
! 3187: return(ret);
! 3188: ret = xmlStrcat(ret, BAD_CAST ":");
! 3189: ret = xmlStrcat(ret, ns->prefix);
! 3190: return(ret);
! 3191: }
! 3192:
! 3193: case XML_ELEMENT_DECL:
! 3194: case XML_ATTRIBUTE_DECL:
! 3195: case XML_ENTITY_DECL:
! 3196: case XML_XINCLUDE_START:
! 3197: case XML_XINCLUDE_END:
! 3198: return(NULL);
! 3199: }
! 3200: return(NULL);
! 3201: }
! 3202:
! 3203: /**
! 3204: * xmlTextReaderConstName:
! 3205: * @reader: the xmlTextReaderPtr used
! 3206: *
! 3207: * The qualified name of the node, equal to Prefix :LocalName.
! 3208: *
! 3209: * Returns the local name or NULL if not available, the string is
! 3210: * deallocated with the reader.
! 3211: */
! 3212: const xmlChar *
! 3213: xmlTextReaderConstName(xmlTextReaderPtr reader) {
! 3214: xmlNodePtr node;
! 3215:
! 3216: if ((reader == NULL) || (reader->node == NULL))
! 3217: return(NULL);
! 3218: if (reader->curnode != NULL)
! 3219: node = reader->curnode;
! 3220: else
! 3221: node = reader->node;
! 3222: switch (node->type) {
! 3223: case XML_ELEMENT_NODE:
! 3224: case XML_ATTRIBUTE_NODE:
! 3225: if ((node->ns == NULL) ||
! 3226: (node->ns->prefix == NULL))
! 3227: return(node->name);
! 3228: return(CONSTQSTR(node->ns->prefix, node->name));
! 3229: case XML_TEXT_NODE:
! 3230: return(CONSTSTR(BAD_CAST "#text"));
! 3231: case XML_CDATA_SECTION_NODE:
! 3232: return(CONSTSTR(BAD_CAST "#cdata-section"));
! 3233: case XML_ENTITY_NODE:
! 3234: case XML_ENTITY_REF_NODE:
! 3235: return(CONSTSTR(node->name));
! 3236: case XML_PI_NODE:
! 3237: return(CONSTSTR(node->name));
! 3238: case XML_COMMENT_NODE:
! 3239: return(CONSTSTR(BAD_CAST "#comment"));
! 3240: case XML_DOCUMENT_NODE:
! 3241: case XML_HTML_DOCUMENT_NODE:
! 3242: #ifdef LIBXML_DOCB_ENABLED
! 3243: case XML_DOCB_DOCUMENT_NODE:
! 3244: #endif
! 3245: return(CONSTSTR(BAD_CAST "#document"));
! 3246: case XML_DOCUMENT_FRAG_NODE:
! 3247: return(CONSTSTR(BAD_CAST "#document-fragment"));
! 3248: case XML_NOTATION_NODE:
! 3249: return(CONSTSTR(node->name));
! 3250: case XML_DOCUMENT_TYPE_NODE:
! 3251: case XML_DTD_NODE:
! 3252: return(CONSTSTR(node->name));
! 3253: case XML_NAMESPACE_DECL: {
! 3254: xmlNsPtr ns = (xmlNsPtr) node;
! 3255:
! 3256: if (ns->prefix == NULL)
! 3257: return(CONSTSTR(BAD_CAST "xmlns"));
! 3258: return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
! 3259: }
! 3260:
! 3261: case XML_ELEMENT_DECL:
! 3262: case XML_ATTRIBUTE_DECL:
! 3263: case XML_ENTITY_DECL:
! 3264: case XML_XINCLUDE_START:
! 3265: case XML_XINCLUDE_END:
! 3266: return(NULL);
! 3267: }
! 3268: return(NULL);
! 3269: }
! 3270:
! 3271: /**
! 3272: * xmlTextReaderPrefix:
! 3273: * @reader: the xmlTextReaderPtr used
! 3274: *
! 3275: * A shorthand reference to the namespace associated with the node.
! 3276: *
! 3277: * Returns the prefix or NULL if not available,
! 3278: * if non NULL it need to be freed by the caller.
! 3279: */
! 3280: xmlChar *
! 3281: xmlTextReaderPrefix(xmlTextReaderPtr reader) {
! 3282: xmlNodePtr node;
! 3283: if ((reader == NULL) || (reader->node == NULL))
! 3284: return(NULL);
! 3285: if (reader->curnode != NULL)
! 3286: node = reader->curnode;
! 3287: else
! 3288: node = reader->node;
! 3289: if (node->type == XML_NAMESPACE_DECL) {
! 3290: xmlNsPtr ns = (xmlNsPtr) node;
! 3291: if (ns->prefix == NULL)
! 3292: return(NULL);
! 3293: return(xmlStrdup(BAD_CAST "xmlns"));
! 3294: }
! 3295: if ((node->type != XML_ELEMENT_NODE) &&
! 3296: (node->type != XML_ATTRIBUTE_NODE))
! 3297: return(NULL);
! 3298: if ((node->ns != NULL) && (node->ns->prefix != NULL))
! 3299: return(xmlStrdup(node->ns->prefix));
! 3300: return(NULL);
! 3301: }
! 3302:
! 3303: /**
! 3304: * xmlTextReaderConstPrefix:
! 3305: * @reader: the xmlTextReaderPtr used
! 3306: *
! 3307: * A shorthand reference to the namespace associated with the node.
! 3308: *
! 3309: * Returns the prefix or NULL if not available, the string is deallocated
! 3310: * with the reader.
! 3311: */
! 3312: const xmlChar *
! 3313: xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
! 3314: xmlNodePtr node;
! 3315: if ((reader == NULL) || (reader->node == NULL))
! 3316: return(NULL);
! 3317: if (reader->curnode != NULL)
! 3318: node = reader->curnode;
! 3319: else
! 3320: node = reader->node;
! 3321: if (node->type == XML_NAMESPACE_DECL) {
! 3322: xmlNsPtr ns = (xmlNsPtr) node;
! 3323: if (ns->prefix == NULL)
! 3324: return(NULL);
! 3325: return(CONSTSTR(BAD_CAST "xmlns"));
! 3326: }
! 3327: if ((node->type != XML_ELEMENT_NODE) &&
! 3328: (node->type != XML_ATTRIBUTE_NODE))
! 3329: return(NULL);
! 3330: if ((node->ns != NULL) && (node->ns->prefix != NULL))
! 3331: return(CONSTSTR(node->ns->prefix));
! 3332: return(NULL);
! 3333: }
! 3334:
! 3335: /**
! 3336: * xmlTextReaderNamespaceUri:
! 3337: * @reader: the xmlTextReaderPtr used
! 3338: *
! 3339: * The URI defining the namespace associated with the node.
! 3340: *
! 3341: * Returns the namespace URI or NULL if not available,
! 3342: * if non NULL it need to be freed by the caller.
! 3343: */
! 3344: xmlChar *
! 3345: xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
! 3346: xmlNodePtr node;
! 3347: if ((reader == NULL) || (reader->node == NULL))
! 3348: return(NULL);
! 3349: if (reader->curnode != NULL)
! 3350: node = reader->curnode;
! 3351: else
! 3352: node = reader->node;
! 3353: if (node->type == XML_NAMESPACE_DECL)
! 3354: return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
! 3355: if ((node->type != XML_ELEMENT_NODE) &&
! 3356: (node->type != XML_ATTRIBUTE_NODE))
! 3357: return(NULL);
! 3358: if (node->ns != NULL)
! 3359: return(xmlStrdup(node->ns->href));
! 3360: return(NULL);
! 3361: }
! 3362:
! 3363: /**
! 3364: * xmlTextReaderConstNamespaceUri:
! 3365: * @reader: the xmlTextReaderPtr used
! 3366: *
! 3367: * The URI defining the namespace associated with the node.
! 3368: *
! 3369: * Returns the namespace URI or NULL if not available, the string
! 3370: * will be deallocated with the reader
! 3371: */
! 3372: const xmlChar *
! 3373: xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
! 3374: xmlNodePtr node;
! 3375: if ((reader == NULL) || (reader->node == NULL))
! 3376: return(NULL);
! 3377: if (reader->curnode != NULL)
! 3378: node = reader->curnode;
! 3379: else
! 3380: node = reader->node;
! 3381: if (node->type == XML_NAMESPACE_DECL)
! 3382: return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
! 3383: if ((node->type != XML_ELEMENT_NODE) &&
! 3384: (node->type != XML_ATTRIBUTE_NODE))
! 3385: return(NULL);
! 3386: if (node->ns != NULL)
! 3387: return(CONSTSTR(node->ns->href));
! 3388: return(NULL);
! 3389: }
! 3390:
! 3391: /**
! 3392: * xmlTextReaderBaseUri:
! 3393: * @reader: the xmlTextReaderPtr used
! 3394: *
! 3395: * The base URI of the node.
! 3396: *
! 3397: * Returns the base URI or NULL if not available,
! 3398: * if non NULL it need to be freed by the caller.
! 3399: */
! 3400: xmlChar *
! 3401: xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
! 3402: if ((reader == NULL) || (reader->node == NULL))
! 3403: return(NULL);
! 3404: return(xmlNodeGetBase(NULL, reader->node));
! 3405: }
! 3406:
! 3407: /**
! 3408: * xmlTextReaderConstBaseUri:
! 3409: * @reader: the xmlTextReaderPtr used
! 3410: *
! 3411: * The base URI of the node.
! 3412: *
! 3413: * Returns the base URI or NULL if not available, the string
! 3414: * will be deallocated with the reader
! 3415: */
! 3416: const xmlChar *
! 3417: xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
! 3418: xmlChar *tmp;
! 3419: const xmlChar *ret;
! 3420:
! 3421: if ((reader == NULL) || (reader->node == NULL))
! 3422: return(NULL);
! 3423: tmp = xmlNodeGetBase(NULL, reader->node);
! 3424: if (tmp == NULL)
! 3425: return(NULL);
! 3426: ret = CONSTSTR(tmp);
! 3427: xmlFree(tmp);
! 3428: return(ret);
! 3429: }
! 3430:
! 3431: /**
! 3432: * xmlTextReaderDepth:
! 3433: * @reader: the xmlTextReaderPtr used
! 3434: *
! 3435: * The depth of the node in the tree.
! 3436: *
! 3437: * Returns the depth or -1 in case of error
! 3438: */
! 3439: int
! 3440: xmlTextReaderDepth(xmlTextReaderPtr reader) {
! 3441: if (reader == NULL)
! 3442: return(-1);
! 3443: if (reader->node == NULL)
! 3444: return(0);
! 3445:
! 3446: if (reader->curnode != NULL) {
! 3447: if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
! 3448: (reader->curnode->type == XML_NAMESPACE_DECL))
! 3449: return(reader->depth + 1);
! 3450: return(reader->depth + 2);
! 3451: }
! 3452: return(reader->depth);
! 3453: }
! 3454:
! 3455: /**
! 3456: * xmlTextReaderHasAttributes:
! 3457: * @reader: the xmlTextReaderPtr used
! 3458: *
! 3459: * Whether the node has attributes.
! 3460: *
! 3461: * Returns 1 if true, 0 if false, and -1 in case or error
! 3462: */
! 3463: int
! 3464: xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
! 3465: xmlNodePtr node;
! 3466: if (reader == NULL)
! 3467: return(-1);
! 3468: if (reader->node == NULL)
! 3469: return(0);
! 3470: if (reader->curnode != NULL)
! 3471: node = reader->curnode;
! 3472: else
! 3473: node = reader->node;
! 3474:
! 3475: if ((node->type == XML_ELEMENT_NODE) &&
! 3476: ((node->properties != NULL) || (node->nsDef != NULL)))
! 3477: return(1);
! 3478: /* TODO: handle the xmlDecl */
! 3479: return(0);
! 3480: }
! 3481:
! 3482: /**
! 3483: * xmlTextReaderHasValue:
! 3484: * @reader: the xmlTextReaderPtr used
! 3485: *
! 3486: * Whether the node can have a text value.
! 3487: *
! 3488: * Returns 1 if true, 0 if false, and -1 in case or error
! 3489: */
! 3490: int
! 3491: xmlTextReaderHasValue(xmlTextReaderPtr reader) {
! 3492: xmlNodePtr node;
! 3493: if (reader == NULL)
! 3494: return(-1);
! 3495: if (reader->node == NULL)
! 3496: return(0);
! 3497: if (reader->curnode != NULL)
! 3498: node = reader->curnode;
! 3499: else
! 3500: node = reader->node;
! 3501:
! 3502: switch (node->type) {
! 3503: case XML_ATTRIBUTE_NODE:
! 3504: case XML_TEXT_NODE:
! 3505: case XML_CDATA_SECTION_NODE:
! 3506: case XML_PI_NODE:
! 3507: case XML_COMMENT_NODE:
! 3508: case XML_NAMESPACE_DECL:
! 3509: return(1);
! 3510: default:
! 3511: break;
! 3512: }
! 3513: return(0);
! 3514: }
! 3515:
! 3516: /**
! 3517: * xmlTextReaderValue:
! 3518: * @reader: the xmlTextReaderPtr used
! 3519: *
! 3520: * Provides the text value of the node if present
! 3521: *
! 3522: * Returns the string or NULL if not available. The result must be deallocated
! 3523: * with xmlFree()
! 3524: */
! 3525: xmlChar *
! 3526: xmlTextReaderValue(xmlTextReaderPtr reader) {
! 3527: xmlNodePtr node;
! 3528: if (reader == NULL)
! 3529: return(NULL);
! 3530: if (reader->node == NULL)
! 3531: return(NULL);
! 3532: if (reader->curnode != NULL)
! 3533: node = reader->curnode;
! 3534: else
! 3535: node = reader->node;
! 3536:
! 3537: switch (node->type) {
! 3538: case XML_NAMESPACE_DECL:
! 3539: return(xmlStrdup(((xmlNsPtr) node)->href));
! 3540: case XML_ATTRIBUTE_NODE:{
! 3541: xmlAttrPtr attr = (xmlAttrPtr) node;
! 3542:
! 3543: if (attr->parent != NULL)
! 3544: return (xmlNodeListGetString
! 3545: (attr->parent->doc, attr->children, 1));
! 3546: else
! 3547: return (xmlNodeListGetString(NULL, attr->children, 1));
! 3548: break;
! 3549: }
! 3550: case XML_TEXT_NODE:
! 3551: case XML_CDATA_SECTION_NODE:
! 3552: case XML_PI_NODE:
! 3553: case XML_COMMENT_NODE:
! 3554: if (node->content != NULL)
! 3555: return (xmlStrdup(node->content));
! 3556: default:
! 3557: break;
! 3558: }
! 3559: return(NULL);
! 3560: }
! 3561:
! 3562: /**
! 3563: * xmlTextReaderConstValue:
! 3564: * @reader: the xmlTextReaderPtr used
! 3565: *
! 3566: * Provides the text value of the node if present
! 3567: *
! 3568: * Returns the string or NULL if not available. The result will be
! 3569: * deallocated on the next Read() operation.
! 3570: */
! 3571: const xmlChar *
! 3572: xmlTextReaderConstValue(xmlTextReaderPtr reader) {
! 3573: xmlNodePtr node;
! 3574: if (reader == NULL)
! 3575: return(NULL);
! 3576: if (reader->node == NULL)
! 3577: return(NULL);
! 3578: if (reader->curnode != NULL)
! 3579: node = reader->curnode;
! 3580: else
! 3581: node = reader->node;
! 3582:
! 3583: switch (node->type) {
! 3584: case XML_NAMESPACE_DECL:
! 3585: return(((xmlNsPtr) node)->href);
! 3586: case XML_ATTRIBUTE_NODE:{
! 3587: xmlAttrPtr attr = (xmlAttrPtr) node;
! 3588:
! 3589: if ((attr->children != NULL) &&
! 3590: (attr->children->type == XML_TEXT_NODE) &&
! 3591: (attr->children->next == NULL))
! 3592: return(attr->children->content);
! 3593: else {
! 3594: if (reader->buffer == NULL)
! 3595: reader->buffer = xmlBufferCreateSize(100);
! 3596: if (reader->buffer == NULL) {
! 3597: xmlGenericError(xmlGenericErrorContext,
! 3598: "xmlTextReaderSetup : malloc failed\n");
! 3599: return (NULL);
! 3600: }
! 3601: reader->buffer->use = 0;
! 3602: xmlNodeBufGetContent(reader->buffer, node);
! 3603: return(reader->buffer->content);
! 3604: }
! 3605: break;
! 3606: }
! 3607: case XML_TEXT_NODE:
! 3608: case XML_CDATA_SECTION_NODE:
! 3609: case XML_PI_NODE:
! 3610: case XML_COMMENT_NODE:
! 3611: return(node->content);
! 3612: default:
! 3613: break;
! 3614: }
! 3615: return(NULL);
! 3616: }
! 3617:
! 3618: /**
! 3619: * xmlTextReaderIsDefault:
! 3620: * @reader: the xmlTextReaderPtr used
! 3621: *
! 3622: * Whether an Attribute node was generated from the default value
! 3623: * defined in the DTD or schema.
! 3624: *
! 3625: * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
! 3626: */
! 3627: int
! 3628: xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
! 3629: if (reader == NULL)
! 3630: return(-1);
! 3631: return(0);
! 3632: }
! 3633:
! 3634: /**
! 3635: * xmlTextReaderQuoteChar:
! 3636: * @reader: the xmlTextReaderPtr used
! 3637: *
! 3638: * The quotation mark character used to enclose the value of an attribute.
! 3639: *
! 3640: * Returns " or ' and -1 in case of error
! 3641: */
! 3642: int
! 3643: xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
! 3644: if (reader == NULL)
! 3645: return(-1);
! 3646: /* TODO maybe lookup the attribute value for " first */
! 3647: return((int) '"');
! 3648: }
! 3649:
! 3650: /**
! 3651: * xmlTextReaderXmlLang:
! 3652: * @reader: the xmlTextReaderPtr used
! 3653: *
! 3654: * The xml:lang scope within which the node resides.
! 3655: *
! 3656: * Returns the xml:lang value or NULL if none exists.,
! 3657: * if non NULL it need to be freed by the caller.
! 3658: */
! 3659: xmlChar *
! 3660: xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
! 3661: if (reader == NULL)
! 3662: return(NULL);
! 3663: if (reader->node == NULL)
! 3664: return(NULL);
! 3665: return(xmlNodeGetLang(reader->node));
! 3666: }
! 3667:
! 3668: /**
! 3669: * xmlTextReaderConstXmlLang:
! 3670: * @reader: the xmlTextReaderPtr used
! 3671: *
! 3672: * The xml:lang scope within which the node resides.
! 3673: *
! 3674: * Returns the xml:lang value or NULL if none exists.
! 3675: */
! 3676: const xmlChar *
! 3677: xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
! 3678: xmlChar *tmp;
! 3679: const xmlChar *ret;
! 3680:
! 3681: if (reader == NULL)
! 3682: return(NULL);
! 3683: if (reader->node == NULL)
! 3684: return(NULL);
! 3685: tmp = xmlNodeGetLang(reader->node);
! 3686: if (tmp == NULL)
! 3687: return(NULL);
! 3688: ret = CONSTSTR(tmp);
! 3689: xmlFree(tmp);
! 3690: return(ret);
! 3691: }
! 3692:
! 3693: /**
! 3694: * xmlTextReaderConstString:
! 3695: * @reader: the xmlTextReaderPtr used
! 3696: * @str: the string to intern.
! 3697: *
! 3698: * Get an interned string from the reader, allows for example to
! 3699: * speedup string name comparisons
! 3700: *
! 3701: * Returns an interned copy of the string or NULL in case of error. The
! 3702: * string will be deallocated with the reader.
! 3703: */
! 3704: const xmlChar *
! 3705: xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
! 3706: if (reader == NULL)
! 3707: return(NULL);
! 3708: return(CONSTSTR(str));
! 3709: }
! 3710:
! 3711: /**
! 3712: * xmlTextReaderNormalization:
! 3713: * @reader: the xmlTextReaderPtr used
! 3714: *
! 3715: * The value indicating whether to normalize white space and attribute values.
! 3716: * Since attribute value and end of line normalizations are a MUST in the XML
! 3717: * specification only the value true is accepted. The broken bahaviour of
! 3718: * accepting out of range character entities like � is of course not
! 3719: * supported either.
! 3720: *
! 3721: * Returns 1 or -1 in case of error.
! 3722: */
! 3723: int
! 3724: xmlTextReaderNormalization(xmlTextReaderPtr reader) {
! 3725: if (reader == NULL)
! 3726: return(-1);
! 3727: return(1);
! 3728: }
! 3729:
! 3730: /************************************************************************
! 3731: * *
! 3732: * Extensions to the base APIs *
! 3733: * *
! 3734: ************************************************************************/
! 3735:
! 3736: /**
! 3737: * xmlTextReaderSetParserProp:
! 3738: * @reader: the xmlTextReaderPtr used
! 3739: * @prop: the xmlParserProperties to set
! 3740: * @value: usually 0 or 1 to (de)activate it
! 3741: *
! 3742: * Change the parser processing behaviour by changing some of its internal
! 3743: * properties. Note that some properties can only be changed before any
! 3744: * read has been done.
! 3745: *
! 3746: * Returns 0 if the call was successful, or -1 in case of error
! 3747: */
! 3748: int
! 3749: xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
! 3750: xmlParserProperties p = (xmlParserProperties) prop;
! 3751: xmlParserCtxtPtr ctxt;
! 3752:
! 3753: if ((reader == NULL) || (reader->ctxt == NULL))
! 3754: return(-1);
! 3755: ctxt = reader->ctxt;
! 3756:
! 3757: switch (p) {
! 3758: case XML_PARSER_LOADDTD:
! 3759: if (value != 0) {
! 3760: if (ctxt->loadsubset == 0) {
! 3761: if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
! 3762: return(-1);
! 3763: ctxt->loadsubset = XML_DETECT_IDS;
! 3764: }
! 3765: } else {
! 3766: ctxt->loadsubset = 0;
! 3767: }
! 3768: return(0);
! 3769: case XML_PARSER_DEFAULTATTRS:
! 3770: if (value != 0) {
! 3771: ctxt->loadsubset |= XML_COMPLETE_ATTRS;
! 3772: } else {
! 3773: if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
! 3774: ctxt->loadsubset -= XML_COMPLETE_ATTRS;
! 3775: }
! 3776: return(0);
! 3777: case XML_PARSER_VALIDATE:
! 3778: if (value != 0) {
! 3779: ctxt->validate = 1;
! 3780: reader->validate = XML_TEXTREADER_VALIDATE_DTD;
! 3781: } else {
! 3782: ctxt->validate = 0;
! 3783: }
! 3784: return(0);
! 3785: case XML_PARSER_SUBST_ENTITIES:
! 3786: if (value != 0) {
! 3787: ctxt->replaceEntities = 1;
! 3788: } else {
! 3789: ctxt->replaceEntities = 0;
! 3790: }
! 3791: return(0);
! 3792: }
! 3793: return(-1);
! 3794: }
! 3795:
! 3796: /**
! 3797: * xmlTextReaderGetParserProp:
! 3798: * @reader: the xmlTextReaderPtr used
! 3799: * @prop: the xmlParserProperties to get
! 3800: *
! 3801: * Read the parser internal property.
! 3802: *
! 3803: * Returns the value, usually 0 or 1, or -1 in case of error.
! 3804: */
! 3805: int
! 3806: xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
! 3807: xmlParserProperties p = (xmlParserProperties) prop;
! 3808: xmlParserCtxtPtr ctxt;
! 3809:
! 3810: if ((reader == NULL) || (reader->ctxt == NULL))
! 3811: return(-1);
! 3812: ctxt = reader->ctxt;
! 3813:
! 3814: switch (p) {
! 3815: case XML_PARSER_LOADDTD:
! 3816: if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
! 3817: return(1);
! 3818: return(0);
! 3819: case XML_PARSER_DEFAULTATTRS:
! 3820: if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
! 3821: return(1);
! 3822: return(0);
! 3823: case XML_PARSER_VALIDATE:
! 3824: return(reader->validate);
! 3825: case XML_PARSER_SUBST_ENTITIES:
! 3826: return(ctxt->replaceEntities);
! 3827: }
! 3828: return(-1);
! 3829: }
! 3830:
! 3831:
! 3832: /**
! 3833: * xmlTextReaderGetParserLineNumber:
! 3834: * @reader: the user data (XML reader context)
! 3835: *
! 3836: * Provide the line number of the current parsing point.
! 3837: *
! 3838: * Returns an int or 0 if not available
! 3839: */
! 3840: int
! 3841: xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
! 3842: {
! 3843: if ((reader == NULL) || (reader->ctxt == NULL) ||
! 3844: (reader->ctxt->input == NULL)) {
! 3845: return (0);
! 3846: }
! 3847: return (reader->ctxt->input->line);
! 3848: }
! 3849:
! 3850: /**
! 3851: * xmlTextReaderGetParserColumnNumber:
! 3852: * @reader: the user data (XML reader context)
! 3853: *
! 3854: * Provide the column number of the current parsing point.
! 3855: *
! 3856: * Returns an int or 0 if not available
! 3857: */
! 3858: int
! 3859: xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
! 3860: {
! 3861: if ((reader == NULL) || (reader->ctxt == NULL) ||
! 3862: (reader->ctxt->input == NULL)) {
! 3863: return (0);
! 3864: }
! 3865: return (reader->ctxt->input->col);
! 3866: }
! 3867:
! 3868: /**
! 3869: * xmlTextReaderCurrentNode:
! 3870: * @reader: the xmlTextReaderPtr used
! 3871: *
! 3872: * Hacking interface allowing to get the xmlNodePtr correponding to the
! 3873: * current node being accessed by the xmlTextReader. This is dangerous
! 3874: * because the underlying node may be destroyed on the next Reads.
! 3875: *
! 3876: * Returns the xmlNodePtr or NULL in case of error.
! 3877: */
! 3878: xmlNodePtr
! 3879: xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
! 3880: if (reader == NULL)
! 3881: return(NULL);
! 3882:
! 3883: if (reader->curnode != NULL)
! 3884: return(reader->curnode);
! 3885: return(reader->node);
! 3886: }
! 3887:
! 3888: /**
! 3889: * xmlTextReaderPreserve:
! 3890: * @reader: the xmlTextReaderPtr used
! 3891: *
! 3892: * This tells the XML Reader to preserve the current node.
! 3893: * The caller must also use xmlTextReaderCurrentDoc() to
! 3894: * keep an handle on the resulting document once parsing has finished
! 3895: *
! 3896: * Returns the xmlNodePtr or NULL in case of error.
! 3897: */
! 3898: xmlNodePtr
! 3899: xmlTextReaderPreserve(xmlTextReaderPtr reader) {
! 3900: xmlNodePtr cur, parent;
! 3901:
! 3902: if (reader == NULL)
! 3903: return(NULL);
! 3904:
! 3905: if (reader->curnode != NULL)
! 3906: cur = reader->curnode;
! 3907: else
! 3908: cur = reader->node;
! 3909: if (cur == NULL)
! 3910: return(NULL);
! 3911:
! 3912: if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
! 3913: cur->extra |= NODE_IS_PRESERVED;
! 3914: cur->extra |= NODE_IS_SPRESERVED;
! 3915: }
! 3916: reader->preserves++;
! 3917:
! 3918: parent = cur->parent;;
! 3919: while (parent != NULL) {
! 3920: if (parent->type == XML_ELEMENT_NODE)
! 3921: parent->extra |= NODE_IS_PRESERVED;
! 3922: parent = parent->parent;
! 3923: }
! 3924: return(cur);
! 3925: }
! 3926:
! 3927: #ifdef LIBXML_PATTERN_ENABLED
! 3928: /**
! 3929: * xmlTextReaderPreservePattern:
! 3930: * @reader: the xmlTextReaderPtr used
! 3931: * @pattern: an XPath subset pattern
! 3932: * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
! 3933: *
! 3934: * This tells the XML Reader to preserve all nodes matched by the
! 3935: * pattern. The caller must also use xmlTextReaderCurrentDoc() to
! 3936: * keep an handle on the resulting document once parsing has finished
! 3937: *
! 3938: * Returns a positive number in case of success and -1 in case of error
! 3939: */
! 3940: int
! 3941: xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
! 3942: const xmlChar **namespaces)
! 3943: {
! 3944: xmlPatternPtr comp;
! 3945:
! 3946: if ((reader == NULL) || (pattern == NULL))
! 3947: return(-1);
! 3948:
! 3949: comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
! 3950: if (comp == NULL)
! 3951: return(-1);
! 3952:
! 3953: if (reader->patternMax <= 0) {
! 3954: reader->patternMax = 4;
! 3955: reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
! 3956: sizeof(reader->patternTab[0]));
! 3957: if (reader->patternTab == NULL) {
! 3958: xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
! 3959: return (-1);
! 3960: }
! 3961: }
! 3962: if (reader->patternNr >= reader->patternMax) {
! 3963: xmlPatternPtr *tmp;
! 3964: reader->patternMax *= 2;
! 3965: tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
! 3966: reader->patternMax *
! 3967: sizeof(reader->patternTab[0]));
! 3968: if (tmp == NULL) {
! 3969: xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
! 3970: reader->patternMax /= 2;
! 3971: return (-1);
! 3972: }
! 3973: reader->patternTab = tmp;
! 3974: }
! 3975: reader->patternTab[reader->patternNr] = comp;
! 3976: return(reader->patternNr++);
! 3977: }
! 3978: #endif
! 3979:
! 3980: /**
! 3981: * xmlTextReaderCurrentDoc:
! 3982: * @reader: the xmlTextReaderPtr used
! 3983: *
! 3984: * Hacking interface allowing to get the xmlDocPtr correponding to the
! 3985: * current document being accessed by the xmlTextReader.
! 3986: * NOTE: as a result of this call, the reader will not destroy the
! 3987: * associated XML document and calling xmlFreeDoc() on the result
! 3988: * is needed once the reader parsing has finished.
! 3989: *
! 3990: * Returns the xmlDocPtr or NULL in case of error.
! 3991: */
! 3992: xmlDocPtr
! 3993: xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
! 3994: if (reader == NULL)
! 3995: return(NULL);
! 3996: if (reader->doc != NULL)
! 3997: return(reader->doc);
! 3998: if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
! 3999: return(NULL);
! 4000:
! 4001: reader->preserve = 1;
! 4002: return(reader->ctxt->myDoc);
! 4003: }
! 4004:
! 4005: #ifdef LIBXML_SCHEMAS_ENABLED
! 4006: static char *xmlTextReaderBuildMessage(const char *msg, va_list ap);
! 4007:
! 4008: static void XMLCDECL
! 4009: xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
! 4010:
! 4011: static void XMLCDECL
! 4012: xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
! 4013:
! 4014: static void XMLCDECL
! 4015: xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
! 4016: {
! 4017: xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
! 4018:
! 4019: char *str;
! 4020:
! 4021: va_list ap;
! 4022:
! 4023: va_start(ap, msg);
! 4024: str = xmlTextReaderBuildMessage(msg, ap);
! 4025: if (!reader->errorFunc) {
! 4026: xmlTextReaderValidityError(ctx, "%s", str);
! 4027: } else {
! 4028: reader->errorFunc(reader->errorFuncArg, str,
! 4029: XML_PARSER_SEVERITY_VALIDITY_ERROR,
! 4030: NULL /* locator */ );
! 4031: }
! 4032: if (str != NULL)
! 4033: xmlFree(str);
! 4034: va_end(ap);
! 4035: }
! 4036:
! 4037: static void XMLCDECL
! 4038: xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
! 4039: {
! 4040: xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
! 4041:
! 4042: char *str;
! 4043:
! 4044: va_list ap;
! 4045:
! 4046: va_start(ap, msg);
! 4047: str = xmlTextReaderBuildMessage(msg, ap);
! 4048: if (!reader->errorFunc) {
! 4049: xmlTextReaderValidityWarning(ctx, "%s", str);
! 4050: } else {
! 4051: reader->errorFunc(reader->errorFuncArg, str,
! 4052: XML_PARSER_SEVERITY_VALIDITY_WARNING,
! 4053: NULL /* locator */ );
! 4054: }
! 4055: if (str != NULL)
! 4056: xmlFree(str);
! 4057: va_end(ap);
! 4058: }
! 4059:
! 4060: static void
! 4061: xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
! 4062:
! 4063: static void
! 4064: xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
! 4065: {
! 4066: xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
! 4067:
! 4068: if (reader->sErrorFunc) {
! 4069: reader->sErrorFunc(reader->errorFuncArg, error);
! 4070: } else {
! 4071: xmlTextReaderStructuredError(reader, error);
! 4072: }
! 4073: }
! 4074: /**
! 4075: * xmlTextReaderRelaxNGSetSchema:
! 4076: * @reader: the xmlTextReaderPtr used
! 4077: * @schema: a precompiled RelaxNG schema
! 4078: *
! 4079: * Use RelaxNG to validate the document as it is processed.
! 4080: * Activation is only possible before the first Read().
! 4081: * if @schema is NULL, then RelaxNG validation is desactivated.
! 4082: @ The @schema should not be freed until the reader is deallocated
! 4083: * or its use has been deactivated.
! 4084: *
! 4085: * Returns 0 in case the RelaxNG validation could be (des)activated and
! 4086: * -1 in case of error.
! 4087: */
! 4088: int
! 4089: xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
! 4090: if (reader == NULL)
! 4091: return(-1);
! 4092: if (schema == NULL) {
! 4093: if (reader->rngSchemas != NULL) {
! 4094: xmlRelaxNGFree(reader->rngSchemas);
! 4095: reader->rngSchemas = NULL;
! 4096: }
! 4097: if (reader->rngValidCtxt != NULL) {
! 4098: xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
! 4099: reader->rngValidCtxt = NULL;
! 4100: }
! 4101: return(0);
! 4102: }
! 4103: if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
! 4104: return(-1);
! 4105: if (reader->rngSchemas != NULL) {
! 4106: xmlRelaxNGFree(reader->rngSchemas);
! 4107: reader->rngSchemas = NULL;
! 4108: }
! 4109: if (reader->rngValidCtxt != NULL) {
! 4110: xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
! 4111: reader->rngValidCtxt = NULL;
! 4112: }
! 4113: reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
! 4114: if (reader->rngValidCtxt == NULL)
! 4115: return(-1);
! 4116: if (reader->errorFunc != NULL) {
! 4117: xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
! 4118: xmlTextReaderValidityErrorRelay,
! 4119: xmlTextReaderValidityWarningRelay,
! 4120: reader);
! 4121: }
! 4122: if (reader->sErrorFunc != NULL) {
! 4123: xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
! 4124: xmlTextReaderValidityStructuredRelay,
! 4125: reader);
! 4126: }
! 4127: reader->rngValidErrors = 0;
! 4128: reader->rngFullNode = NULL;
! 4129: reader->validate = XML_TEXTREADER_VALIDATE_RNG;
! 4130: return(0);
! 4131: }
! 4132:
! 4133: /**
! 4134: * xmlTextReaderSetSchema:
! 4135: * @reader: the xmlTextReaderPtr used
! 4136: * @schema: a precompiled Schema schema
! 4137: *
! 4138: * Use XSD Schema to validate the document as it is processed.
! 4139: * Activation is only possible before the first Read().
! 4140: * if @schema is NULL, then Schema validation is desactivated.
! 4141: @ The @schema should not be freed until the reader is deallocated
! 4142: * or its use has been deactivated.
! 4143: *
! 4144: * Returns 0 in case the Schema validation could be (des)activated and
! 4145: * -1 in case of error.
! 4146: */
! 4147: int
! 4148: xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
! 4149: if (reader == NULL)
! 4150: return(-1);
! 4151: if (schema == NULL) {
! 4152: if (reader->xsdPlug != NULL) {
! 4153: xmlSchemaSAXUnplug(reader->xsdPlug);
! 4154: reader->xsdPlug = NULL;
! 4155: }
! 4156: if (reader->xsdValidCtxt != NULL) {
! 4157: if (! reader->xsdPreserveCtxt)
! 4158: xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
! 4159: reader->xsdValidCtxt = NULL;
! 4160: }
! 4161: reader->xsdPreserveCtxt = 0;
! 4162: if (reader->xsdSchemas != NULL) {
! 4163: xmlSchemaFree(reader->xsdSchemas);
! 4164: reader->xsdSchemas = NULL;
! 4165: }
! 4166: return(0);
! 4167: }
! 4168: if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
! 4169: return(-1);
! 4170: if (reader->xsdPlug != NULL) {
! 4171: xmlSchemaSAXUnplug(reader->xsdPlug);
! 4172: reader->xsdPlug = NULL;
! 4173: }
! 4174: if (reader->xsdValidCtxt != NULL) {
! 4175: if (! reader->xsdPreserveCtxt)
! 4176: xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
! 4177: reader->xsdValidCtxt = NULL;
! 4178: }
! 4179: reader->xsdPreserveCtxt = 0;
! 4180: if (reader->xsdSchemas != NULL) {
! 4181: xmlSchemaFree(reader->xsdSchemas);
! 4182: reader->xsdSchemas = NULL;
! 4183: }
! 4184: reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
! 4185: if (reader->xsdValidCtxt == NULL) {
! 4186: xmlSchemaFree(reader->xsdSchemas);
! 4187: reader->xsdSchemas = NULL;
! 4188: return(-1);
! 4189: }
! 4190: reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
! 4191: &(reader->ctxt->sax),
! 4192: &(reader->ctxt->userData));
! 4193: if (reader->xsdPlug == NULL) {
! 4194: xmlSchemaFree(reader->xsdSchemas);
! 4195: reader->xsdSchemas = NULL;
! 4196: xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
! 4197: reader->xsdValidCtxt = NULL;
! 4198: return(-1);
! 4199: }
! 4200: if (reader->errorFunc != NULL) {
! 4201: xmlSchemaSetValidErrors(reader->xsdValidCtxt,
! 4202: xmlTextReaderValidityErrorRelay,
! 4203: xmlTextReaderValidityWarningRelay,
! 4204: reader);
! 4205: }
! 4206: if (reader->sErrorFunc != NULL) {
! 4207: xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
! 4208: xmlTextReaderValidityStructuredRelay,
! 4209: reader);
! 4210: }
! 4211: reader->xsdValidErrors = 0;
! 4212: reader->validate = XML_TEXTREADER_VALIDATE_XSD;
! 4213: return(0);
! 4214: }
! 4215:
! 4216: /**
! 4217: * xmlTextReaderRelaxNGValidate:
! 4218: * @reader: the xmlTextReaderPtr used
! 4219: * @rng: the path to a RelaxNG schema or NULL
! 4220: *
! 4221: * Use RelaxNG to validate the document as it is processed.
! 4222: * Activation is only possible before the first Read().
! 4223: * if @rng is NULL, then RelaxNG validation is deactivated.
! 4224: *
! 4225: * Returns 0 in case the RelaxNG validation could be (de)activated and
! 4226: * -1 in case of error.
! 4227: */
! 4228: int
! 4229: xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
! 4230: xmlRelaxNGParserCtxtPtr ctxt;
! 4231:
! 4232: if (reader == NULL)
! 4233: return(-1);
! 4234:
! 4235: if (rng == NULL) {
! 4236: if (reader->rngValidCtxt != NULL) {
! 4237: xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
! 4238: reader->rngValidCtxt = NULL;
! 4239: }
! 4240: if (reader->rngSchemas != NULL) {
! 4241: xmlRelaxNGFree(reader->rngSchemas);
! 4242: reader->rngSchemas = NULL;
! 4243: }
! 4244: return(0);
! 4245: }
! 4246: if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
! 4247: return(-1);
! 4248: if (reader->rngSchemas != NULL) {
! 4249: xmlRelaxNGFree(reader->rngSchemas);
! 4250: reader->rngSchemas = NULL;
! 4251: }
! 4252: if (reader->rngValidCtxt != NULL) {
! 4253: xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
! 4254: reader->rngValidCtxt = NULL;
! 4255: }
! 4256: ctxt = xmlRelaxNGNewParserCtxt(rng);
! 4257: if (reader->errorFunc != NULL) {
! 4258: xmlRelaxNGSetParserErrors(ctxt,
! 4259: xmlTextReaderValidityErrorRelay,
! 4260: xmlTextReaderValidityWarningRelay,
! 4261: reader);
! 4262: }
! 4263: if (reader->sErrorFunc != NULL) {
! 4264: xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
! 4265: xmlTextReaderValidityStructuredRelay,
! 4266: reader);
! 4267: }
! 4268: reader->rngSchemas = xmlRelaxNGParse(ctxt);
! 4269: xmlRelaxNGFreeParserCtxt(ctxt);
! 4270: if (reader->rngSchemas == NULL)
! 4271: return(-1);
! 4272: reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
! 4273: if (reader->rngValidCtxt == NULL) {
! 4274: xmlRelaxNGFree(reader->rngSchemas);
! 4275: reader->rngSchemas = NULL;
! 4276: return(-1);
! 4277: }
! 4278: if (reader->errorFunc != NULL) {
! 4279: xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
! 4280: xmlTextReaderValidityErrorRelay,
! 4281: xmlTextReaderValidityWarningRelay,
! 4282: reader);
! 4283: }
! 4284: if (reader->sErrorFunc != NULL) {
! 4285: xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
! 4286: xmlTextReaderValidityStructuredRelay,
! 4287: reader);
! 4288: }
! 4289: reader->rngValidErrors = 0;
! 4290: reader->rngFullNode = NULL;
! 4291: reader->validate = XML_TEXTREADER_VALIDATE_RNG;
! 4292: return(0);
! 4293: }
! 4294:
! 4295: /**
! 4296: * xmlTextReaderSchemaValidateInternal:
! 4297: * @reader: the xmlTextReaderPtr used
! 4298: * @xsd: the path to a W3C XSD schema or NULL
! 4299: * @ctxt: the XML Schema validation context or NULL
! 4300: * @options: options (not used yet)
! 4301: *
! 4302: * Validate the document as it is processed using XML Schema.
! 4303: * Activation is only possible before the first Read().
! 4304: * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
! 4305: *
! 4306: * Returns 0 in case the schemas validation could be (de)activated and
! 4307: * -1 in case of error.
! 4308: */
! 4309: static int
! 4310: xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
! 4311: const char *xsd,
! 4312: xmlSchemaValidCtxtPtr ctxt,
! 4313: int options ATTRIBUTE_UNUSED)
! 4314: {
! 4315: if (reader == NULL)
! 4316: return(-1);
! 4317:
! 4318: if ((xsd != NULL) && (ctxt != NULL))
! 4319: return(-1);
! 4320:
! 4321: if (((xsd != NULL) || (ctxt != NULL)) &&
! 4322: ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
! 4323: (reader->ctxt == NULL)))
! 4324: return(-1);
! 4325:
! 4326: /* Cleanup previous validation stuff. */
! 4327: if (reader->xsdPlug != NULL) {
! 4328: xmlSchemaSAXUnplug(reader->xsdPlug);
! 4329: reader->xsdPlug = NULL;
! 4330: }
! 4331: if (reader->xsdValidCtxt != NULL) {
! 4332: if (! reader->xsdPreserveCtxt)
! 4333: xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
! 4334: reader->xsdValidCtxt = NULL;
! 4335: }
! 4336: reader->xsdPreserveCtxt = 0;
! 4337: if (reader->xsdSchemas != NULL) {
! 4338: xmlSchemaFree(reader->xsdSchemas);
! 4339: reader->xsdSchemas = NULL;
! 4340: }
! 4341:
! 4342: if ((xsd == NULL) && (ctxt == NULL)) {
! 4343: /* We just want to deactivate the validation, so get out. */
! 4344: return(0);
! 4345: }
! 4346:
! 4347: if (xsd != NULL) {
! 4348: xmlSchemaParserCtxtPtr pctxt;
! 4349: /* Parse the schema and create validation environment. */
! 4350: pctxt = xmlSchemaNewParserCtxt(xsd);
! 4351: if (reader->errorFunc != NULL) {
! 4352: xmlSchemaSetParserErrors(pctxt,
! 4353: xmlTextReaderValidityErrorRelay,
! 4354: xmlTextReaderValidityWarningRelay,
! 4355: reader);
! 4356: }
! 4357: reader->xsdSchemas = xmlSchemaParse(pctxt);
! 4358: xmlSchemaFreeParserCtxt(pctxt);
! 4359: if (reader->xsdSchemas == NULL)
! 4360: return(-1);
! 4361: reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
! 4362: if (reader->xsdValidCtxt == NULL) {
! 4363: xmlSchemaFree(reader->xsdSchemas);
! 4364: reader->xsdSchemas = NULL;
! 4365: return(-1);
! 4366: }
! 4367: reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
! 4368: &(reader->ctxt->sax),
! 4369: &(reader->ctxt->userData));
! 4370: if (reader->xsdPlug == NULL) {
! 4371: xmlSchemaFree(reader->xsdSchemas);
! 4372: reader->xsdSchemas = NULL;
! 4373: xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
! 4374: reader->xsdValidCtxt = NULL;
! 4375: return(-1);
! 4376: }
! 4377: } else {
! 4378: /* Use the given validation context. */
! 4379: reader->xsdValidCtxt = ctxt;
! 4380: reader->xsdPreserveCtxt = 1;
! 4381: reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
! 4382: &(reader->ctxt->sax),
! 4383: &(reader->ctxt->userData));
! 4384: if (reader->xsdPlug == NULL) {
! 4385: reader->xsdValidCtxt = NULL;
! 4386: reader->xsdPreserveCtxt = 0;
! 4387: return(-1);
! 4388: }
! 4389: }
! 4390: /*
! 4391: * Redirect the validation context's error channels to use
! 4392: * the reader channels.
! 4393: * TODO: In case the user provides the validation context we
! 4394: * could make this redirection optional.
! 4395: */
! 4396: if (reader->errorFunc != NULL) {
! 4397: xmlSchemaSetValidErrors(reader->xsdValidCtxt,
! 4398: xmlTextReaderValidityErrorRelay,
! 4399: xmlTextReaderValidityWarningRelay,
! 4400: reader);
! 4401: }
! 4402: if (reader->sErrorFunc != NULL) {
! 4403: xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
! 4404: xmlTextReaderValidityStructuredRelay,
! 4405: reader);
! 4406: }
! 4407: reader->xsdValidErrors = 0;
! 4408: reader->validate = XML_TEXTREADER_VALIDATE_XSD;
! 4409: return(0);
! 4410: }
! 4411:
! 4412: /**
! 4413: * xmlTextReaderSchemaValidateCtxt:
! 4414: * @reader: the xmlTextReaderPtr used
! 4415: * @ctxt: the XML Schema validation context or NULL
! 4416: * @options: options (not used yet)
! 4417: *
! 4418: * Use W3C XSD schema context to validate the document as it is processed.
! 4419: * Activation is only possible before the first Read().
! 4420: * If @ctxt is NULL, then XML Schema validation is deactivated.
! 4421: *
! 4422: * Returns 0 in case the schemas validation could be (de)activated and
! 4423: * -1 in case of error.
! 4424: */
! 4425: int
! 4426: xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
! 4427: xmlSchemaValidCtxtPtr ctxt,
! 4428: int options)
! 4429: {
! 4430: return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
! 4431: }
! 4432:
! 4433: /**
! 4434: * xmlTextReaderSchemaValidate:
! 4435: * @reader: the xmlTextReaderPtr used
! 4436: * @xsd: the path to a W3C XSD schema or NULL
! 4437: *
! 4438: * Use W3C XSD schema to validate the document as it is processed.
! 4439: * Activation is only possible before the first Read().
! 4440: * If @xsd is NULL, then XML Schema validation is deactivated.
! 4441: *
! 4442: * Returns 0 in case the schemas validation could be (de)activated and
! 4443: * -1 in case of error.
! 4444: */
! 4445: int
! 4446: xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
! 4447: {
! 4448: return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
! 4449: }
! 4450: #endif
! 4451:
! 4452: /**
! 4453: * xmlTextReaderIsNamespaceDecl:
! 4454: * @reader: the xmlTextReaderPtr used
! 4455: *
! 4456: * Determine whether the current node is a namespace declaration
! 4457: * rather than a regular attribute.
! 4458: *
! 4459: * Returns 1 if the current node is a namespace declaration, 0 if it
! 4460: * is a regular attribute or other type of node, or -1 in case of
! 4461: * error.
! 4462: */
! 4463: int
! 4464: xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
! 4465: xmlNodePtr node;
! 4466: if (reader == NULL)
! 4467: return(-1);
! 4468: if (reader->node == NULL)
! 4469: return(-1);
! 4470: if (reader->curnode != NULL)
! 4471: node = reader->curnode;
! 4472: else
! 4473: node = reader->node;
! 4474:
! 4475: if (XML_NAMESPACE_DECL == node->type)
! 4476: return(1);
! 4477: else
! 4478: return(0);
! 4479: }
! 4480:
! 4481: /**
! 4482: * xmlTextReaderConstXmlVersion:
! 4483: * @reader: the xmlTextReaderPtr used
! 4484: *
! 4485: * Determine the XML version of the document being read.
! 4486: *
! 4487: * Returns a string containing the XML version of the document or NULL
! 4488: * in case of error. The string is deallocated with the reader.
! 4489: */
! 4490: const xmlChar *
! 4491: xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
! 4492: xmlDocPtr doc = NULL;
! 4493: if (reader == NULL)
! 4494: return(NULL);
! 4495: if (reader->doc != NULL)
! 4496: doc = reader->doc;
! 4497: else if (reader->ctxt != NULL)
! 4498: doc = reader->ctxt->myDoc;
! 4499: if (doc == NULL)
! 4500: return(NULL);
! 4501:
! 4502: if (doc->version == NULL)
! 4503: return(NULL);
! 4504: else
! 4505: return(CONSTSTR(doc->version));
! 4506: }
! 4507:
! 4508: /**
! 4509: * xmlTextReaderStandalone:
! 4510: * @reader: the xmlTextReaderPtr used
! 4511: *
! 4512: * Determine the standalone status of the document being read.
! 4513: *
! 4514: * Returns 1 if the document was declared to be standalone, 0 if it
! 4515: * was declared to be not standalone, or -1 if the document did not
! 4516: * specify its standalone status or in case of error.
! 4517: */
! 4518: int
! 4519: xmlTextReaderStandalone(xmlTextReaderPtr reader) {
! 4520: xmlDocPtr doc = NULL;
! 4521: if (reader == NULL)
! 4522: return(-1);
! 4523: if (reader->doc != NULL)
! 4524: doc = reader->doc;
! 4525: else if (reader->ctxt != NULL)
! 4526: doc = reader->ctxt->myDoc;
! 4527: if (doc == NULL)
! 4528: return(-1);
! 4529:
! 4530: return(doc->standalone);
! 4531: }
! 4532:
! 4533: /************************************************************************
! 4534: * *
! 4535: * Error Handling Extensions *
! 4536: * *
! 4537: ************************************************************************/
! 4538:
! 4539: /* helper to build a xmlMalloc'ed string from a format and va_list */
! 4540: static char *
! 4541: xmlTextReaderBuildMessage(const char *msg, va_list ap) {
! 4542: int size = 0;
! 4543: int chars;
! 4544: char *larger;
! 4545: char *str = NULL;
! 4546: va_list aq;
! 4547:
! 4548: while (1) {
! 4549: VA_COPY(aq, ap);
! 4550: chars = vsnprintf(str, size, msg, aq);
! 4551: va_end(aq);
! 4552: if (chars < 0) {
! 4553: xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
! 4554: if (str)
! 4555: xmlFree(str);
! 4556: return NULL;
! 4557: }
! 4558: if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
! 4559: break;
! 4560: if (chars < MAX_ERR_MSG_SIZE)
! 4561: size = chars + 1;
! 4562: else
! 4563: size = MAX_ERR_MSG_SIZE;
! 4564: if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
! 4565: xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
! 4566: if (str)
! 4567: xmlFree(str);
! 4568: return NULL;
! 4569: }
! 4570: str = larger;
! 4571: }
! 4572:
! 4573: return str;
! 4574: }
! 4575:
! 4576: /**
! 4577: * xmlTextReaderLocatorLineNumber:
! 4578: * @locator: the xmlTextReaderLocatorPtr used
! 4579: *
! 4580: * Obtain the line number for the given locator.
! 4581: *
! 4582: * Returns the line number or -1 in case of error.
! 4583: */
! 4584: int
! 4585: xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
! 4586: /* we know that locator is a xmlParserCtxtPtr */
! 4587: xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
! 4588: int ret = -1;
! 4589:
! 4590: if (locator == NULL)
! 4591: return(-1);
! 4592: if (ctx->node != NULL) {
! 4593: ret = xmlGetLineNo(ctx->node);
! 4594: }
! 4595: else {
! 4596: /* inspired from error.c */
! 4597: xmlParserInputPtr input;
! 4598: input = ctx->input;
! 4599: if ((input->filename == NULL) && (ctx->inputNr > 1))
! 4600: input = ctx->inputTab[ctx->inputNr - 2];
! 4601: if (input != NULL) {
! 4602: ret = input->line;
! 4603: }
! 4604: else {
! 4605: ret = -1;
! 4606: }
! 4607: }
! 4608:
! 4609: return ret;
! 4610: }
! 4611:
! 4612: /**
! 4613: * xmlTextReaderLocatorBaseURI:
! 4614: * @locator: the xmlTextReaderLocatorPtr used
! 4615: *
! 4616: * Obtain the base URI for the given locator.
! 4617: *
! 4618: * Returns the base URI or NULL in case of error,
! 4619: * if non NULL it need to be freed by the caller.
! 4620: */
! 4621: xmlChar *
! 4622: xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
! 4623: /* we know that locator is a xmlParserCtxtPtr */
! 4624: xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
! 4625: xmlChar *ret = NULL;
! 4626:
! 4627: if (locator == NULL)
! 4628: return(NULL);
! 4629: if (ctx->node != NULL) {
! 4630: ret = xmlNodeGetBase(NULL,ctx->node);
! 4631: }
! 4632: else {
! 4633: /* inspired from error.c */
! 4634: xmlParserInputPtr input;
! 4635: input = ctx->input;
! 4636: if ((input->filename == NULL) && (ctx->inputNr > 1))
! 4637: input = ctx->inputTab[ctx->inputNr - 2];
! 4638: if (input != NULL) {
! 4639: ret = xmlStrdup(BAD_CAST input->filename);
! 4640: }
! 4641: else {
! 4642: ret = NULL;
! 4643: }
! 4644: }
! 4645:
! 4646: return ret;
! 4647: }
! 4648:
! 4649: static void
! 4650: xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
! 4651: char *str)
! 4652: {
! 4653: xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
! 4654:
! 4655: xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
! 4656:
! 4657: if (str != NULL) {
! 4658: if (reader->errorFunc)
! 4659: reader->errorFunc(reader->errorFuncArg, str, severity,
! 4660: (xmlTextReaderLocatorPtr) ctx);
! 4661: xmlFree(str);
! 4662: }
! 4663: }
! 4664:
! 4665: static void
! 4666: xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
! 4667: {
! 4668: xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
! 4669:
! 4670: xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
! 4671:
! 4672: if (error && reader->sErrorFunc) {
! 4673: reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
! 4674: }
! 4675: }
! 4676:
! 4677: static void XMLCDECL
! 4678: xmlTextReaderError(void *ctxt, const char *msg, ...)
! 4679: {
! 4680: va_list ap;
! 4681:
! 4682: va_start(ap, msg);
! 4683: xmlTextReaderGenericError(ctxt,
! 4684: XML_PARSER_SEVERITY_ERROR,
! 4685: xmlTextReaderBuildMessage(msg, ap));
! 4686: va_end(ap);
! 4687:
! 4688: }
! 4689:
! 4690: static void XMLCDECL
! 4691: xmlTextReaderWarning(void *ctxt, const char *msg, ...)
! 4692: {
! 4693: va_list ap;
! 4694:
! 4695: va_start(ap, msg);
! 4696: xmlTextReaderGenericError(ctxt,
! 4697: XML_PARSER_SEVERITY_WARNING,
! 4698: xmlTextReaderBuildMessage(msg, ap));
! 4699: va_end(ap);
! 4700: }
! 4701:
! 4702: static void XMLCDECL
! 4703: xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
! 4704: {
! 4705: va_list ap;
! 4706:
! 4707: int len = xmlStrlen((const xmlChar *) msg);
! 4708:
! 4709: if ((len > 1) && (msg[len - 2] != ':')) {
! 4710: /*
! 4711: * some callbacks only report locator information:
! 4712: * skip them (mimicking behaviour in error.c)
! 4713: */
! 4714: va_start(ap, msg);
! 4715: xmlTextReaderGenericError(ctxt,
! 4716: XML_PARSER_SEVERITY_VALIDITY_ERROR,
! 4717: xmlTextReaderBuildMessage(msg, ap));
! 4718: va_end(ap);
! 4719: }
! 4720: }
! 4721:
! 4722: static void XMLCDECL
! 4723: xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
! 4724: {
! 4725: va_list ap;
! 4726:
! 4727: int len = xmlStrlen((const xmlChar *) msg);
! 4728:
! 4729: if ((len != 0) && (msg[len - 1] != ':')) {
! 4730: /*
! 4731: * some callbacks only report locator information:
! 4732: * skip them (mimicking behaviour in error.c)
! 4733: */
! 4734: va_start(ap, msg);
! 4735: xmlTextReaderGenericError(ctxt,
! 4736: XML_PARSER_SEVERITY_VALIDITY_WARNING,
! 4737: xmlTextReaderBuildMessage(msg, ap));
! 4738: va_end(ap);
! 4739: }
! 4740: }
! 4741:
! 4742: /**
! 4743: * xmlTextReaderSetErrorHandler:
! 4744: * @reader: the xmlTextReaderPtr used
! 4745: * @f: the callback function to call on error and warnings
! 4746: * @arg: a user argument to pass to the callback function
! 4747: *
! 4748: * Register a callback function that will be called on error and warnings.
! 4749: *
! 4750: * If @f is NULL, the default error and warning handlers are restored.
! 4751: */
! 4752: void
! 4753: xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
! 4754: xmlTextReaderErrorFunc f, void *arg)
! 4755: {
! 4756: if (f != NULL) {
! 4757: reader->ctxt->sax->error = xmlTextReaderError;
! 4758: reader->ctxt->sax->serror = NULL;
! 4759: reader->ctxt->vctxt.error = xmlTextReaderValidityError;
! 4760: reader->ctxt->sax->warning = xmlTextReaderWarning;
! 4761: reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
! 4762: reader->errorFunc = f;
! 4763: reader->sErrorFunc = NULL;
! 4764: reader->errorFuncArg = arg;
! 4765: #ifdef LIBXML_SCHEMAS_ENABLED
! 4766: if (reader->rngValidCtxt) {
! 4767: xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
! 4768: xmlTextReaderValidityErrorRelay,
! 4769: xmlTextReaderValidityWarningRelay,
! 4770: reader);
! 4771: xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
! 4772: reader);
! 4773: }
! 4774: if (reader->xsdValidCtxt) {
! 4775: xmlSchemaSetValidErrors(reader->xsdValidCtxt,
! 4776: xmlTextReaderValidityErrorRelay,
! 4777: xmlTextReaderValidityWarningRelay,
! 4778: reader);
! 4779: xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
! 4780: reader);
! 4781: }
! 4782: #endif
! 4783: } else {
! 4784: /* restore defaults */
! 4785: reader->ctxt->sax->error = xmlParserError;
! 4786: reader->ctxt->vctxt.error = xmlParserValidityError;
! 4787: reader->ctxt->sax->warning = xmlParserWarning;
! 4788: reader->ctxt->vctxt.warning = xmlParserValidityWarning;
! 4789: reader->errorFunc = NULL;
! 4790: reader->sErrorFunc = NULL;
! 4791: reader->errorFuncArg = NULL;
! 4792: #ifdef LIBXML_SCHEMAS_ENABLED
! 4793: if (reader->rngValidCtxt) {
! 4794: xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
! 4795: reader);
! 4796: xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
! 4797: reader);
! 4798: }
! 4799: if (reader->xsdValidCtxt) {
! 4800: xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
! 4801: reader);
! 4802: xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
! 4803: reader);
! 4804: }
! 4805: #endif
! 4806: }
! 4807: }
! 4808:
! 4809: /**
! 4810: * xmlTextReaderSetStructuredErrorHandler:
! 4811: * @reader: the xmlTextReaderPtr used
! 4812: * @f: the callback function to call on error and warnings
! 4813: * @arg: a user argument to pass to the callback function
! 4814: *
! 4815: * Register a callback function that will be called on error and warnings.
! 4816: *
! 4817: * If @f is NULL, the default error and warning handlers are restored.
! 4818: */
! 4819: void
! 4820: xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
! 4821: xmlStructuredErrorFunc f, void *arg)
! 4822: {
! 4823: if (f != NULL) {
! 4824: reader->ctxt->sax->error = NULL;
! 4825: reader->ctxt->sax->serror = xmlTextReaderStructuredError;
! 4826: reader->ctxt->vctxt.error = xmlTextReaderValidityError;
! 4827: reader->ctxt->sax->warning = xmlTextReaderWarning;
! 4828: reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
! 4829: reader->sErrorFunc = f;
! 4830: reader->errorFunc = NULL;
! 4831: reader->errorFuncArg = arg;
! 4832: #ifdef LIBXML_SCHEMAS_ENABLED
! 4833: if (reader->rngValidCtxt) {
! 4834: xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
! 4835: reader);
! 4836: xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
! 4837: xmlTextReaderValidityStructuredRelay,
! 4838: reader);
! 4839: }
! 4840: if (reader->xsdValidCtxt) {
! 4841: xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
! 4842: reader);
! 4843: xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
! 4844: xmlTextReaderValidityStructuredRelay,
! 4845: reader);
! 4846: }
! 4847: #endif
! 4848: } else {
! 4849: /* restore defaults */
! 4850: reader->ctxt->sax->error = xmlParserError;
! 4851: reader->ctxt->sax->serror = NULL;
! 4852: reader->ctxt->vctxt.error = xmlParserValidityError;
! 4853: reader->ctxt->sax->warning = xmlParserWarning;
! 4854: reader->ctxt->vctxt.warning = xmlParserValidityWarning;
! 4855: reader->errorFunc = NULL;
! 4856: reader->sErrorFunc = NULL;
! 4857: reader->errorFuncArg = NULL;
! 4858: #ifdef LIBXML_SCHEMAS_ENABLED
! 4859: if (reader->rngValidCtxt) {
! 4860: xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
! 4861: reader);
! 4862: xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
! 4863: reader);
! 4864: }
! 4865: if (reader->xsdValidCtxt) {
! 4866: xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
! 4867: reader);
! 4868: xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
! 4869: reader);
! 4870: }
! 4871: #endif
! 4872: }
! 4873: }
! 4874:
! 4875: /**
! 4876: * xmlTextReaderIsValid:
! 4877: * @reader: the xmlTextReaderPtr used
! 4878: *
! 4879: * Retrieve the validity status from the parser context
! 4880: *
! 4881: * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
! 4882: */
! 4883: int
! 4884: xmlTextReaderIsValid(xmlTextReaderPtr reader)
! 4885: {
! 4886: if (reader == NULL)
! 4887: return (-1);
! 4888: #ifdef LIBXML_SCHEMAS_ENABLED
! 4889: if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
! 4890: return (reader->rngValidErrors == 0);
! 4891: if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
! 4892: return (reader->xsdValidErrors == 0);
! 4893: #endif
! 4894: if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
! 4895: return (reader->ctxt->valid);
! 4896: return (0);
! 4897: }
! 4898:
! 4899: /**
! 4900: * xmlTextReaderGetErrorHandler:
! 4901: * @reader: the xmlTextReaderPtr used
! 4902: * @f: the callback function or NULL is no callback has been registered
! 4903: * @arg: a user argument
! 4904: *
! 4905: * Retrieve the error callback function and user argument.
! 4906: */
! 4907: void
! 4908: xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
! 4909: xmlTextReaderErrorFunc * f, void **arg)
! 4910: {
! 4911: if (f != NULL)
! 4912: *f = reader->errorFunc;
! 4913: if (arg != NULL)
! 4914: *arg = reader->errorFuncArg;
! 4915: }
! 4916: /************************************************************************
! 4917: * *
! 4918: * New set (2.6.0) of simpler and more flexible APIs *
! 4919: * *
! 4920: ************************************************************************/
! 4921:
! 4922: /**
! 4923: * xmlTextReaderSetup:
! 4924: * @reader: an XML reader
! 4925: * @input: xmlParserInputBufferPtr used to feed the reader, will
! 4926: * be destroyed with it.
! 4927: * @URL: the base URL to use for the document
! 4928: * @encoding: the document encoding, or NULL
! 4929: * @options: a combination of xmlParserOption
! 4930: *
! 4931: * Setup an XML reader with new options
! 4932: *
! 4933: * Returns 0 in case of success and -1 in case of error.
! 4934: */
! 4935: int
! 4936: xmlTextReaderSetup(xmlTextReaderPtr reader,
! 4937: xmlParserInputBufferPtr input, const char *URL,
! 4938: const char *encoding, int options)
! 4939: {
! 4940: if (reader == NULL) {
! 4941: if (input != NULL)
! 4942: xmlFreeParserInputBuffer(input);
! 4943: return (-1);
! 4944: }
! 4945:
! 4946: /*
! 4947: * we force the generation of compact text nodes on the reader
! 4948: * since usr applications should never modify the tree
! 4949: */
! 4950: options |= XML_PARSE_COMPACT;
! 4951:
! 4952: reader->doc = NULL;
! 4953: reader->entNr = 0;
! 4954: reader->parserFlags = options;
! 4955: reader->validate = XML_TEXTREADER_NOT_VALIDATE;
! 4956: if ((input != NULL) && (reader->input != NULL) &&
! 4957: (reader->allocs & XML_TEXTREADER_INPUT)) {
! 4958: xmlFreeParserInputBuffer(reader->input);
! 4959: reader->input = NULL;
! 4960: reader->allocs -= XML_TEXTREADER_INPUT;
! 4961: }
! 4962: if (input != NULL) {
! 4963: reader->input = input;
! 4964: reader->allocs |= XML_TEXTREADER_INPUT;
! 4965: }
! 4966: if (reader->buffer == NULL)
! 4967: reader->buffer = xmlBufferCreateSize(100);
! 4968: if (reader->buffer == NULL) {
! 4969: xmlGenericError(xmlGenericErrorContext,
! 4970: "xmlTextReaderSetup : malloc failed\n");
! 4971: return (-1);
! 4972: }
! 4973: if (reader->sax == NULL)
! 4974: reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
! 4975: if (reader->sax == NULL) {
! 4976: xmlGenericError(xmlGenericErrorContext,
! 4977: "xmlTextReaderSetup : malloc failed\n");
! 4978: return (-1);
! 4979: }
! 4980: xmlSAXVersion(reader->sax, 2);
! 4981: reader->startElement = reader->sax->startElement;
! 4982: reader->sax->startElement = xmlTextReaderStartElement;
! 4983: reader->endElement = reader->sax->endElement;
! 4984: reader->sax->endElement = xmlTextReaderEndElement;
! 4985: #ifdef LIBXML_SAX1_ENABLED
! 4986: if (reader->sax->initialized == XML_SAX2_MAGIC) {
! 4987: #endif /* LIBXML_SAX1_ENABLED */
! 4988: reader->startElementNs = reader->sax->startElementNs;
! 4989: reader->sax->startElementNs = xmlTextReaderStartElementNs;
! 4990: reader->endElementNs = reader->sax->endElementNs;
! 4991: reader->sax->endElementNs = xmlTextReaderEndElementNs;
! 4992: #ifdef LIBXML_SAX1_ENABLED
! 4993: } else {
! 4994: reader->startElementNs = NULL;
! 4995: reader->endElementNs = NULL;
! 4996: }
! 4997: #endif /* LIBXML_SAX1_ENABLED */
! 4998: reader->characters = reader->sax->characters;
! 4999: reader->sax->characters = xmlTextReaderCharacters;
! 5000: reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
! 5001: reader->cdataBlock = reader->sax->cdataBlock;
! 5002: reader->sax->cdataBlock = xmlTextReaderCDataBlock;
! 5003:
! 5004: reader->mode = XML_TEXTREADER_MODE_INITIAL;
! 5005: reader->node = NULL;
! 5006: reader->curnode = NULL;
! 5007: if (input != NULL) {
! 5008: if (reader->input->buffer->use < 4) {
! 5009: xmlParserInputBufferRead(input, 4);
! 5010: }
! 5011: if (reader->ctxt == NULL) {
! 5012: if (reader->input->buffer->use >= 4) {
! 5013: reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
! 5014: (const char *) reader->input->buffer->content, 4, URL);
! 5015: reader->base = 0;
! 5016: reader->cur = 4;
! 5017: } else {
! 5018: reader->ctxt =
! 5019: xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
! 5020: reader->base = 0;
! 5021: reader->cur = 0;
! 5022: }
! 5023: } else {
! 5024: xmlParserInputPtr inputStream;
! 5025: xmlParserInputBufferPtr buf;
! 5026: xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
! 5027:
! 5028: xmlCtxtReset(reader->ctxt);
! 5029: buf = xmlAllocParserInputBuffer(enc);
! 5030: if (buf == NULL) return(-1);
! 5031: inputStream = xmlNewInputStream(reader->ctxt);
! 5032: if (inputStream == NULL) {
! 5033: xmlFreeParserInputBuffer(buf);
! 5034: return(-1);
! 5035: }
! 5036:
! 5037: if (URL == NULL)
! 5038: inputStream->filename = NULL;
! 5039: else
! 5040: inputStream->filename = (char *)
! 5041: xmlCanonicPath((const xmlChar *) URL);
! 5042: inputStream->buf = buf;
! 5043: inputStream->base = inputStream->buf->buffer->content;
! 5044: inputStream->cur = inputStream->buf->buffer->content;
! 5045: inputStream->end =
! 5046: &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
! 5047:
! 5048: inputPush(reader->ctxt, inputStream);
! 5049: reader->cur = 0;
! 5050: }
! 5051: if (reader->ctxt == NULL) {
! 5052: xmlGenericError(xmlGenericErrorContext,
! 5053: "xmlTextReaderSetup : malloc failed\n");
! 5054: return (-1);
! 5055: }
! 5056: }
! 5057: if (reader->dict != NULL) {
! 5058: if (reader->ctxt->dict != NULL) {
! 5059: if (reader->dict != reader->ctxt->dict) {
! 5060: xmlDictFree(reader->dict);
! 5061: reader->dict = reader->ctxt->dict;
! 5062: }
! 5063: } else {
! 5064: reader->ctxt->dict = reader->dict;
! 5065: }
! 5066: } else {
! 5067: if (reader->ctxt->dict == NULL)
! 5068: reader->ctxt->dict = xmlDictCreate();
! 5069: reader->dict = reader->ctxt->dict;
! 5070: }
! 5071: reader->ctxt->_private = reader;
! 5072: reader->ctxt->linenumbers = 1;
! 5073: reader->ctxt->dictNames = 1;
! 5074: /*
! 5075: * use the parser dictionnary to allocate all elements and attributes names
! 5076: */
! 5077: reader->ctxt->docdict = 1;
! 5078: reader->ctxt->parseMode = XML_PARSE_READER;
! 5079:
! 5080: #ifdef LIBXML_XINCLUDE_ENABLED
! 5081: if (reader->xincctxt != NULL) {
! 5082: xmlXIncludeFreeContext(reader->xincctxt);
! 5083: reader->xincctxt = NULL;
! 5084: }
! 5085: if (options & XML_PARSE_XINCLUDE) {
! 5086: reader->xinclude = 1;
! 5087: reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
! 5088: options -= XML_PARSE_XINCLUDE;
! 5089: } else
! 5090: reader->xinclude = 0;
! 5091: reader->in_xinclude = 0;
! 5092: #endif
! 5093: #ifdef LIBXML_PATTERN_ENABLED
! 5094: if (reader->patternTab == NULL) {
! 5095: reader->patternNr = 0;
! 5096: reader->patternMax = 0;
! 5097: }
! 5098: while (reader->patternNr > 0) {
! 5099: reader->patternNr--;
! 5100: if (reader->patternTab[reader->patternNr] != NULL) {
! 5101: xmlFreePattern(reader->patternTab[reader->patternNr]);
! 5102: reader->patternTab[reader->patternNr] = NULL;
! 5103: }
! 5104: }
! 5105: #endif
! 5106:
! 5107: if (options & XML_PARSE_DTDVALID)
! 5108: reader->validate = XML_TEXTREADER_VALIDATE_DTD;
! 5109:
! 5110: xmlCtxtUseOptions(reader->ctxt, options);
! 5111: if (encoding != NULL) {
! 5112: xmlCharEncodingHandlerPtr hdlr;
! 5113:
! 5114: hdlr = xmlFindCharEncodingHandler(encoding);
! 5115: if (hdlr != NULL)
! 5116: xmlSwitchToEncoding(reader->ctxt, hdlr);
! 5117: }
! 5118: if ((URL != NULL) && (reader->ctxt->input != NULL) &&
! 5119: (reader->ctxt->input->filename == NULL))
! 5120: reader->ctxt->input->filename = (char *)
! 5121: xmlStrdup((const xmlChar *) URL);
! 5122:
! 5123: reader->doc = NULL;
! 5124:
! 5125: return (0);
! 5126: }
! 5127:
! 5128: /**
! 5129: * xmlTextReaderByteConsumed:
! 5130: * @reader: an XML reader
! 5131: *
! 5132: * This function provides the current index of the parser used
! 5133: * by the reader, relative to the start of the current entity.
! 5134: * This function actually just wraps a call to xmlBytesConsumed()
! 5135: * for the parser context associated with the reader.
! 5136: * See xmlBytesConsumed() for more information.
! 5137: *
! 5138: * Returns the index in bytes from the beginning of the entity or -1
! 5139: * in case the index could not be computed.
! 5140: */
! 5141: long
! 5142: xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
! 5143: if ((reader == NULL) || (reader->ctxt == NULL))
! 5144: return(-1);
! 5145: return(xmlByteConsumed(reader->ctxt));
! 5146: }
! 5147:
! 5148:
! 5149: /**
! 5150: * xmlReaderWalker:
! 5151: * @doc: a preparsed document
! 5152: *
! 5153: * Create an xmltextReader for a preparsed document.
! 5154: *
! 5155: * Returns the new reader or NULL in case of error.
! 5156: */
! 5157: xmlTextReaderPtr
! 5158: xmlReaderWalker(xmlDocPtr doc)
! 5159: {
! 5160: xmlTextReaderPtr ret;
! 5161:
! 5162: if (doc == NULL)
! 5163: return(NULL);
! 5164:
! 5165: ret = xmlMalloc(sizeof(xmlTextReader));
! 5166: if (ret == NULL) {
! 5167: xmlGenericError(xmlGenericErrorContext,
! 5168: "xmlNewTextReader : malloc failed\n");
! 5169: return(NULL);
! 5170: }
! 5171: memset(ret, 0, sizeof(xmlTextReader));
! 5172: ret->entNr = 0;
! 5173: ret->input = NULL;
! 5174: ret->mode = XML_TEXTREADER_MODE_INITIAL;
! 5175: ret->node = NULL;
! 5176: ret->curnode = NULL;
! 5177: ret->base = 0;
! 5178: ret->cur = 0;
! 5179: ret->allocs = XML_TEXTREADER_CTXT;
! 5180: ret->doc = doc;
! 5181: ret->state = XML_TEXTREADER_START;
! 5182: ret->dict = xmlDictCreate();
! 5183: return(ret);
! 5184: }
! 5185:
! 5186: /**
! 5187: * xmlReaderForDoc:
! 5188: * @cur: a pointer to a zero terminated string
! 5189: * @URL: the base URL to use for the document
! 5190: * @encoding: the document encoding, or NULL
! 5191: * @options: a combination of xmlParserOption
! 5192: *
! 5193: * Create an xmltextReader for an XML in-memory document.
! 5194: * The parsing flags @options are a combination of xmlParserOption.
! 5195: *
! 5196: * Returns the new reader or NULL in case of error.
! 5197: */
! 5198: xmlTextReaderPtr
! 5199: xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
! 5200: int options)
! 5201: {
! 5202: int len;
! 5203:
! 5204: if (cur == NULL)
! 5205: return (NULL);
! 5206: len = xmlStrlen(cur);
! 5207:
! 5208: return (xmlReaderForMemory
! 5209: ((const char *) cur, len, URL, encoding, options));
! 5210: }
! 5211:
! 5212: /**
! 5213: * xmlReaderForFile:
! 5214: * @filename: a file or URL
! 5215: * @encoding: the document encoding, or NULL
! 5216: * @options: a combination of xmlParserOption
! 5217: *
! 5218: * parse an XML file from the filesystem or the network.
! 5219: * The parsing flags @options are a combination of xmlParserOption.
! 5220: *
! 5221: * Returns the new reader or NULL in case of error.
! 5222: */
! 5223: xmlTextReaderPtr
! 5224: xmlReaderForFile(const char *filename, const char *encoding, int options)
! 5225: {
! 5226: xmlTextReaderPtr reader;
! 5227:
! 5228: reader = xmlNewTextReaderFilename(filename);
! 5229: if (reader == NULL)
! 5230: return (NULL);
! 5231: xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
! 5232: return (reader);
! 5233: }
! 5234:
! 5235: /**
! 5236: * xmlReaderForMemory:
! 5237: * @buffer: a pointer to a char array
! 5238: * @size: the size of the array
! 5239: * @URL: the base URL to use for the document
! 5240: * @encoding: the document encoding, or NULL
! 5241: * @options: a combination of xmlParserOption
! 5242: *
! 5243: * Create an xmltextReader for an XML in-memory document.
! 5244: * The parsing flags @options are a combination of xmlParserOption.
! 5245: *
! 5246: * Returns the new reader or NULL in case of error.
! 5247: */
! 5248: xmlTextReaderPtr
! 5249: xmlReaderForMemory(const char *buffer, int size, const char *URL,
! 5250: const char *encoding, int options)
! 5251: {
! 5252: xmlTextReaderPtr reader;
! 5253: xmlParserInputBufferPtr buf;
! 5254:
! 5255: buf = xmlParserInputBufferCreateStatic(buffer, size,
! 5256: XML_CHAR_ENCODING_NONE);
! 5257: if (buf == NULL) {
! 5258: return (NULL);
! 5259: }
! 5260: reader = xmlNewTextReader(buf, URL);
! 5261: if (reader == NULL) {
! 5262: xmlFreeParserInputBuffer(buf);
! 5263: return (NULL);
! 5264: }
! 5265: reader->allocs |= XML_TEXTREADER_INPUT;
! 5266: xmlTextReaderSetup(reader, NULL, URL, encoding, options);
! 5267: return (reader);
! 5268: }
! 5269:
! 5270: /**
! 5271: * xmlReaderForFd:
! 5272: * @fd: an open file descriptor
! 5273: * @URL: the base URL to use for the document
! 5274: * @encoding: the document encoding, or NULL
! 5275: * @options: a combination of xmlParserOption
! 5276: *
! 5277: * Create an xmltextReader for an XML from a file descriptor.
! 5278: * The parsing flags @options are a combination of xmlParserOption.
! 5279: * NOTE that the file descriptor will not be closed when the
! 5280: * reader is closed or reset.
! 5281: *
! 5282: * Returns the new reader or NULL in case of error.
! 5283: */
! 5284: xmlTextReaderPtr
! 5285: xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
! 5286: {
! 5287: xmlTextReaderPtr reader;
! 5288: xmlParserInputBufferPtr input;
! 5289:
! 5290: if (fd < 0)
! 5291: return (NULL);
! 5292:
! 5293: input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
! 5294: if (input == NULL)
! 5295: return (NULL);
! 5296: input->closecallback = NULL;
! 5297: reader = xmlNewTextReader(input, URL);
! 5298: if (reader == NULL) {
! 5299: xmlFreeParserInputBuffer(input);
! 5300: return (NULL);
! 5301: }
! 5302: reader->allocs |= XML_TEXTREADER_INPUT;
! 5303: xmlTextReaderSetup(reader, NULL, URL, encoding, options);
! 5304: return (reader);
! 5305: }
! 5306:
! 5307: /**
! 5308: * xmlReaderForIO:
! 5309: * @ioread: an I/O read function
! 5310: * @ioclose: an I/O close function
! 5311: * @ioctx: an I/O handler
! 5312: * @URL: the base URL to use for the document
! 5313: * @encoding: the document encoding, or NULL
! 5314: * @options: a combination of xmlParserOption
! 5315: *
! 5316: * Create an xmltextReader for an XML document from I/O functions and source.
! 5317: * The parsing flags @options are a combination of xmlParserOption.
! 5318: *
! 5319: * Returns the new reader or NULL in case of error.
! 5320: */
! 5321: xmlTextReaderPtr
! 5322: xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
! 5323: void *ioctx, const char *URL, const char *encoding,
! 5324: int options)
! 5325: {
! 5326: xmlTextReaderPtr reader;
! 5327: xmlParserInputBufferPtr input;
! 5328:
! 5329: if (ioread == NULL)
! 5330: return (NULL);
! 5331:
! 5332: input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
! 5333: XML_CHAR_ENCODING_NONE);
! 5334: if (input == NULL)
! 5335: return (NULL);
! 5336: reader = xmlNewTextReader(input, URL);
! 5337: if (reader == NULL) {
! 5338: xmlFreeParserInputBuffer(input);
! 5339: return (NULL);
! 5340: }
! 5341: reader->allocs |= XML_TEXTREADER_INPUT;
! 5342: xmlTextReaderSetup(reader, NULL, URL, encoding, options);
! 5343: return (reader);
! 5344: }
! 5345:
! 5346: /**
! 5347: * xmlReaderNewWalker:
! 5348: * @reader: an XML reader
! 5349: * @doc: a preparsed document
! 5350: *
! 5351: * Setup an xmltextReader to parse a preparsed XML document.
! 5352: * This reuses the existing @reader xmlTextReader.
! 5353: *
! 5354: * Returns 0 in case of success and -1 in case of error
! 5355: */
! 5356: int
! 5357: xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
! 5358: {
! 5359: if (doc == NULL)
! 5360: return (-1);
! 5361: if (reader == NULL)
! 5362: return (-1);
! 5363:
! 5364: if (reader->input != NULL) {
! 5365: xmlFreeParserInputBuffer(reader->input);
! 5366: }
! 5367: if (reader->ctxt != NULL) {
! 5368: xmlCtxtReset(reader->ctxt);
! 5369: }
! 5370:
! 5371: reader->entNr = 0;
! 5372: reader->input = NULL;
! 5373: reader->mode = XML_TEXTREADER_MODE_INITIAL;
! 5374: reader->node = NULL;
! 5375: reader->curnode = NULL;
! 5376: reader->base = 0;
! 5377: reader->cur = 0;
! 5378: reader->allocs = XML_TEXTREADER_CTXT;
! 5379: reader->doc = doc;
! 5380: reader->state = XML_TEXTREADER_START;
! 5381: if (reader->dict == NULL) {
! 5382: if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
! 5383: reader->dict = reader->ctxt->dict;
! 5384: else
! 5385: reader->dict = xmlDictCreate();
! 5386: }
! 5387: return(0);
! 5388: }
! 5389:
! 5390: /**
! 5391: * xmlReaderNewDoc:
! 5392: * @reader: an XML reader
! 5393: * @cur: a pointer to a zero terminated string
! 5394: * @URL: the base URL to use for the document
! 5395: * @encoding: the document encoding, or NULL
! 5396: * @options: a combination of xmlParserOption
! 5397: *
! 5398: * Setup an xmltextReader to parse an XML in-memory document.
! 5399: * The parsing flags @options are a combination of xmlParserOption.
! 5400: * This reuses the existing @reader xmlTextReader.
! 5401: *
! 5402: * Returns 0 in case of success and -1 in case of error
! 5403: */
! 5404: int
! 5405: xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
! 5406: const char *URL, const char *encoding, int options)
! 5407: {
! 5408:
! 5409: int len;
! 5410:
! 5411: if (cur == NULL)
! 5412: return (-1);
! 5413: if (reader == NULL)
! 5414: return (-1);
! 5415:
! 5416: len = xmlStrlen(cur);
! 5417: return (xmlReaderNewMemory(reader, (const char *)cur, len,
! 5418: URL, encoding, options));
! 5419: }
! 5420:
! 5421: /**
! 5422: * xmlReaderNewFile:
! 5423: * @reader: an XML reader
! 5424: * @filename: a file or URL
! 5425: * @encoding: the document encoding, or NULL
! 5426: * @options: a combination of xmlParserOption
! 5427: *
! 5428: * parse an XML file from the filesystem or the network.
! 5429: * The parsing flags @options are a combination of xmlParserOption.
! 5430: * This reuses the existing @reader xmlTextReader.
! 5431: *
! 5432: * Returns 0 in case of success and -1 in case of error
! 5433: */
! 5434: int
! 5435: xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
! 5436: const char *encoding, int options)
! 5437: {
! 5438: xmlParserInputBufferPtr input;
! 5439:
! 5440: if (filename == NULL)
! 5441: return (-1);
! 5442: if (reader == NULL)
! 5443: return (-1);
! 5444:
! 5445: input =
! 5446: xmlParserInputBufferCreateFilename(filename,
! 5447: XML_CHAR_ENCODING_NONE);
! 5448: if (input == NULL)
! 5449: return (-1);
! 5450: return (xmlTextReaderSetup(reader, input, filename, encoding, options));
! 5451: }
! 5452:
! 5453: /**
! 5454: * xmlReaderNewMemory:
! 5455: * @reader: an XML reader
! 5456: * @buffer: a pointer to a char array
! 5457: * @size: the size of the array
! 5458: * @URL: the base URL to use for the document
! 5459: * @encoding: the document encoding, or NULL
! 5460: * @options: a combination of xmlParserOption
! 5461: *
! 5462: * Setup an xmltextReader to parse an XML in-memory document.
! 5463: * The parsing flags @options are a combination of xmlParserOption.
! 5464: * This reuses the existing @reader xmlTextReader.
! 5465: *
! 5466: * Returns 0 in case of success and -1 in case of error
! 5467: */
! 5468: int
! 5469: xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
! 5470: const char *URL, const char *encoding, int options)
! 5471: {
! 5472: xmlParserInputBufferPtr input;
! 5473:
! 5474: if (reader == NULL)
! 5475: return (-1);
! 5476: if (buffer == NULL)
! 5477: return (-1);
! 5478:
! 5479: input = xmlParserInputBufferCreateStatic(buffer, size,
! 5480: XML_CHAR_ENCODING_NONE);
! 5481: if (input == NULL) {
! 5482: return (-1);
! 5483: }
! 5484: return (xmlTextReaderSetup(reader, input, URL, encoding, options));
! 5485: }
! 5486:
! 5487: /**
! 5488: * xmlReaderNewFd:
! 5489: * @reader: an XML reader
! 5490: * @fd: an open file descriptor
! 5491: * @URL: the base URL to use for the document
! 5492: * @encoding: the document encoding, or NULL
! 5493: * @options: a combination of xmlParserOption
! 5494: *
! 5495: * Setup an xmltextReader to parse an XML from a file descriptor.
! 5496: * NOTE that the file descriptor will not be closed when the
! 5497: * reader is closed or reset.
! 5498: * The parsing flags @options are a combination of xmlParserOption.
! 5499: * This reuses the existing @reader xmlTextReader.
! 5500: *
! 5501: * Returns 0 in case of success and -1 in case of error
! 5502: */
! 5503: int
! 5504: xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
! 5505: const char *URL, const char *encoding, int options)
! 5506: {
! 5507: xmlParserInputBufferPtr input;
! 5508:
! 5509: if (fd < 0)
! 5510: return (-1);
! 5511: if (reader == NULL)
! 5512: return (-1);
! 5513:
! 5514: input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
! 5515: if (input == NULL)
! 5516: return (-1);
! 5517: input->closecallback = NULL;
! 5518: return (xmlTextReaderSetup(reader, input, URL, encoding, options));
! 5519: }
! 5520:
! 5521: /**
! 5522: * xmlReaderNewIO:
! 5523: * @reader: an XML reader
! 5524: * @ioread: an I/O read function
! 5525: * @ioclose: an I/O close function
! 5526: * @ioctx: an I/O handler
! 5527: * @URL: the base URL to use for the document
! 5528: * @encoding: the document encoding, or NULL
! 5529: * @options: a combination of xmlParserOption
! 5530: *
! 5531: * Setup an xmltextReader to parse an XML document from I/O functions
! 5532: * and source.
! 5533: * The parsing flags @options are a combination of xmlParserOption.
! 5534: * This reuses the existing @reader xmlTextReader.
! 5535: *
! 5536: * Returns 0 in case of success and -1 in case of error
! 5537: */
! 5538: int
! 5539: xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
! 5540: xmlInputCloseCallback ioclose, void *ioctx,
! 5541: const char *URL, const char *encoding, int options)
! 5542: {
! 5543: xmlParserInputBufferPtr input;
! 5544:
! 5545: if (ioread == NULL)
! 5546: return (-1);
! 5547: if (reader == NULL)
! 5548: return (-1);
! 5549:
! 5550: input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
! 5551: XML_CHAR_ENCODING_NONE);
! 5552: if (input == NULL)
! 5553: return (-1);
! 5554: return (xmlTextReaderSetup(reader, input, URL, encoding, options));
! 5555: }
! 5556: /************************************************************************
! 5557: * *
! 5558: * Utilities *
! 5559: * *
! 5560: ************************************************************************/
! 5561: #ifdef NOT_USED_YET
! 5562:
! 5563: /**
! 5564: * xmlBase64Decode:
! 5565: * @in: the input buffer
! 5566: * @inlen: the size of the input (in), the size read from it (out)
! 5567: * @to: the output buffer
! 5568: * @tolen: the size of the output (in), the size written to (out)
! 5569: *
! 5570: * Base64 decoder, reads from @in and save in @to
! 5571: * TODO: tell jody when this is actually exported
! 5572: *
! 5573: * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
! 5574: * 2 if there wasn't enough space on the output or -1 in case of error.
! 5575: */
! 5576: static int
! 5577: xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
! 5578: unsigned char *to, unsigned long *tolen)
! 5579: {
! 5580: unsigned long incur; /* current index in in[] */
! 5581:
! 5582: unsigned long inblk; /* last block index in in[] */
! 5583:
! 5584: unsigned long outcur; /* current index in out[] */
! 5585:
! 5586: unsigned long inmax; /* size of in[] */
! 5587:
! 5588: unsigned long outmax; /* size of out[] */
! 5589:
! 5590: unsigned char cur; /* the current value read from in[] */
! 5591:
! 5592: unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
! 5593:
! 5594: int nbintmp; /* number of byte in intmp[] */
! 5595:
! 5596: int is_ignore; /* cur should be ignored */
! 5597:
! 5598: int is_end = 0; /* the end of the base64 was found */
! 5599:
! 5600: int retval = 1;
! 5601:
! 5602: int i;
! 5603:
! 5604: if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
! 5605: return (-1);
! 5606:
! 5607: incur = 0;
! 5608: inblk = 0;
! 5609: outcur = 0;
! 5610: inmax = *inlen;
! 5611: outmax = *tolen;
! 5612: nbintmp = 0;
! 5613:
! 5614: while (1) {
! 5615: if (incur >= inmax)
! 5616: break;
! 5617: cur = in[incur++];
! 5618: is_ignore = 0;
! 5619: if ((cur >= 'A') && (cur <= 'Z'))
! 5620: cur = cur - 'A';
! 5621: else if ((cur >= 'a') && (cur <= 'z'))
! 5622: cur = cur - 'a' + 26;
! 5623: else if ((cur >= '0') && (cur <= '9'))
! 5624: cur = cur - '0' + 52;
! 5625: else if (cur == '+')
! 5626: cur = 62;
! 5627: else if (cur == '/')
! 5628: cur = 63;
! 5629: else if (cur == '.')
! 5630: cur = 0;
! 5631: else if (cur == '=') /*no op , end of the base64 stream */
! 5632: is_end = 1;
! 5633: else {
! 5634: is_ignore = 1;
! 5635: if (nbintmp == 0)
! 5636: inblk = incur;
! 5637: }
! 5638:
! 5639: if (!is_ignore) {
! 5640: int nbouttmp = 3;
! 5641:
! 5642: int is_break = 0;
! 5643:
! 5644: if (is_end) {
! 5645: if (nbintmp == 0)
! 5646: break;
! 5647: if ((nbintmp == 1) || (nbintmp == 2))
! 5648: nbouttmp = 1;
! 5649: else
! 5650: nbouttmp = 2;
! 5651: nbintmp = 3;
! 5652: is_break = 1;
! 5653: }
! 5654: intmp[nbintmp++] = cur;
! 5655: /*
! 5656: * if intmp is full, push the 4byte sequence as a 3 byte
! 5657: * sequence out
! 5658: */
! 5659: if (nbintmp == 4) {
! 5660: nbintmp = 0;
! 5661: outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
! 5662: outtmp[1] =
! 5663: ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
! 5664: outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
! 5665: if (outcur + 3 >= outmax) {
! 5666: retval = 2;
! 5667: break;
! 5668: }
! 5669:
! 5670: for (i = 0; i < nbouttmp; i++)
! 5671: to[outcur++] = outtmp[i];
! 5672: inblk = incur;
! 5673: }
! 5674:
! 5675: if (is_break) {
! 5676: retval = 0;
! 5677: break;
! 5678: }
! 5679: }
! 5680: }
! 5681:
! 5682: *tolen = outcur;
! 5683: *inlen = inblk;
! 5684: return (retval);
! 5685: }
! 5686:
! 5687: /*
! 5688: * Test routine for the xmlBase64Decode function
! 5689: */
! 5690: #if 0
! 5691: int
! 5692: main(int argc, char **argv)
! 5693: {
! 5694: char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
! 5695:
! 5696: char output[100];
! 5697:
! 5698: char output2[100];
! 5699:
! 5700: char output3[100];
! 5701:
! 5702: unsigned long inlen = strlen(input);
! 5703:
! 5704: unsigned long outlen = 100;
! 5705:
! 5706: int ret;
! 5707:
! 5708: unsigned long cons, tmp, tmp2, prod;
! 5709:
! 5710: /*
! 5711: * Direct
! 5712: */
! 5713: ret = xmlBase64Decode(input, &inlen, output, &outlen);
! 5714:
! 5715: output[outlen] = 0;
! 5716: printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
! 5717: outlen, output)indent: Standard input:179: Error:Unmatched #endif
! 5718: ;
! 5719:
! 5720: /*
! 5721: * output chunking
! 5722: */
! 5723: cons = 0;
! 5724: prod = 0;
! 5725: while (cons < inlen) {
! 5726: tmp = 5;
! 5727: tmp2 = inlen - cons;
! 5728:
! 5729: printf("%ld %ld\n", cons, prod);
! 5730: ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
! 5731: cons += tmp2;
! 5732: prod += tmp;
! 5733: printf("%ld %ld\n", cons, prod);
! 5734: }
! 5735: output2[outlen] = 0;
! 5736: printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
! 5737: prod, output2);
! 5738:
! 5739: /*
! 5740: * input chunking
! 5741: */
! 5742: cons = 0;
! 5743: prod = 0;
! 5744: while (cons < inlen) {
! 5745: tmp = 100 - prod;
! 5746: tmp2 = inlen - cons;
! 5747: if (tmp2 > 5)
! 5748: tmp2 = 5;
! 5749:
! 5750: printf("%ld %ld\n", cons, prod);
! 5751: ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
! 5752: cons += tmp2;
! 5753: prod += tmp;
! 5754: printf("%ld %ld\n", cons, prod);
! 5755: }
! 5756: output3[outlen] = 0;
! 5757: printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
! 5758: prod, output3);
! 5759: return (0);
! 5760:
! 5761: }
! 5762: #endif
! 5763: #endif /* NOT_USED_YET */
! 5764: #define bottom_xmlreader
! 5765: #include "elfgcchack.h"
! 5766: #endif /* LIBXML_READER_ENABLED */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>