| 3969 | */ |
| 3970 | |
| 3971 | void |
| 3972 | htmlParseElement(htmlParserCtxtPtr ctxt) { |
| 3973 | const xmlChar *name; |
| 3974 | xmlChar *currentNode = NULL; |
| 3975 | const htmlElemDesc * info; |
| 3976 | htmlParserNodeInfo node_info; |
| 3977 | int failed; |
| 3978 | int depth; |
| 3979 | const xmlChar *oldptr; |
| 3980 | |
| 3981 | if ((ctxt == NULL) || (ctxt->input == NULL)) { |
| 3982 | htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, |
| 3983 | "htmlParseElement: context error\n", NULL, NULL); |
| 3984 | return; |
| 3985 | } |
| 3986 | /* Capture start position */ |
| 3987 | if (ctxt->record_info) { |
| 3988 | node_info.begin_pos = ctxt->input->consumed + |
| 3989 | (CUR_PTR - ctxt->input->base); |
| 3990 | node_info.begin_line = ctxt->input->line; |
| 3991 | } |
| 3992 | |
| 3993 | failed = htmlParseStartTag(ctxt); |
| 3994 | name = ctxt->name; |
| 3995 | if ((failed == -1) || (name == NULL)) { |
| 3996 | if (CUR == '>') |
| 3997 | NEXT; |
| 3998 | return; |
| 3999 | } |
| 4000 | |
| 4001 | /* |
| 4002 | * Lookup the info for that element. |
| 4003 | */ |
| 4004 | info = htmlTagLookup(name); |
| 4005 | if (info == NULL) { |
| 4006 | htmlParseErr(ctxt, XML_HTML_UNKNOWN_TAG, |
| 4007 | "Tag %s invalid\n", name, NULL); |
| 4008 | } |
| 4009 | |
| 4010 | /* |
| 4011 | * Check for an Empty Element labeled the XML/SGML way |
| 4012 | */ |
| 4013 | if ((CUR == '/') && (NXT(1) == '>')) { |
| 4014 | SKIP(2); |
| 4015 | if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) |
| 4016 | ctxt->sax->endElement(ctxt->userData, name); |
| 4017 | htmlnamePop(ctxt); |
| 4018 | return; |
| 4019 | } |
| 4020 | |
| 4021 | if (CUR == '>') { |
| 4022 | NEXT; |
| 4023 | } else { |
| 4024 | htmlParseErr(ctxt, XML_ERR_GT_REQUIRED, |
| 4025 | "Couldn't find end of Start Tag %s\n", name, NULL); |
| 4026 | |
| 4027 | /* |
| 4028 | * end of parsing of this node. |