1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-03-31 06:50:06 +03:00

- Lots of improvements, too long to list here

- Push mode for the XML parser (HTML to come)
- XML shell like interface for debug
- improvements on XPath and validation
Daniel
This commit is contained in:
Daniel Veillard 1999-12-28 16:35:14 +00:00
parent fef854d234
commit dbfd641b78
31 changed files with 2876 additions and 307 deletions

View File

@ -1,3 +1,20 @@
Tue Dec 28 18:44:22 CET 1999 Daniel Veillard <Daniel.Veillard@w3.org>
* parser.[ch] parserInternals.h: Push parser for XML,
seems to work fine now
* tester.c debugXML.[ch]: Added an XML shell debug facility and
--push for push testing
* xpath.[ch] : cleaned up for Shell usage, added missing APIs
* testSAX.c: added --push
* HTMLtree.[ch] tree.[ch]: new functions for dumping parts of the
subtree
* xmlIO.[ch] : enriched API + fixes for push mode
* entities.[ch]: added the entity content length to the struct.
* xmlmemory.[ch]: new API to show the last entries for the shell
* valid.c: added required attribute testing
* SAX.c: the cdata callback now merge contiguous fragments
* HTMLparser.c: cleanup of some macros
Wed Dec 22 12:20:53 CET 1999 Daniel Veillard <Daniel.Veillard@w3.org>
* parser.c: fix for PIs name starting with xml

View File

@ -57,8 +57,8 @@
* Generic function for accessing stacks in the Parser Context
*/
#define PUSH_AND_POP(type, name) \
int html##name##Push(htmlParserCtxtPtr ctxt, type value) { \
#define PUSH_AND_POP(scope, type, name) \
scope int html##name##Push(htmlParserCtxtPtr ctxt, type value) { \
if (ctxt->name##Nr >= ctxt->name##Max) { \
ctxt->name##Max *= 2; \
ctxt->name##Tab = (void *) xmlRealloc(ctxt->name##Tab, \
@ -72,7 +72,7 @@ int html##name##Push(htmlParserCtxtPtr ctxt, type value) { \
ctxt->name = value; \
return(ctxt->name##Nr++); \
} \
type html##name##Pop(htmlParserCtxtPtr ctxt) { \
scope type html##name##Pop(htmlParserCtxtPtr ctxt) { \
type ret; \
if (ctxt->name##Nr < 0) return(0); \
ctxt->name##Nr--; \
@ -86,8 +86,8 @@ type html##name##Pop(htmlParserCtxtPtr ctxt) { \
return(ret); \
} \
PUSH_AND_POP(xmlNodePtr, node)
PUSH_AND_POP(xmlChar*, name)
PUSH_AND_POP(extern, xmlNodePtr, node)
PUSH_AND_POP(extern, xmlChar*, name)
/*
* Macros for accessing the content. Those should be used only by the parser,
@ -2626,11 +2626,11 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) {
}
/********************************************************************************
* *
* Parser contexts handling *
* *
********************************************************************************/
/************************************************************************
* *
* Parser contexts handling *
* *
************************************************************************/
/**
* xmlInitParserCtxt:
@ -2665,6 +2665,7 @@ htmlInitParserCtxt(htmlParserCtxtPtr ctxt)
ctxt->version = NULL;
ctxt->encoding = NULL;
ctxt->standalone = -1;
ctxt->instate = XML_PARSER_START;
/* Allocate the Node stack */
ctxt->nodeTab = (htmlNodePtr *) xmlMalloc(10 * sizeof(htmlNodePtr));
@ -2691,6 +2692,7 @@ htmlInitParserCtxt(htmlParserCtxtPtr ctxt)
ctxt->record_info = 0;
ctxt->validate = 0;
ctxt->nbChars = 0;
ctxt->checkIndex = 0;
xmlInitNodeInfoSeq(&ctxt->node_seq);
}

View File

