version 1.15, 1998/05/25 23:58:37
|
version 1.16, 1998/06/19 04:48:27
|
Line 127
|
Line 127
|
/* |
/* |
* Forward definition for recusive behaviour. |
* Forward definition for recusive behaviour. |
*/ |
*/ |
xmlNodePtr xmlParseElement(CHAR **p, xmlDocPtr doc); |
xmlNodePtr xmlParseElement(xmlParserCtxtPtr ctxt); |
|
|
/* |
/* |
* xmlHandleData : this routine represent's the specific application |
* xmlHandleData : this routine represent's the specific application |
Line 227 CHAR *xmlStrchr(const CHAR *str, CHAR va
|
Line 227 CHAR *xmlStrchr(const CHAR *str, CHAR va
|
* xmlParseName : parse an XML name. |
* xmlParseName : parse an XML name. |
*/ |
*/ |
|
|
CHAR *xmlParseName(CHAR **p) { |
CHAR *xmlParseName(xmlParserCtxtPtr ctxt) { |
CHAR *cur = *p, *q, *ret = NULL; |
CHAR *q, *ret = NULL; |
|
|
/* |
/* |
* Name ::= (Letter | '_') (NameChar)* |
* Name ::= (Letter | '_') (NameChar)* |
*/ |
*/ |
if (!IS_LETTER(*cur) && (*cur != '_')) return(NULL); |
if (!IS_LETTER(ctxt->cur[0]) && (ctxt->cur[0] != '_')) return(NULL); |
q = cur++; |
q = ctxt->cur++; |
while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) || |
while ((IS_LETTER(ctxt->cur[0])) || (IS_DIGIT(ctxt->cur[0])) || |
(*cur == '.') || (*cur == '-') || (*cur == '_') || |
(ctxt->cur[0] == '.') || (ctxt->cur[0] == '-') || (ctxt->cur[0] == '_') || |
(*cur == ':') || |
(ctxt->cur[0] == ':') || |
(IS_COMBINING(*cur)) || (IS_IGNORABLE(*cur)) || |
(IS_COMBINING(ctxt->cur[0])) || (IS_IGNORABLE(ctxt->cur[0])) || |
(IS_EXTENDER(*cur))) |
(IS_EXTENDER(ctxt->cur[0]))) |
cur++; |
ctxt->cur++; |
|
|
ret = xmlStrndup(q, cur - q); |
ret = xmlStrndup(q, ctxt->cur - q); |
|
|
*p = cur; |
|
return(ret); |
return(ret); |
} |
} |
|
|
/* |
/* |
* Parse and return a string between quotes or doublequotes |
* Parse and return a string between quotes or doublequotes |
*/ |
*/ |
CHAR *xmlParseQuotedString(CHAR **p) { |
CHAR *xmlParseQuotedString(xmlParserCtxtPtr ctxt) { |
CHAR *ret = NULL; |
CHAR *ret = NULL; |
CHAR *cur = *p, *q; |
CHAR *q; |
|
|
if (*cur == '"') { |
if (ctxt->cur[0] == '"') { |
cur++; |
ctxt->cur++; |
q = cur; |
q = ctxt->cur; |
while (IS_CHAR(*cur) && (*cur != '"')) cur++; |
while (IS_CHAR(ctxt->cur[0]) && (ctxt->cur[0] != '"')) ctxt->cur++; |
if (*cur != '"') |
if (ctxt->cur[0] != '"') |
fprintf(stderr, "String not closed \"%.50s\n", q); |
fprintf(stderr, "String not closed \"%.50s\n", q); |
else { |
else { |
ret = xmlStrndup(q, cur - q); |
ret = xmlStrndup(q, ctxt->cur - q); |
cur++; |
ctxt->cur++; |
} |
} |
} else if (*cur == '\''){ |
} else if (ctxt->cur[0] == '\''){ |
cur++; |
ctxt->cur++; |
q = cur; |
q = ctxt->cur; |
while (IS_CHAR(*cur) && (*cur != '\'')) cur++; |
while (IS_CHAR(ctxt->cur[0]) && (ctxt->cur[0] != '\'')) ctxt->cur++; |
if (*cur != '\'') |
if (ctxt->cur[0] != '\'') |
fprintf(stderr, "String not closed '%.50s\n", q); |
fprintf(stderr, "String not closed '%.50s\n", q); |
else { |
else { |
ret = xmlStrndup(q, cur - q); |
ret = xmlStrndup(q, ctxt->cur - q); |
cur++; |
ctxt->cur++; |
} |
} |
} |
} |
*p = cur; |
|
return(ret); |
return(ret); |
} |
} |
|
|
/* |
/* |
* Skip an XML (SGML) comment <!-- .... --> |
* Skip an XML (SGML) comment <!-- .... --> |
|
* |
|
* TODO !!!! Save the comment in the tree !!! |
*/ |
*/ |
void xmlParserSkipComment(CHAR **p) { |
void xmlParserSkipComment(xmlParserCtxtPtr ctxt) { |
CHAR *cur = *p, *q, *r, *start; |
CHAR *q, *r, *start; |
|
|
/* |
/* |
* An extra check may avoid errors and isn't that costly ! |
* An extra check may avoid errors and isn't that costly ! |
*/ |
*/ |
if ((cur[0] != '<') || (cur[1] != '!') || |
if ((ctxt->cur[0] != '<') || (ctxt->cur[1] != '!') || |
(cur[2] != '-') || (cur[3] != '-')) return; |
(ctxt->cur[2] != '-') || (ctxt->cur[3] != '-')) return; |
|
|
cur += 4; |
ctxt->cur += 4; |
start = q = cur; |
start = q = ctxt->cur; |
cur++; |
ctxt->cur++; |
r = cur; |
r = ctxt->cur; |
cur++; |
ctxt->cur++; |
while (IS_CHAR(*cur) && |
while (IS_CHAR(ctxt->cur[0]) && |
((*cur == ':') || (*cur != '>') || (*r != '-') || (*q != '-'))) { |
((ctxt->cur[0] == ':') || (ctxt->cur[0] != '>') || |
cur++;r++;q++; |
(*r != '-') || (*q != '-'))) { |
|
ctxt->cur++;r++;q++; |
} |
} |
if (!IS_CHAR(*cur)) { |
if (!IS_CHAR(ctxt->cur[0])) { |
fprintf(stderr, "Comment not terminated <!--%.50s\n", start); |
fprintf(stderr, "Comment not terminated <!--%.50s\n", start); |
*p = start; |
ctxt->cur = start; /* !!! We shouldn't really try to recover !!! */ |
} else { |
} else { |
cur++; |
ctxt->cur++; |
*p = cur; |
|
} |
} |
} |
} |
|
|
Line 314 void xmlParserSkipComment(CHAR **p) {
|
Line 314 void xmlParserSkipComment(CHAR **p) {
|
* xmlParseNamespace: parse specific '<?namespace ...' constructs. |
* xmlParseNamespace: parse specific '<?namespace ...' constructs. |
*/ |
*/ |
|
|
void xmlParseNamespace(CHAR **p, xmlDocPtr doc) { |
void xmlParseNamespace(xmlParserCtxtPtr ctxt) { |
CHAR *cur = *p; |
|
CHAR *href = NULL; |
CHAR *href = NULL; |
CHAR *AS = NULL; |
CHAR *AS = NULL; |
int garbage = 0; |
int garbage = 0; |
Line 323 void xmlParseNamespace(CHAR **p, xmlDocP
|
Line 322 void xmlParseNamespace(CHAR **p, xmlDocP
|
/* |
/* |
* We know that 'namespace' is here. |
* We know that 'namespace' is here. |
*/ |
*/ |
cur += 9; |
ctxt->cur += 9; |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
|
|
while (IS_CHAR(*cur) && (*cur != '>')) { |
while (IS_CHAR(ctxt->cur[0]) && (ctxt->cur[0] != '>')) { |
/* |
/* |
* We can have 'href' or 'AS' attributes. |
* We can have 'href' or 'AS' attributes. |
*/ |
*/ |
if ((cur[0] == 'h') && (cur[1] == 'r') && (cur[2] == 'e') && |
if ((ctxt->cur[0] == 'h') && (ctxt->cur[1] == 'r') && |
(cur[3] == 'f')) { |
(ctxt->cur[2] == 'e') && (ctxt->cur[3] == 'f')) { |
garbage = 0; |
garbage = 0; |
cur += 4; |
ctxt->cur += 4; |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
|
|
if (*cur != '=') continue; |
if (ctxt->cur[0] != '=') continue; |
cur++; |
ctxt->cur++; |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
|
|
href = xmlParseQuotedString(&cur); |
href = xmlParseQuotedString(ctxt); |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
} else if ((cur[0] == 'A') && (cur[1] == 'S')) { |
} else if ((ctxt->cur[0] == 'A') && (ctxt->cur[1] == 'S')) { |
garbage = 0; |
garbage = 0; |
cur += 2; |
ctxt->cur += 2; |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
|
|
if (*cur != '=') continue; |
if (ctxt->cur[0] != '=') continue; |
cur++; |
ctxt->cur++; |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
|
|
AS = xmlParseQuotedString(&cur); |
AS = xmlParseQuotedString(ctxt); |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
} else if ((cur[0] == '?') && (cur[1] == '>')) { |
} else if ((ctxt->cur[0] == '?') && (ctxt->cur[1] == '>')) { |
garbage = 0; |
garbage = 0; |
cur ++; |
ctxt->cur ++; |
} else { |
} else { |
/* |
/* |
* Found garbage when parsing the namespace |
* Found garbage when parsing the namespace |
*/ |
*/ |
if (!garbage) fprintf(stderr, |
if (!garbage) fprintf(stderr, |
"\nxmlParseNamespace found garbage: "); |
"\nxmlParseNamespace found garbage: "); |
fprintf(stderr, "%c", *cur); |
fprintf(stderr, "%c", ctxt->cur[0]); |
cur++; |
ctxt->cur++; |
} |
} |
} |
} |
|
|
MOVETO_ENDTAG(cur); |
MOVETO_ENDTAG(ctxt->cur); |
cur++; |
ctxt->cur++; |
|
|
/* |
/* |
* Register the DTD. |
* Register the DTD. |
*/ |
*/ |
if (href != NULL) |
if (href != NULL) |
xmlNewDtd(doc, href, AS); |
xmlNewDtd(ctxt->doc, href, AS); |
|
|
if (AS != NULL) free(AS); |
if (AS != NULL) free(AS); |
if (href != NULL) free(href); |
if (href != NULL) free(href); |
|
|
*p = cur; |
|
} |
} |
|
|
/* |
/* |
* xmlParsePI: parse an XML Processing Instruction. |
* xmlParsePI: parse an XML Processing Instruction. |
*/ |
*/ |
|
|
void xmlParsePI(CHAR **p, xmlDocPtr doc) { |
void xmlParsePI(xmlParserCtxtPtr ctxt) { |
CHAR *cur = *p; |
if ((ctxt->cur[0] == '<') && (ctxt->cur[1] == '?')) { |
|
|
if ((cur[0] == '<') && (cur[1] == '?')) { |
|
/* |
/* |
* this is a Processing Instruction. |
* this is a Processing Instruction. |
*/ |
*/ |
cur += 2; |
ctxt->cur += 2; |
|
|
/* |
/* |
* Special for WebDav, support for the Processing Instruction |
* Special for WebDav, support for the Processing Instruction |
* '<?namespace ...' contruct in the header of the XML document. |
* '<?namespace ...' contruct in the header of the XML document. |
*/ |
*/ |
if ((cur[0] == 'n') && (cur[1] == 'a') && |
if ((ctxt->cur[0] == 'n') && (ctxt->cur[1] == 'a') && |
(cur[2] == 'm') && (cur[3] == 'e') && |
(ctxt->cur[2] == 'm') && (ctxt->cur[3] == 'e') && |
(cur[4] == 's') && (cur[5] == 'p') && |
(ctxt->cur[4] == 's') && (ctxt->cur[5] == 'p') && |
(cur[6] == 'a') && (cur[7] == 'c') && |
(ctxt->cur[6] == 'a') && (ctxt->cur[7] == 'c') && |
(cur[8] == 'e')) { |
(ctxt->cur[8] == 'e')) { |
xmlParseNamespace(&cur, doc); |
xmlParseNamespace(ctxt); |
} else { |
} else { |
/* Unknown PI, ignore it ! */ |
/* Unknown PI, ignore it ! */ |
fprintf(stderr, "xmlParsePI : skipping unknown PI %30s\n", cur); |
fprintf(stderr, "xmlParsePI : skipping unknown PI %30s\n", |
MOVETO_ENDTAG(cur); |
ctxt->cur); |
cur++; |
MOVETO_ENDTAG(ctxt->cur); |
|
ctxt->cur++; |
} |
} |
} |
} |
*p = cur; |
|
} |
} |
|
|
/* |
/* |
Line 421 void xmlParsePI(CHAR **p, xmlDocPtr doc)
|
Line 416 void xmlParsePI(CHAR **p, xmlDocPtr doc)
|
* Attribute ::= Name Eq AttValue |
* Attribute ::= Name Eq AttValue |
*/ |
*/ |
|
|
void xmlParseAttribute(CHAR **p, xmlNodePtr node) { |
void xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlNodePtr node) { |
CHAR *cur = *p, *q, *name, *value = NULL; |
CHAR *q, *name, *value = NULL; |
|
|
if (!IS_LETTER(*cur) && (*cur != '_')) { |
if (!IS_LETTER(ctxt->cur[0]) && (ctxt->cur[0] != '_')) { |
return; |
return; |
} |
} |
q = cur++; |
q = ctxt->cur++; |
while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) || |
while ((IS_LETTER(ctxt->cur[0])) || (IS_DIGIT(ctxt->cur[0])) || |
(*cur == '.') || (*cur == '-') || (*cur == '_') || |
(ctxt->cur[0] == '.') || (ctxt->cur[0] == '-') || |
(*cur == ':') || |
(ctxt->cur[0] == '_') || (ctxt->cur[0] == ':') || |
(IS_COMBINING(*cur)) || (IS_IGNORABLE(*cur)) || |
(IS_COMBINING(ctxt->cur[0])) || (IS_IGNORABLE(ctxt->cur[0])) || |
(IS_EXTENDER(*cur))) |
(IS_EXTENDER(ctxt->cur[0]))) |
cur++; |
ctxt->cur++; |
name = xmlStrndup(q, cur - q); |
name = xmlStrndup(q, ctxt->cur - q); |
|
|
/* |
/* |
* We should have the equal, we are laxist here and allow attributes |
* We should have the equal, we are laxist here and allow attributes |
* without values and extra spaces. |
* without values and extra spaces. |
*/ |
*/ |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
if (*cur == '=') { |
if (ctxt->cur[0] == '=') { |
cur++; |
ctxt->cur++; |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
if ((*cur != '\'') && (*cur != '"')) { |
if ((ctxt->cur[0] != '\'') && (ctxt->cur[0] != '"')) { |
fprintf(stderr, "Quotes were expected for attribute value %.20s\n", |
fprintf(stderr, "Quotes were expected for attribute value %.20s\n", |
q); |
q); |
} else |
} else |
value = xmlParseQuotedString(&cur); |
value = xmlParseQuotedString(ctxt); |
} |
} |
|
|
/* |
/* |
Line 456 void xmlParseAttribute(CHAR **p, xmlNode
|
Line 451 void xmlParseAttribute(CHAR **p, xmlNode
|
*/ |
*/ |
if (name != NULL) |
if (name != NULL) |
xmlNewProp(node, name, value); |
xmlNewProp(node, name, value); |
|
|
*p = cur; |
|
} |
} |
|
|
/* |
/* |
* xmlParseStartTag: parse a start of tag. |
* xmlParseStartTag: parse a start of tag. |
*/ |
*/ |
|
|
xmlNodePtr xmlParseStartTag(CHAR **p, xmlDocPtr doc) { |
xmlNodePtr xmlParseStartTag(xmlParserCtxtPtr ctxt) { |
CHAR *cur = *p, *q, *ns, *name; |
CHAR *q, *ns, *name; |
xmlDtdPtr dtd = NULL; |
xmlDtdPtr dtd = NULL; |
xmlNodePtr ret = NULL; |
xmlNodePtr ret = NULL; |
|
|
Line 483 xmlNodePtr xmlParseStartTag(CHAR **p, xm
|
Line 476 xmlNodePtr xmlParseStartTag(CHAR **p, xm
|
* |
* |
* STag ::= '<' QName (S Attribute)* S? '>' |
* STag ::= '<' QName (S Attribute)* S? '>' |
*/ |
*/ |
if (*cur != '<') return(NULL); |
if (ctxt->cur[0] != '<') return(NULL); |
cur++; |
ctxt->cur++; |
|
|
if (!IS_LETTER(*cur) && (*cur != '_')) return(NULL); |
if (!IS_LETTER(ctxt->cur[0]) && (ctxt->cur[0] != '_')) return(NULL); |
q = cur++; |
q = ctxt->cur++; |
while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) || |
while ((IS_LETTER(ctxt->cur[0])) || (IS_DIGIT(ctxt->cur[0])) || |
(*cur == '.') || (*cur == '-') || (*cur == '_') || |
(ctxt->cur[0] == '.') || (ctxt->cur[0] == '-') || |
(IS_COMBINING(*cur)) || (IS_IGNORABLE(*cur)) || |
(ctxt->cur[0] == '_') || |
(IS_EXTENDER(*cur))) |
(IS_COMBINING(ctxt->cur[0])) || (IS_IGNORABLE(ctxt->cur[0])) || |
cur++; |
(IS_EXTENDER(ctxt->cur[0]))) |
|
ctxt->cur++; |
|
|
if (*cur == ':') { |
if (ctxt->cur[0] == ':') { |
ns = xmlStrndup(q, cur - q); |
ns = xmlStrndup(q, ctxt->cur - q); |
|
|
cur++; /* skip the column */ |
ctxt->cur++; /* skip the column */ |
if (!IS_LETTER(*cur) && (*cur != '_')) { |
if (!IS_LETTER(ctxt->cur[0]) && (ctxt->cur[0] != '_')) { |
fprintf(stderr, |
fprintf(stderr, |
"Start tag : no element name after namespace identifier %.20s\n", |
"Start tag : no element name after namespace identifier %.20s\n", |
q); |
q); |
free(ns); |
free(ns); |
*p = cur; |
|
return(NULL); |
return(NULL); |
} |
} |
q = cur++; |
q = ctxt->cur++; |
while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) || |
while ((IS_LETTER(ctxt->cur[0])) || (IS_DIGIT(ctxt->cur[0])) || |
(*cur == '.') || (*cur == '-') || (*cur == '_') || |
(ctxt->cur[0] == '.') || (ctxt->cur[0] == '-') || |
(*cur == ':') || |
(ctxt->cur[0] == '_') || (ctxt->cur[0] == ':') || |
(IS_COMBINING(*cur)) || (IS_IGNORABLE(*cur)) || |
(IS_COMBINING(ctxt->cur[0])) || (IS_IGNORABLE(ctxt->cur[0])) || |
(IS_EXTENDER(*cur))) |
(IS_EXTENDER(ctxt->cur[0]))) |
cur++; |
ctxt->cur++; |
name = xmlStrndup(q, cur - q); |
name = xmlStrndup(q, ctxt->cur - q); |
|
|
/* |
/* |
* Search the DTD associated to ns. |
* Search the DTD associated to ns. |
*/ |
*/ |
dtd = xmlSearchDtd(doc, ns); |
dtd = xmlSearchDtd(ctxt->doc, ns); |
if (dtd == NULL) |
if (dtd == NULL) |
fprintf(stderr, "Start tag : Couldn't find namespace %s\n", ns); |
fprintf(stderr, "Start tag : Couldn't find namespace %s\n", ns); |
free(ns); |
free(ns); |
} else |
} else |
name = xmlStrndup(q, cur - q); |
name = xmlStrndup(q, ctxt->cur - q); |
|
|
ret = xmlNewNode(dtd, name, NULL); |
ret = xmlNewNode(dtd, name, NULL); |
|
|
Line 532 xmlNodePtr xmlParseStartTag(CHAR **p, xm
|
Line 525 xmlNodePtr xmlParseStartTag(CHAR **p, xm
|
* |
* |
* (S Attribute)* S? |
* (S Attribute)* S? |
*/ |
*/ |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
while ((IS_CHAR(*cur)) && |
while ((IS_CHAR(ctxt->cur[0])) && |
(*cur != '>') && |
(ctxt->cur[0] != '>') && |
((cur[0] != '/') || (cur[1] != '>'))) { |
((ctxt->cur[0] != '/') || (ctxt->cur[1] != '>'))) { |
if (IS_LETTER(*cur) || (*cur == '_')) |
if (IS_LETTER(ctxt->cur[0]) || (ctxt->cur[0] == '_')) |
xmlParseAttribute(&cur, ret); |
xmlParseAttribute(ctxt, ret); |
else { |
else { |
/* We should warn TODO !!! */ |
/* We should warn TODO !!! */ |
cur++; |
ctxt->cur++; |
} |
} |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
} |
} |
|
|
*p = cur; |
|
return(ret); |
return(ret); |
} |
} |
|
|
Line 554 xmlNodePtr xmlParseStartTag(CHAR **p, xm
|
Line 546 xmlNodePtr xmlParseStartTag(CHAR **p, xm
|
* already been read. |
* already been read. |
*/ |
*/ |
|
|
void xmlParseEndTag(CHAR **p, xmlDocPtr doc, xmlDtdPtr *dtdPtr, CHAR **tagPtr) { |
void xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlDtdPtr *dtdPtr, CHAR **tagPtr) { |
CHAR *cur = *p, *q, *ns, *name; |
CHAR *q, *ns, *name; |
xmlDtdPtr dtd = NULL; |
xmlDtdPtr dtd = NULL; |
|
|
*dtdPtr = NULL; |
*dtdPtr = NULL; |
Line 575 void xmlParseEndTag(CHAR **p, xmlDocPtr
|
Line 567 void xmlParseEndTag(CHAR **p, xmlDocPtr
|
* |
* |
* ETag ::= '</' Name S? '>' |
* ETag ::= '</' Name S? '>' |
*/ |
*/ |
if (!IS_LETTER(*cur) && (*cur != '_')) return; |
if (!IS_LETTER(ctxt->cur[0]) && (ctxt->cur[0] != '_')) return; |
q = cur++; |
q = ctxt->cur++; |
while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) || |
while ((IS_LETTER(ctxt->cur[0])) || (IS_DIGIT(ctxt->cur[0])) || |
(*cur == '.') || (*cur == '-') || (*cur == '_') || |
(ctxt->cur[0] == '.') || (ctxt->cur[0] == '-') || |
(IS_COMBINING(*cur)) || (IS_IGNORABLE(*cur)) || |
(ctxt->cur[0] == '_') || |
(IS_EXTENDER(*cur))) |
(IS_COMBINING(ctxt->cur[0])) || (IS_IGNORABLE(ctxt->cur[0])) || |
cur++; |
(IS_EXTENDER(ctxt->cur[0]))) |
|
ctxt->cur++; |
|
|
if (*cur == ':') { |
if (ctxt->cur[0] == ':') { |
ns = xmlStrndup(q, cur - q); |
ns = xmlStrndup(q, ctxt->cur - q); |
|
|
cur++; /* skip the column */ |
ctxt->cur++; /* skip the column */ |
if (!IS_LETTER(*cur) && (*cur != '_')) { |
if (!IS_LETTER(ctxt->cur[0]) && (ctxt->cur[0] != '_')) { |
fprintf(stderr, |
fprintf(stderr, |
"End tag : no element name after namespace identifier %.20s\n", |
"End tag : no element name after namespace identifier %.20s\n", |
q); |
q); |
free(ns); |
free(ns); |
*p = cur; |
|
return; |
return; |
} |
} |
q = cur++; |
q = ctxt->cur++; |
while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) || |
while ((IS_LETTER(ctxt->cur[0])) || (IS_DIGIT(ctxt->cur[0])) || |
(*cur == '.') || (*cur == '-') || (*cur == '_') || |
(ctxt->cur[0] == '.') || (ctxt->cur[0] == '-') || |
(*cur == ':') || |
(ctxt->cur[0] == '_') || (ctxt->cur[0] == ':') || |
(IS_COMBINING(*cur)) || (IS_IGNORABLE(*cur)) || |
(IS_COMBINING(ctxt->cur[0])) || (IS_IGNORABLE(ctxt->cur[0])) || |
(IS_EXTENDER(*cur))) |
(IS_EXTENDER(ctxt->cur[0]))) |
cur++; |
ctxt->cur++; |
name = xmlStrndup(q, cur - q); |
name = xmlStrndup(q, ctxt->cur - q); |
|
|
/* |
/* |
* Search the DTD associated to ns. |
* Search the DTD associated to ns. |
*/ |
*/ |
dtd = xmlSearchDtd(doc, ns); |
dtd = xmlSearchDtd(ctxt->doc, ns); |
if (dtd == NULL) |
if (dtd == NULL) |
fprintf(stderr, "End tag : Couldn't find namespace %s\n", ns); |
fprintf(stderr, "End tag : Couldn't find namespace %s\n", ns); |
free(ns); |
free(ns); |
} else |
} else |
name = xmlStrndup(q, cur - q); |
name = xmlStrndup(q, ctxt->cur - q); |
|
|
*dtdPtr = dtd; |
*dtdPtr = dtd; |
*tagPtr = name; |
*tagPtr = name; |
Line 620 void xmlParseEndTag(CHAR **p, xmlDocPtr
|
Line 612 void xmlParseEndTag(CHAR **p, xmlDocPtr
|
/* |
/* |
* We should definitely be at the ending "S? '>'" part |
* We should definitely be at the ending "S? '>'" part |
*/ |
*/ |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
if ((!IS_CHAR(*cur)) || (*cur != '>')) { |
if ((!IS_CHAR(ctxt->cur[0])) || (ctxt->cur[0] != '>')) { |
fprintf(stderr, "End tag : expected '>', got %.20s\n", cur); |
fprintf(stderr, "End tag : expected '>', got %.20s\n", ctxt->cur); |
/* |
/* |
* Note : skipping to the next '>' is probably otherkill, |
* Note : skipping to the next '>' is probably otherkill, |
* especially in case the '>' is hust missing. |
* especially in case the '>' is hust missing. |
* |
* |
* Otherwise add: |
* Otherwise add: |
* MOVETO_ENDTAG(cur); |
* MOVETO_ENDTAG(ctxt->cur); |
*/ |
*/ |
} else |
} else |
cur++; |
ctxt->cur++; |
|
|
*p = cur; |
|
return; |
return; |
} |
} |
|
|
/* |
/* |
* xmlParseCDSect: escaped pure raw content. |
* xmlParseCDSect: escaped pure raw content. |
*/ |
*/ |
CHAR *xmlParseCDSect(CHAR **p) { |
CHAR *xmlParseCDSect(xmlParserCtxtPtr ctxt) { |
CHAR *cur = *p, *r, *s, *base, *ret; |
CHAR *r, *s, *base, *ret; |
|
|
base = cur; |
base = ctxt->cur; |
if (!IS_CHAR(*cur)) { |
if (!IS_CHAR(ctxt->cur[0])) { |
fprintf(stderr, "CData section not finished : %.20s\n", base); |
fprintf(stderr, "CData section not finished : %.20s\n", base); |
return(NULL); |
return(NULL); |
} |
} |
r = cur++; |
r = ctxt->cur++; |
if (!IS_CHAR(*cur)) { |
if (!IS_CHAR(ctxt->cur[0])) { |
fprintf(stderr, "CData section not finished : %.20s\n", base); |
fprintf(stderr, "CData section not finished : %.20s\n", base); |
return(NULL); |
return(NULL); |
} |
} |
s = cur++; |
s = ctxt->cur++; |
while (IS_CHAR(*cur) && |
while (IS_CHAR(ctxt->cur[0]) && |
((*r != ']') || (*s != ']') || (*cur != '>'))) { |
((*r != ']') || (*s != ']') || (ctxt->cur[0] != '>'))) { |
r++;s++;cur++; |
r++;s++;ctxt->cur++; |
} |
} |
if (!IS_CHAR(*cur)) { |
if (!IS_CHAR(ctxt->cur[0])) { |
fprintf(stderr, "CData section not finished : %.20s\n", base); |
fprintf(stderr, "CData section not finished : %.20s\n", base); |
return(NULL); |
return(NULL); |
} |
} |
ret = xmlStrndup(base, cur-base); |
ret = xmlStrndup(base, ctxt->cur-base); |
*p = cur; |
|
return(ret); |
return(ret); |
} |
} |
|
|
Line 678 CHAR *xmlParseCDSect(CHAR **p) {
|
Line 669 CHAR *xmlParseCDSect(CHAR **p) {
|
* PI : starts by '<?' |
* PI : starts by '<?' |
*/ |
*/ |
|
|
xmlNodePtr xmlParseContent(CHAR **p, xmlDocPtr doc, xmlNodePtr node) { |
xmlNodePtr xmlParseContent(xmlParserCtxtPtr ctxt, xmlNodePtr node) { |
CHAR *cur = *p, *q, *data = NULL; |
CHAR *q, *data = NULL; |
xmlNodePtr ret = NULL; |
xmlNodePtr ret = NULL; |
|
|
/* |
/* |
* First case : a Processing Instruction. |
* First case : a Processing Instruction. |
*/ |
*/ |
if ((cur[0] == '<') && (cur[1] == '?')) { |
if ((ctxt->cur[0] == '<') && (ctxt->cur[1] == '?')) { |
xmlParsePI(&cur, doc); |
xmlParsePI(ctxt); |
} |
} |
/* |
/* |
* Second case : a CDSection |
* Second case : a CDSection |
*/ |
*/ |
if ((cur[0] == '<') && (cur[1] == '!') && (cur[2] == '[') && |
if ((ctxt->cur[0] == '<') && (ctxt->cur[1] == '!') && |
(cur[3] == 'C') && (cur[4] == 'D') && (cur[5] == 'A') && |
(ctxt->cur[2] == '[') && (ctxt->cur[3] == 'C') && |
(cur[6] == 'T') && (cur[7] == 'A') && (cur[8] == '[')) { |
(ctxt->cur[4] == 'D') && (ctxt->cur[5] == 'A') && |
cur += 9; |
(ctxt->cur[6] == 'T') && (ctxt->cur[7] == 'A') && |
data = xmlParseCDSect(&cur); |
(ctxt->cur[8] == '[')) { |
|
ctxt->cur += 9; |
|
data = xmlParseCDSect(ctxt); |
} |
} |
/* |
/* |
* Third case : a sub-element. |
* Third case : a sub-element. |
*/ |
*/ |
else if (cur[0] == '<') { |
else if (ctxt->cur[0] == '<') { |
ret = xmlParseElement(&cur, doc); |
ret = xmlParseElement(ctxt); |
} |
} |
/* |
/* |
* Last case, text. Note that References are handled directly. |
* Last case, text. Note that References are handled directly. |
*/ |
*/ |
else { |
else { |
q = cur; |
q = ctxt->cur; |
while (IS_CHAR(*cur) && (*cur != '<')) cur++; |
while (IS_CHAR(ctxt->cur[0]) && (ctxt->cur[0] != '<')) ctxt->cur++; |
|
|
if (!IS_CHAR(*cur)) { |
if (!IS_CHAR(ctxt->cur[0])) { |
fprintf(stderr, "Truncated content : %.50s\n", q); |
fprintf(stderr, "Truncated content : %.50s\n", q); |
*p = cur; |
|
return(NULL); |
return(NULL); |
} |
} |
|
|
/* |
/* |
* Do the Entities decoding... |
* Do the Entities decoding... |
*/ |
*/ |
data = xmlStrdup(xmlDecodeEntities(doc, q, cur - q)); |
data = xmlStrdup(xmlDecodeEntities(ctxt->doc, q, ctxt->cur - q)); |
} |
} |
|
|
/* |
/* |
Line 736 xmlNodePtr xmlParseContent(CHAR **p, xml
|
Line 728 xmlNodePtr xmlParseContent(CHAR **p, xml
|
} |
} |
} |
} |
|
|
*p = cur; |
|
return(ret); |
return(ret); |
} |
} |
|
|
Line 744 xmlNodePtr xmlParseContent(CHAR **p, xml
|
Line 735 xmlNodePtr xmlParseContent(CHAR **p, xml
|
* xmlParseElement: parse an XML element |
* xmlParseElement: parse an XML element |
*/ |
*/ |
|
|
xmlNodePtr xmlParseElement(CHAR **p, xmlDocPtr doc) { |
xmlNodePtr xmlParseElement(xmlParserCtxtPtr ctxt) { |
CHAR *cur = *p; |
|
xmlNodePtr ret, child; |
xmlNodePtr ret, child; |
CHAR *openTag = *p; |
CHAR *openTag = ctxt->cur; |
CHAR *closeTag = *p; |
CHAR *closeTag = ctxt->cur; |
|
|
ret = xmlParseStartTag(&cur, doc); |
ret = xmlParseStartTag(ctxt); |
if (ret == NULL) { |
if (ret == NULL) { |
*p = cur; |
|
return(NULL); |
return(NULL); |
} |
} |
|
|
/* |
/* |
* Check for an Empty Element. |
* Check for an Empty Element. |
*/ |
*/ |
if ((cur[0] == '/') && (cur[1] == '>')) { |
if ((ctxt->cur[0] == '/') && (ctxt->cur[1] == '>')) { |
cur += 2; |
ctxt->cur += 2; |
*p = cur; |
|
return(ret); |
return(ret); |
} |
} |
if (cur[0] == '>') cur++; |
if (ctxt->cur[0] == '>') ctxt->cur++; |
else { |
else { |
fprintf(stderr, "Couldn't find end of Start Tag %.30s\n", *p); |
fprintf(stderr, "Couldn't find end of Start Tag %.30s\n", openTag); |
*p = cur; |
return(NULL); |
return(ret); |
|
} |
} |
|
|
/* |
/* |
Line 783 xmlNodePtr xmlParseElement(CHAR **p, xml
|
Line 770 xmlNodePtr xmlParseElement(CHAR **p, xml
|
* |
* |
* The loop stops upon detection of an end of tag '</' |
* The loop stops upon detection of an end of tag '</' |
*/ |
*/ |
while ((IS_CHAR(cur[0])) && ((cur[0] != '<') || (cur[1] != '/'))) { |
while ((IS_CHAR(ctxt->cur[0])) && |
child = xmlParseContent(&cur, doc, ret); |
((ctxt->cur[0] != '<') || (ctxt->cur[1] != '/'))) { |
|
child = xmlParseContent(ctxt, ret); |
if (child != NULL) |
if (child != NULL) |
xmlAddChild(ret, child); |
xmlAddChild(ret, child); |
} |
} |
if (!IS_CHAR(cur[0])) { |
if (!IS_CHAR(ctxt->cur[0])) { |
fprintf(stderr, "Premature end of data in tag %.30s\n", *p); |
fprintf(stderr, "Premature end of data in tag %.30s\n", openTag); |
*p = cur; |
return(NULL); |
return(ret); |
|
} |
} |
|
|
/* |
/* |
* parse the end of tag : '</' has been detected. |
* parse the end of tag : '</' has been detected. |
*/ |
*/ |
cur += 2; |
ctxt->cur += 2; |
if (*cur == '>') cur++; /* simplified closing </> */ |
if (ctxt->cur[0] == '>') ctxt->cur++; /* simplified closing </> */ |
else { |
else { |
CHAR *endTag; |
CHAR *endTag; |
xmlDtdPtr endDtd; |
xmlDtdPtr endDtd; |
|
|
xmlParseEndTag(&cur, doc, &endDtd, &endTag); |
xmlParseEndTag(ctxt, &endDtd, &endTag); |
|
|
/* |
/* |
* Check that the Name in the ETag is the same as in the STag. |
* Check that the Name in the ETag is the same as in the STag. |
Line 818 xmlNodePtr xmlParseElement(CHAR **p, xml
|
Line 805 xmlNodePtr xmlParseElement(CHAR **p, xml
|
} |
} |
} |
} |
|
|
*p = cur; |
|
return(ret); |
return(ret); |
} |
} |
|
|
Line 826 xmlNodePtr xmlParseElement(CHAR **p, xml
|
Line 812 xmlNodePtr xmlParseElement(CHAR **p, xml
|
* xmlParseXMLDecl: parse an XML declaration header |
* xmlParseXMLDecl: parse an XML declaration header |
*/ |
*/ |
|
|
xmlDocPtr xmlParseXMLDecl(CHAR **p) { |
void xmlParseXMLDecl(xmlParserCtxtPtr ctxt) { |
CHAR *cur = *p; |
|
CHAR *version; |
CHAR *version; |
xmlDocPtr ret; |
|
|
|
/* |
/* |
* We know that '<?XML' is here. |
* We know that '<?XML' is here. |
*/ |
*/ |
cur += 5; |
ctxt->cur += 5; |
|
|
/* |
/* |
* Parse the version info |
* Parse the version info |
*/ |
*/ |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
|
|
/* |
/* |
* We should have 'version=' here ! |
* We should have 'version=' here ! |
*/ |
*/ |
if ((cur[0] == 'v') && (cur[1] == 'e') && (cur[2] == 'r') && |
if ((ctxt->cur[0] == 'v') && (ctxt->cur[1] == 'e') && |
(cur[3] == 's') && (cur[4] == 'i') && (cur[5] == 'o') && |
(ctxt->cur[2] == 'r') && (ctxt->cur[3] == 's') && |
(cur[6] == 'n') && (cur[7] == '=')) { |
(ctxt->cur[4] == 'i') && (ctxt->cur[5] == 'o') && |
cur += 8; |
(ctxt->cur[6] == 'n') && (ctxt->cur[7] == '=')) { |
version = xmlParseQuotedString(&cur); |
ctxt->cur += 8; |
|
version = xmlParseQuotedString(ctxt); |
if (version == NULL) |
if (version == NULL) |
ret = xmlNewDoc(XML_DEFAULT_VERSION); |
ctxt->doc = xmlNewDoc(XML_DEFAULT_VERSION); |
else { |
else { |
ret = xmlNewDoc(version); |
ctxt->doc = xmlNewDoc(version); |
free(version); |
free(version); |
} |
} |
} else { |
} else { |
ret = xmlNewDoc(XML_DEFAULT_VERSION); |
ctxt->doc = xmlNewDoc(XML_DEFAULT_VERSION); |
} |
} |
|
|
/* |
/* |
* We should check for Required Markup Declaration TODO !!!! |
* We should check for Required Markup Declaration TODO !!!! |
*/ |
*/ |
MOVETO_ENDTAG(cur); |
MOVETO_ENDTAG(ctxt->cur); |
cur++; |
ctxt->cur++; |
|
|
*p = cur; |
|
return(ret); |
|
} |
} |
|
|
/* |
/* |
Line 874 xmlDocPtr xmlParseXMLDecl(CHAR **p) {
|
Line 857 xmlDocPtr xmlParseXMLDecl(CHAR **p) {
|
* (Comment | PI | S)* |
* (Comment | PI | S)* |
*/ |
*/ |
|
|
void xmlParseMisc(CHAR **p, xmlDocPtr doc) { |
void xmlParseMisc(xmlParserCtxtPtr ctxt) { |
CHAR *cur = *p; |
while (((ctxt->cur[0] == '<') && (ctxt->cur[1] == '?')) || |
|
((ctxt->cur[0] == '<') && (ctxt->cur[1] == '!') && |
while (((cur[0] == '<') && (cur[1] == '?')) || |
(ctxt->cur[2] == '-') && (ctxt->cur[2] == '-')) || |
((cur[0] == '<') && (cur[1] == '!') && |
IS_BLANK(ctxt->cur[0])) { |
(cur[2] == '-') && (cur[2] == '-')) || |
if ((ctxt->cur[0] == '<') && (ctxt->cur[1] == '?')) { |
IS_BLANK(*cur)) { |
xmlParsePI(ctxt); |
if ((cur[0] == '<') && (cur[1] == '?')) { |
} else if (IS_BLANK(ctxt->cur[0])) { |
xmlParsePI(&cur, doc); |
ctxt->cur++; |
} else if (IS_BLANK(*cur)) { |
|
cur++; |
|
} else |
} else |
xmlParserSkipComment(&cur); |
xmlParserSkipComment(ctxt); |
} |
} |
|
|
*p = cur; |
|
} |
} |
|
|
/* |
/* |
* xmlParseDoc : parse an XML document and build a tree. |
* xmlParseDocument : parse an XML document and build a tree. |
*/ |
*/ |
|
|
xmlDocPtr xmlParseDoc(CHAR *cur) { |
int xmlParseDocument(xmlParserCtxtPtr ctxt) { |
xmlDocPtr ret; |
|
|
|
/* |
/* |
* We should check for encoding here and plug-in some |
* We should check for encoding here and plug-in some |
* conversion code TODO !!!! |
* conversion code TODO !!!! |
Line 907 xmlDocPtr xmlParseDoc(CHAR *cur) {
|
Line 884 xmlDocPtr xmlParseDoc(CHAR *cur) {
|
/* |
/* |
* Wipe out everything which is before the first '<' |
* Wipe out everything which is before the first '<' |
*/ |
*/ |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
|
|
/* |
/* |
* Check for the XMLDecl in the Prolog. |
* Check for the XMLDecl in the Prolog. |
*/ |
*/ |
if ((cur[0] == '<') && (cur[1] == '?') && |
if ((ctxt->cur[0] == '<') && (ctxt->cur[1] == '?') && |
(cur[2] == 'X') && (cur[3] == 'M') && |
(ctxt->cur[2] == 'X') && (ctxt->cur[3] == 'M') && |
(cur[4] == 'L')) { |
(ctxt->cur[4] == 'L')) { |
ret = xmlParseXMLDecl(&cur); |
xmlParseXMLDecl(ctxt); |
/* SKIP_EOL(cur); */ |
/* SKIP_EOL(cur); */ |
SKIP_BLANKS(cur); |
SKIP_BLANKS(ctxt->cur); |
} else { |
} else { |
ret = xmlNewDoc(XML_DEFAULT_VERSION); |
ctxt->doc = xmlNewDoc(XML_DEFAULT_VERSION); |
} |
} |
|
|
/* |
/* |
* The Misc part of the Prolog |
* The Misc part of the Prolog |
* (Comment | PI | S) * |
* (Comment | PI | S) * |
*/ |
*/ |
xmlParseMisc(&cur, ret); |
xmlParseMisc(ctxt); |
|
|
/* |
/* |
* Time to start parsing |
* Time to start parsing |
*/ |
*/ |
ret->root = xmlParseElement(&cur, ret); |
ctxt->doc->root = xmlParseElement(ctxt); |
|
|
|
return(0); |
|
} |
|
|
|
/* |
|
* xmlParseDoc : parse an XML in-memory document and build a tree. |
|
*/ |
|
|
|
xmlDocPtr xmlParseDoc(CHAR *cur) { |
|
xmlDocPtr ret; |
|
xmlParserCtxtPtr ctxt; |
|
|
|
if (cur == NULL) return(NULL); |
|
|
|
ctxt = (xmlParserCtxtPtr) malloc(sizeof(xmlParserCtxt)); |
|
if (ctxt == NULL) { |
|
perror("malloc"); |
|
return(NULL); |
|
} |
|
|
|
ctxt->filename = NULL; |
|
ctxt->base = cur; |
|
ctxt->cur = cur; |
|
ctxt->line = 1; |
|
ctxt->col = 1; |
|
ctxt->doc = NULL; |
|
|
|
xmlParseDocument(ctxt); |
|
ret = ctxt->doc; |
|
if (ctxt->filename != NULL) |
|
free(ctxt->filename); |
|
free(ctxt); |
|
|
return(ret); |
return(ret); |
} |
} |
|
|
Line 946 xmlDocPtr xmlParseFile(const char *filen
|
Line 955 xmlDocPtr xmlParseFile(const char *filen
|
int res; |
int res; |
struct stat buf; |
struct stat buf; |
char *buffer; |
char *buffer; |
|
xmlParserCtxtPtr ctxt; |
|
|
res = stat(filename, &buf); |
res = stat(filename, &buf); |
if (res < 0) return(NULL); |
if (res < 0) return(NULL); |
Line 971 xmlDocPtr xmlParseFile(const char *filen
|
Line 981 xmlDocPtr xmlParseFile(const char *filen
|
} |
} |
close(input); |
close(input); |
|
|
|
ctxt = (xmlParserCtxtPtr) malloc(sizeof(xmlParserCtxt)); |
|
if (ctxt == NULL) { |
|
perror("malloc"); |
|
return(NULL); |
|
} |
buffer[buf.st_size] = '\0'; |
buffer[buf.st_size] = '\0'; |
ret = xmlParseDoc(buffer); |
|
|
ctxt->filename = strdup(filename); |
|
ctxt->base = buffer; |
|
ctxt->cur = buffer; |
|
ctxt->line = 1; |
|
ctxt->col = 1; |
|
ctxt->doc = NULL; |
|
|
|
xmlParseDocument(ctxt); |
|
ret = ctxt->doc; |
free(buffer); |
free(buffer); |
|
if (ctxt->filename != NULL) |
|
free(ctxt->filename); |
|
free(ctxt); |
|
|
return(ret); |
return(ret); |
} |
} |