@ -28,6 +28,9 @@
#include "entities.h"
#include "valid.h"
static void
htmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur);
/**
* htmlDtdDump:
* @buf: the HTML buffer output
@ -108,7 +111,7 @@ htmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
}
static void
void
htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur);
/**
* htmlNodeListDump:
@ -138,7 +141,7 @@ htmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur) {
*
* Dump an HTML node, recursive behaviour,children are printed too.
*/
static void
void
htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur) {
htmlElemDescPtr info;
@ -149,6 +152,10 @@ htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur) {
/*
* Special cases.
*/
if (cur->type == XML_HTML_DOCUMENT_NODE) {
htmlDocContentDump(buf, (xmlDocPtr) cur);
return;
}
if (cur->type == HTML_TEXT_NODE) {
if (cur->content != NULL) {
xmlChar *buffer;

16
SAX.c
View File

@ -1101,14 +1101,22 @@ void
cdataBlock(void *ctx, const xmlChar *value, int len)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlNodePtr ret;
xmlNodePtr ret, lastChild;
#ifdef DEBUG_SAX
fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
#endif
ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
xmlAddChild(ctxt->node, ret);
/* !!!!! merges */
lastChild = xmlGetLastChild(ctxt->node);
#ifdef DEBUG_SAX_TREE
fprintf(stderr, "add chars to %s \n", ctxt->node->name);
#endif
if ((lastChild != NULL) &&
(lastChild->type == XML_CDATA_SECTION_NODE)) {
xmlTextConcat(lastChild, value, len);
} else {
ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
xmlAddChild(ctxt->node, ret);
}
}
/*

View File

@ -13,9 +13,15 @@
#include "config.h"
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include "xmlmemory.h"
#include "tree.h"
#include "parser.h"
#include "debugXML.h"
#include "HTMLtree.h"
#include "HTMLparser.h"
#define IS_BLANK(c) \
(((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
@ -43,7 +49,7 @@ void xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
if (ns->prefix != NULL)
fprintf(output, "namespace %s href=", ns->prefix);
else
fprintf(output, "default namespace href=", ns->prefix);
fprintf(output, "default namespace href=");
xmlDebugDumpString(output, ns->href);
fprintf(output, "\n");
@ -217,7 +223,7 @@ void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth) {
}
void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
void xmlDebugDumpDocumentHead(FILE *output, xmlDocPtr doc) {
if (output == NULL) output = stdout;
if (doc == NULL) {
fprintf(output, "DOCUMENT == NULL !\n");
@ -286,10 +292,21 @@ void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
fprintf(output, "standalone=true\n");
if (doc->oldNs != NULL)
xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
if (doc->root != NULL)
xmlDebugDumpNodeList(output, doc->root, 1);
}
void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
if (output == NULL) output = stdout;
if (doc == NULL) {
fprintf(output, "DOCUMENT == NULL !\n");
return;
}
xmlDebugDumpDocumentHead(output, doc);
if (((doc->type == XML_DOCUMENT_NODE) ||
(doc->type == XML_HTML_DOCUMENT_NODE)) &&
(doc->root != NULL))
xmlDebugDumpNodeList(output, doc->root, 1);
}
void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
int i;
xmlEntityPtr cur;
@ -422,3 +439,807 @@ void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
} else
fprintf(output, "No entities in external subset\n");
}
static int xmlLsCountNode(xmlNodePtr node) {
int ret = 0;
xmlNodePtr list = NULL;
switch (node->type) {
case XML_ELEMENT_NODE:
list = node->childs;
break;
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
list = ((xmlDocPtr) node)->root;
break;
case XML_ATTRIBUTE_NODE:
list = ((xmlAttrPtr) node)->val;
break;
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
if (node->content != NULL) {
#ifndef XML_USE_BUFFER_CONTENT
ret = xmlStrlen(node->content);
#else
ret = xmlBufferLength(node->content);
#endif
}
break;
case XML_ENTITY_REF_NODE:
case XML_DOCUMENT_TYPE_NODE:
case XML_ENTITY_NODE:
case XML_DOCUMENT_FRAG_NODE:
case XML_NOTATION_NODE:
ret = 1;
break;
}
for (;list != NULL;ret++)
list = list->next;
return(ret);
}
void xmlLsOneNode(FILE *output, xmlNodePtr node) {
switch (node->type) {
case XML_ELEMENT_NODE:
fprintf(output, "-");
break;
case XML_ATTRIBUTE_NODE:
fprintf(output, "a");
break;
case XML_TEXT_NODE:
fprintf(output, "t");
break;
case XML_CDATA_SECTION_NODE:
fprintf(output, "c");
break;
case XML_ENTITY_REF_NODE:
fprintf(output, "e");
break;
case XML_ENTITY_NODE:
fprintf(output, "E");
break;
case XML_PI_NODE:
fprintf(output, "p");
break;
case XML_COMMENT_NODE:
fprintf(output, "c");
break;
case XML_DOCUMENT_NODE:
fprintf(output, "d");
break;
case XML_HTML_DOCUMENT_NODE:
fprintf(output, "h");
break;
case XML_DOCUMENT_TYPE_NODE:
fprintf(output, "T");
break;
case XML_DOCUMENT_FRAG_NODE:
fprintf(output, "F");
break;
case XML_NOTATION_NODE:
fprintf(output, "N");
break;
default:
fprintf(output, "?");
}
if (node->properties != NULL)
fprintf(output, "a");
else
fprintf(output, "-");
if (node->nsDef != NULL)
fprintf(output, "n");
else
fprintf(output, "-");
fprintf(output, " %8d ", xmlLsCountNode(node));
switch (node->type) {
case XML_ELEMENT_NODE:
if (node->name != NULL)
fprintf(output, "%s", node->name);
break;
case XML_ATTRIBUTE_NODE:
if (node->name != NULL)
fprintf(output, "%s", node->name);
break;
case XML_TEXT_NODE:
if (node->content != NULL) {
#ifndef XML_USE_BUFFER_CONTENT
xmlDebugDumpString(output, node->content);
#else
xmlDebugDumpString(output, xmlBufferContent(node->content));
#endif
}
break;
case XML_CDATA_SECTION_NODE:
break;
case XML_ENTITY_REF_NODE:
if (node->name != NULL)
fprintf(output, "%s", node->name);
break;
case XML_ENTITY_NODE:
if (node->name != NULL)
fprintf(output, "%s", node->name);
break;
case XML_PI_NODE:
if (node->name != NULL)
fprintf(output, "%s", node->name);
break;
case XML_COMMENT_NODE:
break;
case XML_DOCUMENT_NODE:
break;
case XML_HTML_DOCUMENT_NODE:
break;
case XML_DOCUMENT_TYPE_NODE:
break;
case XML_DOCUMENT_FRAG_NODE:
break;
case XML_NOTATION_NODE:
break;
default:
if (node->name != NULL)
fprintf(output, "%s", node->name);
}
fprintf(output, "\n");
}
/****************************************************************
* *
* The XML shell related functions *
* *
****************************************************************/
/*
* TODO: Improvement/cleanups for the XML shell
* - allow to shell out an editor on a subpart
* - cleanup function registrations (with help) and calling
* - provide registration routines
*/
/**
* xmlShellList:
* @ctxt: the shell context
* @arg: unused
* @node: a node
* @node2: unused
*
* Implements the XML shell function "ls"
* Does an Unix like listing of the given node (like a directory)
*
* Returns 0
*/
int
xmlShellList(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
xmlNodePtr node2) {
xmlNodePtr cur;
if ((node->type == XML_DOCUMENT_NODE) ||
(node->type == XML_HTML_DOCUMENT_NODE)) {
cur = ((xmlDocPtr) node)->root;
} else if (node->childs != NULL) {
cur = node->childs;
} else {
xmlLsOneNode(stdout, node);
return(0);
}
while (cur != NULL) {
xmlLsOneNode(stdout, cur);
cur = cur->next;
}
return(0);
}
/**
* xmlShellDir:
* @ctxt: the shell context
* @arg: unused
* @node: a node
* @node2: unused
*
* Implements the XML shell function "dir"
* dumps informations about the node (namespace, attributes, content).
*
* Returns 0
*/
int
xmlShellDir(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
xmlNodePtr node2) {
if ((node->type == XML_DOCUMENT_NODE) ||
(node->type == XML_HTML_DOCUMENT_NODE)) {
xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
} else if (node->type == XML_ATTRIBUTE_NODE) {
xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
} else {
xmlDebugDumpOneNode(stdout, node, 0);
}
return(0);
}
/**
* xmlShellCat:
* @ctxt: the shell context
* @arg: unused
* @node: a node
* @node2: unused
*
* Implements the XML shell function "cat"
* dumps the serialization node content (XML or HTML).
*
* Returns 0
*/
int
xmlShellCat(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
xmlNodePtr node2) {
xmlElemDump(stdout, ctxt->doc, node);
printf("\n");
return(0);
}
/**
* xmlShellLoad:
* @ctxt: the shell context
* @filename: the file name
* @node: unused
* @node2: unused
*
* Implements the XML shell function "load"
* loads a new document specified by the filename
*
* Returns 0 or -1 if loading failed
*/
int
xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
xmlNodePtr node2) {
xmlDocPtr doc;
int html = 0;
if (ctxt->doc != NULL)
html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
if (html) {
doc = htmlParseFile(filename, NULL);
} else {
doc = xmlParseFile(filename);
}
if (doc != NULL) {
if (ctxt->loaded == 1) {
xmlFreeDoc(ctxt->doc);
}
ctxt->loaded = 1;
xmlXPathFreeContext(ctxt->pctxt);
xmlFree(ctxt->filename);
ctxt->doc = doc;
ctxt->node = (xmlNodePtr) doc;
ctxt->pctxt = xmlXPathNewContext(doc);
ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
} else
return(-1);
return(0);
}
/**
* xmlShellWrite:
* @ctxt: the shell context
* @filename: the file name
* @node: a node in the tree
* @node2: unused
*
* Implements the XML shell function "write"
* Write the current node to the filename, it saves the serailization
* of the subtree under the @node specified
*
* Returns 0 or -1 in case of error
*/
int
xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
xmlNodePtr node2) {
if (node == NULL)
return(-1);
if ((filename == NULL) || (filename[0] == 0)) {
fprintf(stderr, "Write command requires a filename argument\n");
return(-1);
}
#ifdef W_OK
if (access((char *) filename, W_OK)) {
fprintf(stderr, "Cannot write to %s\n", filename);
return(-1);
}
#endif
switch(node->type) {
case XML_DOCUMENT_NODE:
if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
fprintf(stderr, "Failed to write to %s\n", filename);
return(-1);
}
break;
case XML_HTML_DOCUMENT_NODE:
if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
fprintf(stderr, "Failed to write to %s\n", filename);
return(-1);
}
break;
default: {
FILE *f;
f = fopen((char *) filename, "w");
if (f == NULL) {
fprintf(stderr, "Failed to write to %s\n", filename);
return(-1);
}
xmlElemDump(f, ctxt->doc, node);
fclose(f);
}
}
return(0);
}
/**
* xmlShellSave:
* @ctxt: the shell context
* @filename: the file name (optionnal)
* @node: unused
* @node2: unused
*
* Implements the XML shell function "save"
* Write the current document to the filename, or it's original name
*
* Returns 0 or -1 in case of error
*/
int
xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
xmlNodePtr node2) {
if (ctxt->doc == NULL)
return(-1);
if ((filename == NULL) || (filename[0] == 0))
filename = ctxt->filename;
#ifdef W_OK
if (access((char *) filename, W_OK)) {
fprintf(stderr, "Cannot save to %s\n", filename);
return(-1);
}
#endif
switch(ctxt->doc->type) {
case XML_DOCUMENT_NODE:
if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
fprintf(stderr, "Failed to save to %s\n", filename);
}
break;
case XML_HTML_DOCUMENT_NODE:
if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
fprintf(stderr, "Failed to save to %s\n", filename);
}
break;
default:
fprintf(stderr,
"To save to subparts of a document use the 'write' command\n");
return(-1);
}
return(0);
}
/**
* xmlShellValidate:
* @ctxt: the shell context
* @dtd: the DTD URI (optionnal)
* @node: unused
* @node2: unused
*
* Implements the XML shell function "validate"
* Validate the document, if a DTD path is provided, then the validation
* is done against the given DTD.
*
* Returns 0 or -1 in case of error
*/
int
xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node,
xmlNodePtr node2) {
xmlValidCtxt vctxt;
int res = -1;
vctxt.userData = stderr;
vctxt.error = (xmlValidityErrorFunc) fprintf;
vctxt.warning = (xmlValidityWarningFunc) fprintf;
if ((dtd == NULL) || (dtd[0] == 0)) {
res = xmlValidateDocument(&vctxt, ctxt->doc);
} else {
xmlDtdPtr subset;
subset = xmlParseDTD(NULL, (xmlChar *) dtd);
if (subset != NULL) {
res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
xmlFreeDtd(subset);
}
}
return(res);
}
/**
* xmlShellDu:
* @ctxt: the shell context
* @arg: unused
* @tree: a node defining a subtree
* @node2: unused
*
* Implements the XML shell function "du"
* show the structure of the subtree under node @tree
* If @tree is null, the command works on the current node.
*
* Returns 0 or -1 in case of error
*/
int
xmlShellDu(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree,
xmlNodePtr node2) {
xmlNodePtr node;
int indent = 0,i;
if (tree == NULL) return(-1);
node = tree;
while (node != NULL) {
if ((node->type == XML_DOCUMENT_NODE) ||
(node->type == XML_HTML_DOCUMENT_NODE)) {
printf("/\n");
} else if (node->type == XML_ELEMENT_NODE) {
for (i = 0;i < indent;i++)
printf(" ");
printf("%s\n", node->name);
} else {
}
/*
* Browse the full subtree, deep first
*/
if ((node->type == XML_DOCUMENT_NODE) ||
(node->type == XML_HTML_DOCUMENT_NODE)) {
node = ((xmlDocPtr) node)->root;
} else if (node->childs != NULL) {
/* deep first */
node = node->childs;
indent++;
} else if ((node != tree) && (node->next != NULL)) {
/* then siblings */
node = node->next;
} else if (node != tree) {
/* go up to parents->next if needed */
while (node != tree) {
if (node->parent != NULL) {
node = node->parent;
indent--;
}
if ((node != tree) && (node->next != NULL)) {
node = node->next;
break;
}
if (node->parent == NULL) {
node = NULL;
break;
}
if (node == tree) {
node = NULL;
break;
}
}
/* exit condition */
if (node == tree)
node = NULL;
} else
node = NULL;
}
return(0);
}
/**
* xmlShellPwd:
* @ctxt: the shell context
* @buffer: the output buffer
* @tree: a node
* @node2: unused
*
* Implements the XML shell function "pwd"
* Show the full path from the root to the node, if needed building
* thumblers when similar elements exists at a given ancestor level.
* The output is compatible with XPath commands.
*
* Returns 0 or -1 in case of error
*/
int
xmlShellPwd(xmlShellCtxtPtr ctxt, char *buffer, xmlNodePtr node,
xmlNodePtr node2) {
xmlNodePtr cur, tmp, next;
char buf[500];
char sep;
const char *name;
int occur = 0;
buffer[0] = 0;
if (node == NULL) return(-1);
cur = node;
do {
name = "";
sep= '?';
occur = 0;
if ((cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_HTML_DOCUMENT_NODE)) {
sep = '/';
next = NULL;
} else if (cur->type == XML_ELEMENT_NODE) {
sep = '/';
name = (const char *)cur->name;
next = cur->parent;
/*
* Thumbler index computation
*/
tmp = cur->prev;
while (tmp != NULL) {
if (!xmlStrcmp(cur->name, tmp->name))
occur++;
tmp = tmp->prev;
}
if (occur == 0) {
tmp = cur->next;
while (tmp != NULL) {
if (!xmlStrcmp(cur->name, tmp->name))
occur++;
tmp = tmp->next;
}
if (occur != 0) occur = 1;
} else
occur++;
} else if (cur->type == XML_ATTRIBUTE_NODE) {
sep = '@';
name = (const char *) (((xmlAttrPtr) cur)->name);
next = ((xmlAttrPtr) cur)->node;
} else {
next = cur->parent;
}
if (occur == 0)
sprintf(buf, "%c%s%s", sep, name, buffer);
else
sprintf(buf, "%c%s[%d]%s", sep, name, occur, buffer);
strcpy(buffer, buf);
cur = next;
} while (cur != NULL);
return(0);
}
/**
* xmlShell
* @doc: the initial document
* @filename: the output buffer
* @input: the line reading function
* @output: the output FILE*
*
* Implements the XML shell
* This allow to load, validate, view, modify and save a document
* using a environment similar to a UNIX commandline.
*/
void
xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
FILE *output) {
char prompt[500] = "/ > ";
char *cmdline = NULL;
int nbargs;
char command[100];
char arg[400];
xmlShellCtxtPtr ctxt;
xmlXPathObjectPtr list;
if (doc == NULL)
return;
if (filename == NULL)
return;
if (input == NULL)
return;
if (output == NULL)
return;
ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
if (ctxt == NULL)
return;
ctxt->loaded = 0;
ctxt->doc = doc;
ctxt->input = input;
ctxt->output = output;
ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
ctxt->node = (xmlNodePtr) ctxt->doc;
ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
if (ctxt->pctxt == NULL) {
xmlFree(ctxt);
return;
}
while (1) {
if (ctxt->node == (xmlNodePtr) ctxt->doc)
sprintf(prompt, "%s > ", "/");
else if (ctxt->node->name)
sprintf(prompt, "%s > ", ctxt->node->name);
else
sprintf(prompt, "? > ");
cmdline = ctxt->input(prompt);
if (cmdline == NULL) break;
command[0] = 0;
arg[0] = 0;
nbargs = sscanf(cmdline, "%s %s", command, arg);
if (command[0] == 0) continue;
if (!strcmp(command, "exit"))
break;
if (!strcmp(command, "quit"))
break;
if (!strcmp(command, "bye"))
break;
if (!strcmp(command, "validate")) {
xmlShellValidate(ctxt, arg, NULL, NULL);
} else if (!strcmp(command, "load")) {
xmlShellLoad(ctxt, arg, NULL, NULL);
} else if (!strcmp(command, "save")) {
xmlShellSave(ctxt, arg, NULL, NULL);
} else if (!strcmp(command, "write")) {
xmlShellWrite(ctxt, arg, NULL, NULL);
} else if (!strcmp(command, "free")) {
if (arg[0] == 0) {
xmlMemShow(stdout, 0);
} else {
int len = 0;
sscanf(arg, "%d", &len);
xmlMemShow(stdout, len);
}
} else if (!strcmp(command, "pwd")) {
char dir[500];
if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
printf("%s\n", dir);
} else if (!strcmp(command, "du")) {
xmlShellDu(ctxt, NULL, ctxt->node, NULL);
} else if ((!strcmp(command, "ls")) ||
(!strcmp(command, "dir"))) {
int dir = (!strcmp(command, "dir"));
if (arg[0] == 0) {
if (dir)
xmlShellDir(ctxt, NULL, ctxt->node, NULL);
else
xmlShellList(ctxt, NULL, ctxt->node, NULL);
} else {
ctxt->pctxt->node = ctxt->node;
if (ctxt->pctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
if (list != NULL) {
switch (list->type) {
case XPATH_UNDEFINED:
fprintf(stderr, "%s: no such node\n", arg);
break;
case XPATH_NODESET: {
int i;
for (i = 0;i < list->nodesetval->nodeNr;i++) {
if (dir)
xmlShellDir(ctxt, NULL,
list->nodesetval->nodeTab[i], NULL);
else
xmlShellList(ctxt, NULL,
list->nodesetval->nodeTab[i], NULL);
}
break;
}
case XPATH_BOOLEAN:
fprintf(stderr, "%s is a Boolean\n", arg);
break;
case XPATH_NUMBER:
fprintf(stderr, "%s is a number\n", arg);
break;
case XPATH_STRING:
fprintf(stderr, "%s is a string\n", arg);
break;
}
xmlXPathFreeNodeSetList(list);
} else {
fprintf(stderr, "%s: no such node\n", arg);
}
if (ctxt->pctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
ctxt->pctxt->nodelist = NULL;
}
} else if (!strcmp(command, "cd")) {
if (arg[0] == 0) {
ctxt->node = (xmlNodePtr) ctxt->doc;
} else {
ctxt->pctxt->node = ctxt->node;
if (ctxt->pctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
if (list != NULL) {
switch (list->type) {
case XPATH_UNDEFINED:
fprintf(stderr, "%s: no such node\n", arg);
break;
case XPATH_NODESET:
if (list->nodesetval->nodeNr == 1) {
ctxt->node = list->nodesetval->nodeTab[0];
} else
fprintf(stderr, "%s is a %d Node Set\n",
arg, list->nodesetval->nodeNr);
break;
case XPATH_BOOLEAN:
fprintf(stderr, "%s is a Boolean\n", arg);
break;
case XPATH_NUMBER:
fprintf(stderr, "%s is a number\n", arg);
break;
case XPATH_STRING:
fprintf(stderr, "%s is a string\n", arg);
break;
}
xmlXPathFreeNodeSetList(list);
} else {
fprintf(stderr, "%s: no such node\n", arg);
}
if (ctxt->pctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
ctxt->pctxt->nodelist = NULL;
}
} else if (!strcmp(command, "cat")) {
if (arg[0] == 0) {
xmlShellCat(ctxt, NULL, ctxt->node, NULL);
} else {
ctxt->pctxt->node = ctxt->node;
if (ctxt->pctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
if (list != NULL) {
switch (list->type) {
case XPATH_UNDEFINED:
fprintf(stderr, "%s: no such node\n", arg);
break;
case XPATH_NODESET: {
int i;
for (i = 0;i < list->nodesetval->nodeNr;i++) {
if (i > 0) printf(" -------\n");
xmlShellCat(ctxt, NULL,
list->nodesetval->nodeTab[i], NULL);
}
break;
}
case XPATH_BOOLEAN:
fprintf(stderr, "%s is a Boolean\n", arg);
break;
case XPATH_NUMBER:
fprintf(stderr, "%s is a number\n", arg);
break;
case XPATH_STRING:
fprintf(stderr, "%s is a string\n", arg);
break;
}
xmlXPathFreeNodeSetList(list);
} else {
fprintf(stderr, "%s: no such node\n", arg);
}
if (ctxt->pctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
ctxt->pctxt->nodelist = NULL;
}
} else {
fprintf(stderr, "Unknown command %s\n", command);
}
free(cmdline); /* not xmlFree here ! */
}
xmlXPathFreeContext(ctxt->pctxt);
if (ctxt->loaded) {
xmlFreeDoc(ctxt->doc);
}
xmlFree(ctxt);
if (cmdline != NULL)
free(cmdline); /* not xmlFree here ! */
}

View File

@ -7,19 +7,97 @@
#ifndef __DEBUG_XML__
#define __DEBUG_XML__
#include <stdio.h>
#include "tree.h"
#include "xpath.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void xmlDebugDumpString(FILE *output, const xmlChar *str);
extern void xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth);
extern void xmlDebugDumpAttrList(FILE *output, xmlAttrPtr attr, int depth);
extern void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth);
extern void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth);
extern void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth);
extern void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc);
extern void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc);
/*
* The standard Dump routines
*/
void xmlDebugDumpString (FILE *output,
const xmlChar *str);
void xmlDebugDumpAttr (FILE *output,
xmlAttrPtr attr,
int depth);
void xmlDebugDumpAttrList (FILE *output,
xmlAttrPtr attr,
int depth);
void xmlDebugDumpOneNode (FILE *output,
xmlNodePtr node,
int depth);
void xmlDebugDumpNode (FILE *output,
xmlNodePtr node,
int depth);
void xmlDebugDumpNodeList (FILE *output,
xmlNodePtr node,
int depth);
void xmlDebugDumpDocumentHead(FILE *output,
xmlDocPtr doc);
void xmlDebugDumpDocument (FILE *output,
xmlDocPtr doc);
void xmlDebugDumpEntities (FILE *output,
xmlDocPtr doc);
void xmlLsOneNode (FILE *output,
xmlNodePtr node);
/****************************************************************
* *
* The XML shell related structures and functions *
* *
****************************************************************/
/**
* xmlShellReadlineFunc:
* @prompt: a string prompt
*
* This is a generic signature for the XML shell input function
*
* Returns a string which will be freed by the Shell
*/
typedef char * (* xmlShellReadlineFunc)(char *prompt);
/*
* The shell context itself
* TODO: add the defined function tables.
*/
typedef struct xmlShellCtxt {
char *filename;
xmlDocPtr doc;
xmlNodePtr node;
xmlXPathContextPtr pctxt;
int loaded;
FILE *output;
xmlShellReadlineFunc input;
} xmlShellCtxt, *xmlShellCtxtPtr;
/**
* xmlShellCmd:
* @ctxt: a shell context
* @arg: a string argument
* @node: a first node
* @node2: a second node
*
* This is a generic signature for the XML shell functions
*
* Returns an int, negative returns indicating errors
*/
typedef int (* xmlShellCmd) (xmlShellCtxtPtr ctxt,
char *arg,
xmlNodePtr node,
xmlNodePtr node2);
/*
* The Shell interface.
*/
void xmlShell (xmlDocPtr doc,
char *filename,
xmlShellReadlineFunc input,
FILE *output);
#ifdef __cplusplus
}
#endif

View File

@ -128,6 +128,9 @@ for really accurate description</h3>
<ul>
<li>working on HTML and XML links recognition layers, get in touch with me
if you want to test those.</li>
<li>a Push interface for the XML parser</li>
<li>an shell like interface to the document tree (try tester --shell :-)</li>
<li>lots of bug fixes and improvement added over XMas hollidays</li>
</ul>
<h3>1.8.2: Dec 21 1999</h3>
@ -901,6 +904,6 @@ base under gnome-xml/example</p>
<p><a href="mailto:Daniel.Veillard@w3.org">Daniel Veillard</a></p>
<p>$Id: xml.html,v 1.16 1997/01/04 02:49:42 veillard Exp $</p>
<p>$Id: xml.html,v 1.17 1999/12/21 15:35:27 veillard Exp $</p>
</body>
</html>

View File

@ -114,10 +114,13 @@ xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type,
cur->SystemID = xmlStrdup(SystemID);
else
cur->SystemID = NULL;
if (content != NULL)
cur->content = xmlStrdup(content);
else
if (content != NULL) {
cur->length = xmlStrlen(content);
cur->content = xmlStrndup(content, cur->length);
} else {
cur->length = 0;
cur->content = NULL;
}
cur->orig = NULL;
table->nb_entities++;
}

View File

@ -34,6 +34,7 @@ typedef struct xmlEntity {
const xmlChar *ExternalID; /* External identifier for PUBLIC Entity */
const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC Entity */
xmlChar *content; /* The entity content or ndata if unparsed */
int length; /* the content length */
xmlChar *orig; /* The entity cont without ref substitution */
} xmlEntity;
typedef xmlEntity *xmlEntityPtr;

View File

@ -7,19 +7,97 @@
#ifndef __DEBUG_XML__
#define __DEBUG_XML__
#include <stdio.h>
#include "tree.h"
#include "xpath.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void xmlDebugDumpString(FILE *output, const xmlChar *str);
extern void xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth);
extern void xmlDebugDumpAttrList(FILE *output, xmlAttrPtr attr, int depth);
extern void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth);
extern void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth);
extern void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth);
extern void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc);
extern void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc);
/*
* The standard Dump routines
*/
void xmlDebugDumpString (FILE *output,
const xmlChar *str);
void xmlDebugDumpAttr (FILE *output,
xmlAttrPtr attr,
int depth);
void xmlDebugDumpAttrList (FILE *output,
xmlAttrPtr attr,
int depth);
void xmlDebugDumpOneNode (FILE *output,
xmlNodePtr node,
int depth);
void xmlDebugDumpNode (FILE *output,
xmlNodePtr node,
int depth);
void xmlDebugDumpNodeList (FILE *output,
xmlNodePtr node,
int depth);
void xmlDebugDumpDocumentHead(FILE *output,
xmlDocPtr doc);
void xmlDebugDumpDocument (FILE *output,
xmlDocPtr doc);
void xmlDebugDumpEntities (FILE *output,
xmlDocPtr doc);
void xmlLsOneNode (FILE *output,
xmlNodePtr node);
/****************************************************************
* *
* The XML shell related structures and functions *
* *
****************************************************************/
/**
* xmlShellReadlineFunc:
* @prompt: a string prompt
*
* This is a generic signature for the XML shell input function
*
* Returns a string which will be freed by the Shell
*/
typedef char * (* xmlShellReadlineFunc)(char *prompt);
/*
* The shell context itself
* TODO: add the defined function tables.
*/
typedef struct xmlShellCtxt {
char *filename;
xmlDocPtr doc;
xmlNodePtr node;
xmlXPathContextPtr pctxt;
int loaded;
FILE *output;
xmlShellReadlineFunc input;
} xmlShellCtxt, *xmlShellCtxtPtr;
/**
* xmlShellCmd:
* @ctxt: a shell context
* @arg: a string argument
* @node: a first node
* @node2: a second node
*
* This is a generic signature for the XML shell functions
*
* Returns an int, negative returns indicating errors
*/
typedef int (* xmlShellCmd) (xmlShellCtxtPtr ctxt,
char *arg,
xmlNodePtr node,
xmlNodePtr node2);
/*
* The Shell interface.
*/
void xmlShell (xmlDocPtr doc,
char *filename,
xmlShellReadlineFunc input,
FILE *output);
#ifdef __cplusplus
}
#endif

View File

@ -34,6 +34,7 @@ typedef struct xmlEntity {
const xmlChar *ExternalID; /* External identifier for PUBLIC Entity */
const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC Entity */
xmlChar *content; /* The entity content or ndata if unparsed */
int length; /* the content length */
xmlChar *orig; /* The entity cont without ref substitution */
} xmlEntity;
typedef xmlEntity *xmlEntityPtr;

View File

@ -40,11 +40,12 @@ typedef struct xmlParserInput {
const char *filename; /* The file analyzed, if any */
const char *directory; /* the directory/base of teh file */
const xmlChar *base; /* Base of the array to parse */
const xmlChar *cur; /* Current char being parsed */
const xmlChar *base; /* Base of the array to parse */
const xmlChar *cur; /* Current char being parsed */
int length; /* length if known */
int line; /* Current line */
int col; /* Current column */
int consumed; /* How many xmlChars were already consumed */
int consumed; /* How many xmlChars already consumed */
xmlParserInputDeallocate free; /* function to deallocate the base */
} xmlParserInput;
typedef xmlParserInput *xmlParserInputPtr;
@ -77,20 +78,25 @@ typedef _xmlParserNodeInfoSeq xmlParserNodeInfoSeq;
typedef xmlParserNodeInfoSeq *xmlParserNodeInfoSeqPtr;
/**
* The parser is not a state based parser, but we need to maintain
* The parser is not (yet) a state based parser, but we need to maintain
* minimum state informations, especially for entities processing.
*/
typedef enum {
XML_PARSER_EOF = 0,
XML_PARSER_PROLOG,
XML_PARSER_CONTENT,
XML_PARSER_ENTITY_DECL,
XML_PARSER_ENTITY_VALUE,
XML_PARSER_ATTRIBUTE_VALUE,
XML_PARSER_DTD,
XML_PARSER_EPILOG,
XML_PARSER_COMMENT,
XML_PARSER_CDATA_SECTION
XML_PARSER_EOF = -1, /* nothing is to be parsed */
XML_PARSER_START = 0, /* nothing has been parsed */
XML_PARSER_MISC, /* Misc* before int subset */
XML_PARSER_PI, /* Whithin a processing instruction */
XML_PARSER_DTD, /* within some DTD content */
XML_PARSER_PROLOG, /* Misc* after internal subset */
XML_PARSER_COMMENT, /* within a comment */
XML_PARSER_START_TAG, /* within a start tag */
XML_PARSER_CONTENT, /* within the content */
XML_PARSER_CDATA_SECTION, /* within a CDATA section */
XML_PARSER_END_TAG, /* within a closing tag */
XML_PARSER_ENTITY_DECL, /* within an entity declaration */
XML_PARSER_ENTITY_VALUE, /* within an entity value in a decl */
XML_PARSER_ATTRIBUTE_VALUE, /* within an attribute value */
XML_PARSER_EPILOG /* the Misc* after the last end tag */
} xmlParserInputState;
/**
@ -151,6 +157,7 @@ typedef struct _xmlParserCtxt {
xmlChar * *nameTab; /* array of nodes */
long nbChars; /* number of xmlChar processed */
long checkIndex; /* used by progressive parsing lookup */
} _xmlParserCtxt;
typedef _xmlParserCtxt xmlParserCtxt;
typedef xmlParserCtxt *xmlParserCtxtPtr;
@ -347,13 +354,35 @@ xmlDtdPtr xmlParseDTD (const xmlChar *ExternalID,
xmlDtdPtr xmlSAXParseDTD (xmlSAXHandlerPtr sax,
const xmlChar *ExternalID,
const xmlChar *SystemID);
/**
* SAX initialization routines
*/
void xmlDefaultSAXHandlerInit(void);
void htmlDefaultSAXHandlerInit(void);
/**
* Parser contexts handling.
*/
void xmlInitParserCtxt (xmlParserCtxtPtr ctxt);
void xmlClearParserCtxt (xmlParserCtxtPtr ctxt);
void xmlFreeParserCtxt (xmlParserCtxtPtr ctxt);
void xmlSetupParserForBuffer (xmlParserCtxtPtr ctxt,
const xmlChar* buffer,
const char* filename);
void xmlDefaultSAXHandlerInit(void);
void htmlDefaultSAXHandlerInit(void);
xmlParserCtxtPtr xmlCreateDocParserCtxt (xmlChar *cur);
/**
* Interfaces for the Push mode
*/
xmlParserCtxtPtr xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax,
void *user_data,
const char *chunk,
int size,
const char *filename);
int xmlParseChunk (xmlParserCtxtPtr ctxt,
const char *chunk,
int size,
int terminate);
/**
* Node infos

View File

@ -435,9 +435,10 @@ typedef unsigned char CHARVAL;
* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
*/
#define IS_CHAR(c) \
((((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
(((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF))) && \
(((c) <= 0xD7FF) || ((c) >= 0xE000)) && ((c) <= 0x10FFFF))
((((c) >= 0x20) && ((c) <= 0xD7FF)) || \
((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
(((c) >= 0xE000) && ((c) <= 0xFFFD)) || \
(((c) >= 0x10000) && ((c) <= 0x10FFFF)))
/*
* [85] BaseChar ::= ... long list see REC ...
@ -595,8 +596,7 @@ void xmlParseDocTypeDecl (xmlParserCtxtPtr ctxt);
xmlChar * xmlParseAttribute (xmlParserCtxtPtr ctxt,
xmlChar **value);
xmlChar * xmlParseStartTag (xmlParserCtxtPtr ctxt);
void xmlParseEndTag (xmlParserCtxtPtr ctxt,
xmlChar *tagname);
void xmlParseEndTag (xmlParserCtxtPtr ctxt);
void xmlParseCDSect (xmlParserCtxtPtr ctxt);
void xmlParseContent (xmlParserCtxtPtr ctxt);
void xmlParseElement (xmlParserCtxtPtr ctxt);

View File

@ -526,6 +526,9 @@ void xmlDocDumpMemory (xmlDocPtr cur,
int *size);
void xmlDocDump (FILE *f,
xmlDocPtr cur);
void xmlElemDump (FILE *f,
xmlDocPtr cur,
xmlNodePtr elem);
int xmlSaveFile (const char *filename,
xmlDocPtr cur);

View File

@ -37,6 +37,9 @@ typedef xmlParserInputBuffer *xmlParserInputBufferPtr;
* Interfaces
*/
xmlParserInputBufferPtr
xmlAllocParserInputBuffer (xmlCharEncoding enc);
xmlParserInputBufferPtr
xmlParserInputBufferCreateFilename (const char *filename,
xmlCharEncoding enc);

View File

@ -1,5 +1,5 @@
/*
* memory.h: interface for the memory allocation debug.
* xmlmemory.h: interface for the memory allocation debug.
*
* Daniel.Veillard@w3.org
*/
@ -24,6 +24,7 @@
#define xmlInitMemory()
#define xmlMemoryDump()
#define xmlMemDisplay(x)
#define xmlMemShow(x, d)
#else /* ! NO_DEBUG_MEMORY */
#include <stdio.h>
@ -51,6 +52,7 @@ void xmlFree (void *ptr);
char * xmlMemStrdup (const char *str);
int xmlMemUsed (void);
void xmlMemDisplay (FILE *fp);
void xmlMemShow (FILE *fp, int nr);
void xmlMemoryDump (void);
int xmlInitMemory (void);

View File

@ -205,6 +205,9 @@ xmlXPathObjectPtr xmlXPathEval (const xmlChar *str,
void xmlXPathFreeObject (xmlXPathObjectPtr obj);
xmlXPathObjectPtr xmlXPathEvalExpression (const xmlChar *str,
xmlXPathContextPtr ctxt);
xmlNodeSetPtr xmlXPathNodeSetCreate (xmlNodePtr val);
void xmlXPathFreeNodeSetList (xmlXPathObjectPtr obj);
void xmlXPathFreeNodeSet (xmlNodeSetPtr obj);
#ifdef __cplusplus
}

1102
parser.c

File diff suppressed because it is too large Load Diff

View File

@ -40,11 +40,12 @@ typedef struct xmlParserInput {
const char *filename; /* The file analyzed, if any */
const char *directory; /* the directory/base of teh file */
const xmlChar *base; /* Base of the array to parse */
const xmlChar *cur; /* Current char being parsed */
const xmlChar *base; /* Base of the array to parse */
const xmlChar *cur; /* Current char being parsed */
int length; /* length if known */
int line; /* Current line */
int col; /* Current column */
int consumed; /* How many xmlChars were already consumed */
int consumed; /* How many xmlChars already consumed */
xmlParserInputDeallocate free; /* function to deallocate the base */
} xmlParserInput;
typedef xmlParserInput *xmlParserInputPtr;
@ -77,20 +78,25 @@ typedef _xmlParserNodeInfoSeq xmlParserNodeInfoSeq;
typedef xmlParserNodeInfoSeq *xmlParserNodeInfoSeqPtr;
/**
* The parser is not a state based parser, but we need to maintain
* The parser is not (yet) a state based parser, but we need to maintain
* minimum state informations, especially for entities processing.
*/
typedef enum {
XML_PARSER_EOF = 0,
XML_PARSER_PROLOG,
XML_PARSER_CONTENT,
XML_PARSER_ENTITY_DECL,
XML_PARSER_ENTITY_VALUE,
XML_PARSER_ATTRIBUTE_VALUE,
XML_PARSER_DTD,
XML_PARSER_EPILOG,
XML_PARSER_COMMENT,
XML_PARSER_CDATA_SECTION
XML_PARSER_EOF = -1, /* nothing is to be parsed */
XML_PARSER_START = 0, /* nothing has been parsed */
XML_PARSER_MISC, /* Misc* before int subset */
XML_PARSER_PI, /* Whithin a processing instruction */
XML_PARSER_DTD, /* within some DTD content */
XML_PARSER_PROLOG, /* Misc* after internal subset */
XML_PARSER_COMMENT, /* within a comment */
XML_PARSER_START_TAG, /* within a start tag */
XML_PARSER_CONTENT, /* within the content */
XML_PARSER_CDATA_SECTION, /* within a CDATA section */
XML_PARSER_END_TAG, /* within a closing tag */
XML_PARSER_ENTITY_DECL, /* within an entity declaration */
XML_PARSER_ENTITY_VALUE, /* within an entity value in a decl */
XML_PARSER_ATTRIBUTE_VALUE, /* within an attribute value */
XML_PARSER_EPILOG /* the Misc* after the last end tag */
} xmlParserInputState;
/**
@ -151,6 +157,7 @@ typedef struct _xmlParserCtxt {
xmlChar * *nameTab; /* array of nodes */
long nbChars; /* number of xmlChar processed */
long checkIndex; /* used by progressive parsing lookup */
} _xmlParserCtxt;
typedef _xmlParserCtxt xmlParserCtxt;
typedef xmlParserCtxt *xmlParserCtxtPtr;
@ -347,13 +354,35 @@ xmlDtdPtr xmlParseDTD (const xmlChar *ExternalID,
xmlDtdPtr xmlSAXParseDTD (xmlSAXHandlerPtr sax,
const xmlChar *ExternalID,
const xmlChar *SystemID);
/**
* SAX initialization routines
*/
void xmlDefaultSAXHandlerInit(void);
void htmlDefaultSAXHandlerInit(void);
/**
* Parser contexts handling.
*/
void xmlInitParserCtxt (xmlParserCtxtPtr ctxt);
void xmlClearParserCtxt (xmlParserCtxtPtr ctxt);
void xmlFreeParserCtxt (xmlParserCtxtPtr ctxt);
void xmlSetupParserForBuffer (xmlParserCtxtPtr ctxt,
const xmlChar* buffer,
const char* filename);
void xmlDefaultSAXHandlerInit(void);
void htmlDefaultSAXHandlerInit(void);
xmlParserCtxtPtr xmlCreateDocParserCtxt (xmlChar *cur);
/**
* Interfaces for the Push mode
*/
xmlParserCtxtPtr xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax,
void *user_data,
const char *chunk,
int size,
const char *filename);
int xmlParseChunk (xmlParserCtxtPtr ctxt,
const char *chunk,
int size,
int terminate);
/**
* Node infos

View File

@ -435,9 +435,10 @@ typedef unsigned char CHARVAL;
* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
*/
#define IS_CHAR(c) \
((((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
(((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF))) && \
(((c) <= 0xD7FF) || ((c) >= 0xE000)) && ((c) <= 0x10FFFF))
((((c) >= 0x20) && ((c) <= 0xD7FF)) || \
((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
(((c) >= 0xE000) && ((c) <= 0xFFFD)) || \
(((c) >= 0x10000) && ((c) <= 0x10FFFF)))
/*
* [85] BaseChar ::= ... long list see REC ...
@ -595,8 +596,7 @@ void xmlParseDocTypeDecl (xmlParserCtxtPtr ctxt);
xmlChar * xmlParseAttribute (xmlParserCtxtPtr ctxt,
xmlChar **value);
xmlChar * xmlParseStartTag (xmlParserCtxtPtr ctxt);
void xmlParseEndTag (xmlParserCtxtPtr ctxt,
xmlChar *tagname);
void xmlParseEndTag (xmlParserCtxtPtr ctxt);
void xmlParseCDSect (xmlParserCtxtPtr ctxt);
void xmlParseContent (xmlParserCtxtPtr ctxt);
void xmlParseElement (xmlParserCtxtPtr ctxt);

129
testSAX.c
View File

@ -45,6 +45,7 @@
static int debug = 0;
static int copy = 0;
static int recovery = 0;
static int push = 0;
xmlSAXHandler emptySAXHandlerStruct = {
NULL, /* internalSubset */
@ -77,29 +78,6 @@ xmlSAXHandler emptySAXHandlerStruct = {
xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
extern xmlSAXHandlerPtr debugSAXHandler;
/*
* Note: there is a couple of errors introduced on purpose.
*/
static char buffer[] =
"<?xml version=\"1.0\"?>\n\
<?xml:namespace ns = \"http://www.ietf.org/standards/dav/\" prefix = \"D\"?>\n\
<?xml:namespace ns = \"http://www.w3.com/standards/z39.50/\" prefix = \"Z\"?>\n\
<D:propertyupdate>\n\
<D:set a=\"'toto'\" b>\n\
<D:prop>\n\
<Z:authors>\n\
<Z:Author>Jim Whitehead</Z:Author>\n\
<Z:Author>Roy Fielding</Z:Author>\n\
</Z:authors>\n\
</D:prop>\n\
</D:set>\n\
<D:remove>\n\
<D:prop><Z:Copyright-Owner/></D:prop>\n\
</D:remove>\n\
</D:propertyupdate>\n\
\n\
";
/************************************************************************
* *
* Debug Handlers *
@ -588,42 +566,76 @@ xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
void parseAndPrintFile(char *filename) {
int res;
/*
* Empty callbacks for checking
*/
res = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
if (res != 0) {
fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
}
if (push) {
FILE *f;
/*
* Debug callback
*/
res = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
if (res != 0) {
fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
/*
* Empty callbacks for checking
*/
f = fopen(filename, "r");
if (f != NULL) {
int res;
char chars[10];
xmlParserCtxtPtr ctxt;
res = fread(chars, 1, 4, f);
if (res > 0) {
ctxt = xmlCreatePushParserCtxt(emptySAXHandler, NULL,
chars, res, filename);
while ((res = fread(chars, 1, 3, f)) > 0) {
xmlParseChunk(ctxt, chars, res, 0);
}
xmlParseChunk(ctxt, chars, 0, 1);
xmlFreeParserCtxt(ctxt);
}
fclose(f);
} else {
fprintf(stderr, "Cannot read file %s\n", filename);
}
/*
* Debug callback
*/
f = fopen(filename, "r");
if (f != NULL) {
int res;
char chars[10];
xmlParserCtxtPtr ctxt;
res = fread(chars, 1, 4, f);
if (res > 0) {
ctxt = xmlCreatePushParserCtxt(debugSAXHandler, NULL,
chars, res, filename);
while ((res = fread(chars, 1, 3, f)) > 0) {
xmlParseChunk(ctxt, chars, res, 0);
}
res = xmlParseChunk(ctxt, chars, 0, 1);
xmlFreeParserCtxt(ctxt);
if (res != 0) {
fprintf(stdout,
"xmlSAXUserParseFile returned error %d\n", res);
}
}
fclose(f);
}
} else {
/*
* Empty callbacks for checking
*/
res = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
if (res != 0) {
fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
}
/*
* Debug callback
*/
res = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
if (res != 0) {
fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
}
}
}
void parseAndPrintBuffer(char *buf) {
int res;
/*
* Empty callbacks for checking
*/
res = xmlSAXUserParseMemory(emptySAXHandler, NULL, buf, strlen(buf));
if (res != 0) {
fprintf(stdout, "xmlSAXUserParseMemory returned error %d\n", res);
}
/*
* Debug callback
*/
res = xmlSAXUserParseMemory(debugSAXHandler, NULL, buf, strlen(buf));
if (res != 0) {
fprintf(stdout, "xmlSAXUserParseMemory returned error %d\n", res);
}
}
int main(int argc, char **argv) {
int i;
@ -637,6 +649,9 @@ int main(int argc, char **argv) {
else if ((!strcmp(argv[i], "-recover")) ||
(!strcmp(argv[i], "--recover")))
recovery++;
else if ((!strcmp(argv[i], "-push")) ||
(!strcmp(argv[i], "--push")))
push++;
}
for (i = 1; i < argc ; i++) {
if (argv[i][0] != '-') {
@ -644,10 +659,6 @@ int main(int argc, char **argv) {
files ++;
}
}
if (files == 0) {
printf("\nFirst test for the parser, with errors\n");
parseAndPrintBuffer(buffer);
}
xmlCleanupParser();
xmlMemoryDump();

109
tester.c
View File

@ -30,10 +30,19 @@
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_LIBREADLINE
#include <readline/readline.h>
#ifdef HAVE_LIBHISTORY
#include <readline/history.h>
#endif
#endif
#include "xmlmemory.h"
#include "parser.h"
#include "HTMLparser.h"
#include "HTMLtree.h"
#include "tree.h"
#include "xpath.h"
#include "debugXML.h"
static int debug = 0;
@ -47,20 +56,89 @@ static int postvalid = 0;
static int repeat = 0;
static int insert = 0;
static int compress = 0;
static int html = 0;
static int shell = 0;
static int push = 0;
extern int xmlDoValidityCheckingDefaultValue;
/**
* xmlShellReadline:
* @prompt: the prompt value
*
* Read a string
*
* Returns a pointer to it or NULL on EOF the caller is expected to
* free the returned string.
*/
char *
xmlShellReadline(char *prompt) {
#ifdef HAVE_LIBREADLINE
char *line_read;
/* Get a line from the user. */
line_read = readline (prompt);
/* If the line has any text in it, save it on the history. */
if (line_read && *line_read)
add_history (line_read);
return (line_read);
#else
char line_read[501];
if (prompt != NULL)
fprintf(stdout, "%s", prompt);
if (!fgets(line_read, 500, stdin))
return(NULL);
line_read[500] = 0;
return(strdup(line_read));
#endif
}
void parseAndPrintFile(char *filename) {
xmlDocPtr doc, tmp;
xmlDocPtr doc = NULL, tmp;
if (html) {
doc = htmlParseFile(filename, NULL);
} else {
/*
* build an XML tree from a string;
*/
if (push) {
FILE *f;
f = fopen(filename, "r");
if (f != NULL) {
int res, size = 3;
char chars[1024];
xmlParserCtxtPtr ctxt;
if (repeat)
size = 1024;
res = fread(chars, 1, 4, f);
if (res > 0) {
ctxt = xmlCreatePushParserCtxt(NULL, NULL,
chars, res, filename);
while ((res = fread(chars, 1, size, f)) > 0) {
xmlParseChunk(ctxt, chars, res, 0);
}
xmlParseChunk(ctxt, chars, 0, 1);
doc = ctxt->myDoc;
xmlFreeParserCtxt(ctxt);
}
}
} else if (recovery)
doc = xmlRecoverFile(filename);
else
doc = xmlParseFile(filename);
}
/*
* build an XML tree from a string;
* shell interraction
*/
if (recovery)
doc = xmlRecoverFile(filename);
else
doc = xmlParseFile(filename);
if (shell)
xmlShell(doc, filename, xmlShellReadline, stdout);
/*
* test intermediate copy if needed.
@ -71,7 +149,7 @@ void parseAndPrintFile(char *filename) {
xmlFreeDoc(tmp);
}
if (insert) {
if ((insert) && (!html)) {
const xmlChar* list[256];
int nb, i;
xmlNodePtr node;
@ -116,7 +194,7 @@ void parseAndPrintFile(char *filename) {
xmlValidateDocument(&cvp, doc);
}
if (debugent)
if ((debugent) && (!html))
xmlDebugDumpEntities(stdout, doc);
/*
@ -157,11 +235,23 @@ int main(int argc, char **argv) {
else if ((!strcmp(argv[i], "-repeat")) ||
(!strcmp(argv[i], "--repeat")))
repeat++;
else if ((!strcmp(argv[i], "-push")) ||
(!strcmp(argv[i], "--push")))
push++;
else if ((!strcmp(argv[i], "-compress")) ||
(!strcmp(argv[i], "--compress"))) {
compress++;
xmlSetCompressMode(9);
}
else if ((!strcmp(argv[i], "-html")) ||
(!strcmp(argv[i], "--html"))) {
html++;
}
else if ((!strcmp(argv[i], "-shell")) ||
(!strcmp(argv[i], "--shell"))) {
shell++;
noout = 1;
}
}
if (noent != 0) xmlSubstituteEntitiesDefault(1);
if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
@ -190,6 +280,9 @@ int main(int argc, char **argv) {
printf("\t--repeat : repeat 100 times, for timing or profiling\n");
printf("\t--insert : ad-hoc test for valid insertions\n");
printf("\t--compress : turn on gzip compression of output\n");
printf("\t--html : use the HTML parser\n");
printf("\t--shell : run a navigating shell\n");
printf("\t--push : use the push mode of the parser\n");
}
xmlCleanupParser();
xmlMemoryDump();

345
tree.c
View File

@ -2498,6 +2498,7 @@ xmlNodeGetContent(xmlNodePtr cur) {
return(xmlNodeListGetString(NULL, attr->val, 1));
break;
}
case XML_COMMENT_NODE:
case XML_PI_NODE:
if (cur->content != NULL)
#ifndef XML_USE_BUFFER_CONTENT
@ -2507,8 +2508,12 @@ xmlNodeGetContent(xmlNodePtr cur) {
#endif
return(NULL);
case XML_ENTITY_REF_NODE:
/*
* Locate the entity, and get it's content
* @@@
*/
return(NULL);
case XML_ENTITY_NODE:
case XML_COMMENT_NODE:
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
case XML_DOCUMENT_TYPE_NODE:
@ -2858,18 +2863,6 @@ xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
}
node = node->parent;
}
#if 0
/* Removed support for old namespaces */
if (doc != NULL) {
cur = doc->oldNs;
while (cur != NULL) {
if ((cur->prefix != NULL) && (nameSpace != NULL) &&
(!xmlStrcmp(cur->prefix, nameSpace)))
return(cur);
cur = cur->next;
}
}
#endif
return(NULL);
}
@ -2886,31 +2879,283 @@ xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
xmlNsPtr
xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
xmlNsPtr cur;
xmlNodePtr orig = node;
if ((node == NULL) || (href == NULL)) return(NULL);
while (node != NULL) {
cur = node->nsDef;
while (cur != NULL) {
if ((cur->href != NULL) && (href != NULL) &&
(!xmlStrcmp(cur->href, href)))
(!xmlStrcmp(cur->href, href))) {
/*
* Check that the prefix is not shadowed between orig and node
*/
xmlNodePtr check = orig;
xmlNsPtr tst;
while (check != node) {
tst = check->nsDef;
while (tst != NULL) {
if ((tst->prefix == NULL) && (cur->prefix == NULL))
goto shadowed;
if ((tst->prefix != NULL) && (cur->prefix != NULL) &&
(!xmlStrcmp(tst->prefix, cur->prefix)))
goto shadowed;
tst = tst->next;
}
}
return(cur);
}
shadowed:
cur = cur->next;
}
node = node->parent;
}
#if 0
/* Removed support for old namespaces */
if (doc != NULL) {
cur = doc->oldNs;
while (cur != NULL) {
if ((cur->href != NULL) && (href != NULL) &&
(!xmlStrcmp(cur->href, href)))
return(cur);
cur = cur->next;
return(NULL);
}
/**
* xmlNewReconciliedNs
* @doc: the document
* @tree: a node expected to hold the new namespace
* @ns: the original namespace
*
* This function tries to locate a namespace definition in a tree
* ancestors, or create a new namespace definition node similar to
* @ns trying to reuse the same prefix. However if the given prefix is
* null (default namespace) or reused within the subtree defined by
* @tree or on one of its ancestors then a new prefix is generated.
* Returns the (new) namespace definition or NULL in case of error
*/
xmlNsPtr
xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
xmlNsPtr def;
xmlChar prefix[50];
int counter = 1;
if (tree == NULL) {
#ifdef DEBUG_TREE
fprintf(stderr, "xmlNewReconciliedNs : tree == NULL\n");
#endif
return(NULL);
}
if (ns == NULL) {
#ifdef DEBUG_TREE
fprintf(stderr, "xmlNewReconciliedNs : ns == NULL\n");
#endif
return(NULL);
}
/*
* Search an existing namespace definition inherited.
*/
def = xmlSearchNsByHref(doc, tree, ns->href);
if (def != NULL)
return(def);
/*
* Find a close prefix which is not already in use.
* Let's strip namespace prefixes longer than 20 chars !
*/
sprintf((char *) prefix, "%.20s", ns->prefix);
def = xmlSearchNs(doc, tree, prefix);
while (def != NULL) {
if (counter > 1000) return(NULL);
sprintf((char *) prefix, "%.20s%d", ns->prefix, counter++);
def = xmlSearchNs(doc, tree, prefix);
}
/*
* Ok, now we are ready to create a new one.
*/
def = xmlNewNs(tree, ns->href, prefix);
return(def);
}
/**
* xmlReconciliateNs
* @doc: the document
* @tree: a node defining the subtree to reconciliate
*
* This function checks that all the namespaces declared within the given
* tree are properly declared. This is needed for example after Copy or Cut
* and then paste operations. The subtree may still hold pointers to
* namespace declarations outside the subtree or invalid/masked. As much
* as possible the function try tu reuse the existing namespaces found in
* the new environment. If not possible the new namespaces are redeclared
* on @tree at the top of the given subtree.
* Returns the number of namespace declarations created or -1 in case of error.
*/
int
xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
xmlNsPtr *oldNs = NULL;
xmlNsPtr *newNs = NULL;
int sizeCache = 0;
int nbCache = 0;
xmlNsPtr n;
xmlNodePtr node = tree;
xmlAttrPtr attr;
int ret = 0, i;
while (node != NULL) {
/*
* Reconciliate the node namespace
*/
if (node->ns != NULL) {
/*
* initialize the cache if needed
*/
if (sizeCache == 0) {
sizeCache = 10;
oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
sizeof(xmlNsPtr));
if (oldNs == NULL) {
fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
return(-1);
}
newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
sizeof(xmlNsPtr));
if (newNs == NULL) {
fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
xmlFree(oldNs);
return(-1);
}
}
for (i = 0;i < nbCache;i++) {
if (oldNs[i] == node->ns) {
node->ns = newNs[i];
break;
}
}
if (i == nbCache) {
/*
* Ok we need to recreate a new namespace definition
*/
n = xmlNewReconciliedNs(doc, tree, node->ns);
if (n != NULL) { /* :-( what if else ??? */
/*
* check if we need to grow the cache buffers.
*/
if (sizeCache <= nbCache) {
sizeCache *= 2;
oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
sizeof(xmlNsPtr));
if (oldNs == NULL) {
fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
xmlFree(newNs);
return(-1);
}
newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
sizeof(xmlNsPtr));
if (newNs == NULL) {
fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
xmlFree(oldNs);
return(-1);
}
}
newNs[nbCache] = n;
oldNs[nbCache++] = node->ns;
node->ns = n;
}
}
}
/*
* now check for namespace hold by attributes on the node.
*/
attr = node->properties;
while (attr != NULL) {
if (attr->ns != NULL) {
/*
* initialize the cache if needed
*/
if (sizeCache == 0) {
sizeCache = 10;
oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
sizeof(xmlNsPtr));
if (oldNs == NULL) {
fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
return(-1);
}
newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
sizeof(xmlNsPtr));
if (newNs == NULL) {
fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
xmlFree(oldNs);
return(-1);
}
}
for (i = 0;i < nbCache;i++) {
if (oldNs[i] == attr->ns) {
node->ns = newNs[i];
break;
}
}
if (i == nbCache) {
/*
* Ok we need to recreate a new namespace definition
*/
n = xmlNewReconciliedNs(doc, tree, attr->ns);
if (n != NULL) { /* :-( what if else ??? */
/*
* check if we need to grow the cache buffers.
*/
if (sizeCache <= nbCache) {
sizeCache *= 2;
oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
sizeof(xmlNsPtr));
if (oldNs == NULL) {
fprintf(stderr,
"xmlReconciliateNs : memory pbm\n");
xmlFree(newNs);
return(-1);
}
newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
sizeof(xmlNsPtr));
if (newNs == NULL) {
fprintf(stderr,
"xmlReconciliateNs : memory pbm\n");
xmlFree(oldNs);
return(-1);
}
}
newNs[nbCache] = n;
oldNs[nbCache++] = attr->ns;
attr->ns = n;
}
}
}
attr = attr->next;
}
/*
* Browse the full subtree, deep first
*/
if (node->childs != NULL) {
/* deep first */
node = node->childs;
} else if ((node != tree) && (node->next != NULL)) {
/* then siblings */
node = node->next;
} else if (node != tree) {
/* go up to parents->next if needed */
while (node != tree) {
if (node->parent != NULL)
node = node->parent;
if ((node != tree) && (node->next != NULL)) {
node = node->next;
break;
}
if (node->parent == NULL) {
node = NULL;
break;
}
}
/* exit condition */
if (node == tree)
node = NULL;
}
}
#endif
return(NULL);
return(ret);
}
/**
@ -3095,8 +3340,9 @@ void
xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
if (node == NULL) return;
if (node->type != XML_TEXT_NODE) {
fprintf(stderr, "xmlTextConcat: node is not text\n");
if ((node->type != XML_TEXT_NODE) &&
(node->type != XML_CDATA_SECTION_NODE)) {
fprintf(stderr, "xmlTextConcat: node is not text nor cdata\n");
return;
}
#ifndef XML_USE_BUFFER_CONTENT
@ -3376,7 +3622,11 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
if (len == 0) return;
/* CJN What's this for??? */
l = xmlStrlen(str);
if (len < 0)
l = xmlStrlen(str);
else
for (l = 0;l < len;l++)
if (str[l] == 0) break;
if (l < len){ len = l; printf("xmlBufferAdd bad length\n"); }
/* CJN 11.18.99 okay, now I'm using the length */
@ -3676,6 +3926,9 @@ xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
static void
xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
int format);
void
htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur);
/**
* xmlNodeListDump:
* @buf: the XML buffer output
@ -3850,6 +4103,40 @@ xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
xmlBufferWriteChar(buf, ">");
}
/**
* xmlElemDump:
* @buf: the XML buffer output
* @doc: the document
* @cur: the current node
*
* Dump an XML/HTML node, recursive behaviour,children are printed too.
*/
void
xmlElemDump(FILE *f, xmlDocPtr doc, xmlNodePtr cur) {
xmlBufferPtr buf;
if (cur == NULL) {
#ifdef DEBUG_TREE
fprintf(stderr, "xmlElemDump : cur == NULL\n");
#endif
return;
}
if (doc == NULL) {
#ifdef DEBUG_TREE
fprintf(stderr, "xmlElemDump : doc == NULL\n");
#endif
}
buf = xmlBufferCreate();
if (buf == NULL) return;
if ((doc != NULL) &&
(doc->type == XML_HTML_DOCUMENT_NODE)) {
htmlNodeDump(buf, doc, cur);
} else
xmlNodeDump(buf, doc, cur, 0, 1);
xmlBufferDump(f, buf);
xmlBufferFree(buf);
}
/**
* xmlDocContentDump:
* @buf: the XML buffer output
@ -3937,7 +4224,7 @@ xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
* Returns 0 (uncompressed) to 9 (max compression)
*/
int
xmlGetDocCompressMode (xmlDocPtr doc) {
xmlGetDocCompressMode (xmlDocPtr doc) {
if (doc == NULL) return(-1);
return(doc->compression);
}

3
tree.h
View File

@ -526,6 +526,9 @@ void xmlDocDumpMemory (xmlDocPtr cur,
int *size);
void xmlDocDump (FILE *f,
xmlDocPtr cur);
void xmlElemDump (FILE *f,
xmlDocPtr cur,
xmlNodePtr elem);
int xmlSaveFile (const char *filename,
xmlDocPtr cur);

68
valid.c
View File

@ -25,6 +25,8 @@
#include "parser.h"
#include "parserInternals.h"
/* TODO: use hash table for accesses to elem and attribute dedinitions */
#define VERROR \
if ((ctxt != NULL) && (ctxt->error != NULL)) ctxt->error
@ -494,6 +496,7 @@ xmlCopyElementTable(xmlElementTablePtr table) {
else
cur->name = NULL;
cur->content = xmlCopyElementContent(ent->content);
/* TODO : rebuild the attribute list on the copy */
cur->attributes = NULL;
}
return(ret);
@ -2723,6 +2726,7 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
xmlNodePtr elem) {
xmlElementPtr elemDecl;
xmlElementContentPtr cont;
xmlAttributePtr attr;
xmlNodePtr child;
int ret = 1;
const xmlChar *name;
@ -2869,7 +2873,69 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
break;
}
/* TODO - [ VC: Required Attribute ] */
/* [ VC: Required Attribute ] */
attr = elemDecl->attributes;
while (attr != NULL) {
if (attr->def == XML_ATTRIBUTE_REQUIRED) {
xmlAttrPtr attrib;
int qualified = -1;
attrib = elem->properties;
while (attrib != NULL) {
if (!xmlStrcmp(attrib->name, attr->name)) {
if (attr->prefix != NULL) {
xmlNsPtr nameSpace = attrib->ns;
if (nameSpace == NULL)
nameSpace = elem->ns;
/*
* qualified names handling is problematic, having a
* different prefix should be possible but DTDs don't
* allow to define the URI instead of the prefix :-(
*/
if (nameSpace == NULL) {
if (qualified < 0)
qualified = 0;
} else if (xmlStrcmp(nameSpace->prefix, attr->prefix)) {
if (qualified < 1)
qualified = 1;
} else
goto found;
} else {
/*
* We should allow applications to define namespaces
* for their application even if the DTD doesn't
* carry one, otherwise, basically we would always
* break.
*/
goto found;
}
}
attrib = attrib->next;
}
if (qualified == -1) {
if (attr->prefix == NULL) {
VERROR(ctxt->userData,
"Element %s doesn't carry attribute %s\n",
elem->name, attr->name);
} else {
VERROR(ctxt->userData,
"Element %s doesn't carry attribute %s:%s\n",
elem->name, attr->prefix,attr->name);
}
} else if (qualified == 0) {
VWARNING(ctxt->userData,
"Element %s required attribute %s:%s has no prefix\n",
elem->name, attr->prefix,attr->name);
} else if (qualified == 1) {
VWARNING(ctxt->userData,
"Element %s required attribute %s:%s has different prefix\n",
elem->name, attr->prefix,attr->name);
}
}
found:
attr = attr->next;
}
return(ret);
}

34
xmlIO.c
View File

@ -68,6 +68,11 @@ xmlAllocParserInputBuffer(xmlCharEncoding enc) {
}
memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
ret->buffer = xmlBufferCreate();
if (ret->buffer == NULL) {
xmlFree(ret);
return(NULL);
}
ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
ret->encoder = xmlGetCharEncodingHandler(enc);
ret->fd = -1;
ret->netIO = NULL;
@ -263,32 +268,30 @@ xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
*/
int
xmlParserInputBufferPush(xmlParserInputBufferPtr in, int len, const char *buf) {
char *buffer = NULL;
int nbchars = 0;
if (len < 0) return(0);
if (in->encoder != NULL) {
xmlChar *buf;
xmlChar *buffer;
buf = (xmlChar *) xmlMalloc((len + 1) * 2 * sizeof(xmlChar));
if (buf == NULL) {
buffer = (xmlChar *) xmlMalloc((len + 1) * 2 * sizeof(xmlChar));
if (buffer == NULL) {
fprintf(stderr, "xmlParserInputBufferGrow : out of memory !\n");
xmlFree(buffer);
return(-1);
}
nbchars = in->encoder->input(buf, (len + 1) * 2 * sizeof(xmlChar),
BAD_CAST buffer, len);
nbchars = in->encoder->input(buffer, (len + 1) * 2 * sizeof(xmlChar),
(xmlChar *) buf, len);
/*
* TODO : we really need to have something atomic or the
* encoder must report the number of bytes read
*/
buf[nbchars] = 0;
xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
xmlFree(buf);
} else {
nbchars = len;
buffer[nbchars] = 0;
xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
xmlFree(buffer);
} else {
nbchars = len;
xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
}
#ifdef DEBUG_INPUT
fprintf(stderr, "I/O: pushed %d chars, buffer %d/%d\n",
@ -401,7 +404,14 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
int
xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
/* xmlBufferEmpty(in->buffer); */
return(xmlParserInputBufferGrow(in, len));
if ((in->netIO != NULL) || (in->file != NULL) ||
#ifdef HAVE_ZLIB_H
(in->gzfile != NULL) ||
#endif
(in->fd >= 0))
return(xmlParserInputBufferGrow(in, len));
else
return(0);
}
/*

View File

@ -37,6 +37,9 @@ typedef xmlParserInputBuffer *xmlParserInputBufferPtr;
* Interfaces
*/
xmlParserInputBufferPtr
xmlAllocParserInputBuffer (xmlCharEncoding enc);
xmlParserInputBufferPtr
xmlParserInputBufferCreateFilename (const char *filename,
xmlCharEncoding enc);

View File

@ -368,10 +368,53 @@ xmlMemUsed(void) {
return(debugMemSize);
}
/**
* xmlMemShow:
* @fp: a FILE descriptor used as the output file
* @nr: number of entries to dump
*
* show a show display of the memory allocated, and dump
* the @nr last allocated areas which were not freed
*/
void
xmlMemShow(FILE *fp, int nr)
{
#ifdef MEM_LIST
MEMHDR *p;
#endif
if (fp != NULL)
fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
debugMemSize, debugMaxMemSize);
#ifdef MEM_LIST
if (nr > 0) {
fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
p = memlist;
while ((p) && nr > 0) {
fprintf(fp,"%6lu %6u ",p->mh_number,p->mh_size);
switch (p->mh_type) {
case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
default:fprintf(fp," ??? in ");break;
}
if (p->mh_file != NULL)
fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
if (p->mh_tag != MEMTAG)
fprintf(fp," INVALID");
fprintf(fp,"\n");
nr--;
p = p->mh_next;
}
}
#endif /* MEM_LIST */
}
/**
* xmlMemDisplay:
* @fp: a FILE descriptor used as the output file, if NULL, the result is
8 written to the file .memorylist
* written to the file .memorylist
*
* show in-extenso the memory blocks allocated
*/

View File

@ -1,5 +1,5 @@
/*
* memory.h: interface for the memory allocation debug.
* xmlmemory.h: interface for the memory allocation debug.
*
* Daniel.Veillard@w3.org
*/
@ -24,6 +24,7 @@
#define xmlInitMemory()
#define xmlMemoryDump()
#define xmlMemDisplay(x)
#define xmlMemShow(x, d)
#else /* ! NO_DEBUG_MEMORY */
#include <stdio.h>
@ -51,6 +52,7 @@ void xmlFree (void *ptr);
char * xmlMemStrdup (const char *str);
int xmlMemUsed (void);
void xmlMemDisplay (FILE *fp);
void xmlMemShow (FILE *fp, int nr);
void xmlMemoryDump (void);
int xmlInitMemory (void);

84
xpath.c
View File

@ -47,6 +47,10 @@
#include "xpath.h"
#include "parserInternals.h"
/* #define DEBUG */
/* #define DEBUG_STEP */
/* #define DEBUG_EXPR */
/*
* Setup stuff for floating point
* The lack of portability of this section of the libc is annoying !
@ -151,10 +155,6 @@ xmlXPathInit(void) {
initialized = 1;
}
/* #define DEBUG */
/* #define DEBUG_STEP */
/* #define DEBUG_EXPR */
FILE *xmlXPathDebug = NULL;
#define TODO \
@ -747,6 +747,22 @@ xmlXPathNewNodeSetList(xmlNodeSetPtr val) {
return(ret);
}
/**
* xmlXPathFreeNodeSetList:
* @obj: an existing NodeSetList object
*
* Free up the xmlXPathObjectPtr @obj but don't deallocate the objects in
* the list contrary to xmlXPathFreeObject().
*/
void
xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
if (obj == NULL) return;
#ifdef DEBUG
memset(obj, 0xB , (size_t) sizeof(xmlXPathObject));
#endif
xmlFree(obj);
}
/**
* xmlXPathFreeObject:
* @obj: the object to free
@ -791,6 +807,12 @@ xmlXPathNewContext(xmlDocPtr doc) {
}
memset(ret, 0 , (size_t) sizeof(xmlXPathContext));
ret->doc = doc;
/***********
ret->node = (xmlNodePtr) doc;
ret->nodelist = xmlXPathNodeSetCreate(ret->node);
***********/
ret->node = NULL;
ret->nodelist = NULL;
ret->nb_variables = 0;
ret->max_variables = 0;
@ -825,6 +847,10 @@ xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
if (ctxt->namespaces != NULL)
xmlFree(ctxt->namespaces);
/***********
if (ctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->nodelist);
***********/
#ifdef DEBUG
memset(ctxt, 0xB , (size_t) sizeof(xmlXPathContext));
#endif
@ -1467,12 +1493,13 @@ xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
xmlNodePtr
xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if (cur == NULL) {
if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
return(ctxt->context->doc->root);
if ((ctxt->context->node->type == XML_DOCUMENT_NODE) ||
(ctxt->context->node->type == XML_HTML_DOCUMENT_NODE))
return(((xmlDocPtr) ctxt->context->node)->root);
return(ctxt->context->node->childs);
}
if ((ctxt->context->node->type == XML_DOCUMENT_NODE) ||
(ctxt->context->node->type == XML_HTML_DOCUMENT_NODE))
if ((cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_HTML_DOCUMENT_NODE))
return(NULL);
return(cur->next);
}
@ -1918,23 +1945,23 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
ctxt->context->nodelist->nodeNr);
switch (test) {
case NODE_TEST_NONE:
fprintf(xmlXPathDebug, " seaching for none !!!\n");
fprintf(xmlXPathDebug, " searching for none !!!\n");
break;
case NODE_TEST_TYPE:
fprintf(xmlXPathDebug, " seaching for type %d\n", type);
fprintf(xmlXPathDebug, " searching for type %d\n", type);
break;
case NODE_TEST_PI:
fprintf(xmlXPathDebug, " seaching for PI !!!\n");
fprintf(xmlXPathDebug, " searching for PI !!!\n");
break;
case NODE_TEST_ALL:
fprintf(xmlXPathDebug, " seaching for *\n");
fprintf(xmlXPathDebug, " searching for *\n");
break;
case NODE_TEST_NS:
fprintf(xmlXPathDebug, " seaching for namespace %s\n",
fprintf(xmlXPathDebug, " searching for namespace %s\n",
prefix);
break;
case NODE_TEST_NAME:
fprintf(xmlXPathDebug, " seaching for name %s\n", name);
fprintf(xmlXPathDebug, " searching for name %s\n", name);
if (prefix != NULL)
fprintf(xmlXPathDebug, " with namespace %s\n",
prefix);
@ -1958,7 +1985,10 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
STRANGE
return(NULL);
case NODE_TEST_TYPE:
if (cur->type == type) {
if ((cur->type == type) ||
((type == XML_ELEMENT_NODE) &&
((cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_HTML_DOCUMENT_NODE)))) {
#ifdef DEBUG_STEP
n++;
#endif
@ -4400,6 +4430,7 @@ xmlXPathObjectPtr
xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctxt) {
xmlXPathParserContextPtr pctxt;
xmlXPathObjectPtr res = NULL, tmp;
int stack = 0;
xmlXPathInit();
@ -4408,16 +4439,26 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctxt) {
if (xmlXPathDebug == NULL)
xmlXPathDebug = stderr;
pctxt = xmlXPathNewParserContext(str, ctxt);
if (str[0] == '/')
xmlXPathRoot(pctxt);
xmlXPathEvalLocationPath(pctxt);
/* TODO: cleanup nodelist, res = valuePop(pctxt); */
do {
tmp = valuePop(pctxt);
if (tmp != NULL);
if (tmp != NULL) {
xmlXPathFreeObject(tmp);
stack++;
}
} while (tmp != NULL);
if (res == NULL)
if (stack != 0) {
fprintf(xmlXPathDebug, "xmlXPathEval: %d object left on the stack\n",
stack);
}
if (pctxt->error == XPATH_EXPRESSION_OK)
res = xmlXPathNewNodeSetList(pctxt->context->nodelist);
else
res = NULL;
xmlXPathFreeParserContext(pctxt);
return(res);
}
@ -4436,6 +4477,7 @@ xmlXPathObjectPtr
xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
xmlXPathParserContextPtr pctxt;
xmlXPathObjectPtr res, tmp;
int stack = 0;
xmlXPathInit();
@ -4449,9 +4491,15 @@ xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
res = valuePop(pctxt);
do {
tmp = valuePop(pctxt);
if (tmp != NULL);
if (tmp != NULL) {
xmlXPathFreeObject(tmp);
stack++;
}
} while (tmp != NULL);
if (stack != 0) {
fprintf(xmlXPathDebug, "xmlXPathEval: %d object left on the stack\n",
stack);
}
xmlXPathFreeParserContext(pctxt);
return(res);
}

View File

@ -205,6 +205,9 @@ xmlXPathObjectPtr xmlXPathEval (const xmlChar *str,
void xmlXPathFreeObject (xmlXPathObjectPtr obj);
xmlXPathObjectPtr xmlXPathEvalExpression (const xmlChar *str,
xmlXPathContextPtr ctxt);
xmlNodeSetPtr xmlXPathNodeSetCreate (xmlNodePtr val);
void xmlXPathFreeNodeSetList (xmlXPathObjectPtr obj);
void xmlXPathFreeNodeSet (xmlNodeSetPtr obj);
#ifdef __cplusplus
}