DFNode *fromTidyNode(DFDocument *htmlDoc, TidyDoc tdoc, TidyNode tnode) { switch (tidyNodeGetType(tnode)) { case TidyNode_Text: { char *value = copyTidyNodeValue(tnode,tdoc); DFNode *result = DFCreateTextNode(htmlDoc,value); free(value); return result; } case TidyNode_CDATA: break; case TidyNode_Comment: break; case TidyNode_Root: printf("Have root\n"); break; default: { const char *name = tidyNodeGetName(tnode); if (name == NULL) { printf("NULL name for %p, type %d\n",tnode,tidyNodeGetType(tnode)); return NULL; } const NamespaceDecl *namespaceDecl = DFNameMapNamespaceForID(htmlDoc->map,NAMESPACE_HTML); Tag tag = DFNameMapTagForName(htmlDoc->map,namespaceDecl->namespaceURI,name); DFNode *element = DFCreateElement(htmlDoc,tag); for (TidyAttr tattr = tidyAttrFirst(tnode); tattr != NULL; tattr = tidyAttrNext(tattr)) { const char *name = tidyAttrName(tattr); const char *value = tidyAttrValue(tattr); if (value == NULL) // Can happen in case of the empty string value = "";; Tag attrTag = DFNameMapTagForName(htmlDoc->map,namespaceDecl->namespaceURI,name); DFSetAttribute(element,attrTag,value); } for (TidyNode tchild = tidyGetChild(tnode); tchild != NULL; tchild = tidyGetNext(tchild)) { DFNode *child = fromTidyNode(htmlDoc,tdoc,tchild); if (child != NULL) DFAppendChild(element,child); } return element; } } return NULL; }
static void SAXStartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) { DFSAXParser *parser = (DFSAXParser *)ctx; const NamespaceDecl *namespaceDecl = DFNameMapNamespaceForID(parser->document->map,NAMESPACE_HTML); Tag tag = DFNameMapTagForName(parser->document->map,namespaceDecl->namespaceURI,(const char *)fullname); DFNode *element = DFCreateElement(parser->document,tag); if (atts != NULL) { for (int i = 0; atts[i] != NULL; i += 2) { const xmlChar *name = atts[i]; const xmlChar *value = atts[i+1]; Tag attrTag = DFNameMapTagForName(parser->document->map,namespaceDecl->namespaceURI,(const char *)name); DFSetAttribute(element,attrTag,(const char *)value); } } DFAppendChild(parser->parent,element); parser->parent = element; if (parser->document->root == NULL) parser->document->root = element; }
// FIXME: Not covered by tests void DFMarkupCompatibilityProcessAttr(DFMarkupCompatibility *mc, Tag attr, const char *value, DFNameMap *map) { const char **tokens = DFStringTokenize(value,isspace); for (int tokIndex = 0; tokens[tokIndex]; tokIndex++) { const char *component = tokens[tokIndex]; char *prefix = NULL; char *localName = NULL; const char *colon = strchr(component,':'); if (colon != NULL) { size_t colonPos = colon - component; prefix = DFSubstring(component,0,colonPos); localName = DFSubstring(component,colonPos+1,strlen(component)); } else { prefix = xstrdup(component); localName = NULL; } const char *nsIdStr = NULL; // Find namespace ID for prefix for (int recordIndex = mc->depth-1; recordIndex >= 0; recordIndex--) { MCRecord *record = &mc->records[recordIndex]; if (record->namespaces != NULL) nsIdStr = DFHashTableLookup(record->namespaces,prefix); } if (nsIdStr != NULL) { NamespaceID nsId = atoi(nsIdStr); Tag tag = 0; const NamespaceDecl *nsDecl = DFNameMapNamespaceForID(map,nsId); if (localName != NULL) tag = DFNameMapTagForName(map,nsDecl->namespaceURI,localName); switch (attr) { case MC_IGNORABLE: addDeclToRecord(&mc->records[mc->depth-1],nsId,tag,MCActionIgnore); break; case MC_PROCESSCONTENT: addDeclToRecord(&mc->records[mc->depth-1],nsId,tag,MCActionProcessContent); break; case MC_MUSTUNDERSTAND: addDeclToRecord(&mc->records[mc->depth-1],nsId,tag,MCActionMustUnderstand); break; } } free(prefix); free(localName); } free(tokens); }
Tag DFLookupTag(DFDocument *doc, const char *URI, const char *name) { return DFNameMapTagForName(doc->map,URI,name); }
static void SAXStartElementNS(void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes) { DFSAXParser *parser = (DFSAXParser *)ctx; if (parser->ignoreDepth > 0) { parser->ignoreDepth++; return; } for (int i = 0; i < nb_namespaces; i++) { const xmlChar *nsPrefix = namespaces[i*2]; const xmlChar *nsURI = namespaces[i*2+1]; DFNameMapFoundNamespace(parser->document->map,(const char *)nsURI,(const char *)nsPrefix); } Tag tag = DFNameMapTagForName(parser->document->map,(const char *)URI,(const char *)localname); if (parser->compatibility != NULL) { const TagDecl *tagDecl = DFNameMapNameForTag(parser->document->map,tag); MCAction action = DFMarkupCompatibilityLookup(parser->compatibility,tagDecl->namespaceID,tag,1); if (action == MCActionIgnore) { parser->ignoreDepth++; return; } } if (parser->compatibility != NULL) { DFMarkupCompatibilityPush(parser->compatibility,nb_namespaces,(const char **)namespaces,parser->document->map); } DFNode *element = DFCreateElement(parser->document,tag); for (int i = 0; i < nb_attributes; i++) { const xmlChar *attrLocalName = attributes[i*5+0]; const xmlChar *attrURI = attributes[i*5+2]; const xmlChar *attrValueStart = attributes[i*5+3]; const xmlChar *attrValueEnd = attributes[i*5+4]; unsigned long attrValueLen = (unsigned long)(attrValueEnd - attrValueStart); Tag attrTag = DFNameMapTagForName(parser->document->map,(const char *)attrURI,(const char *)attrLocalName); const TagDecl *attrTagDecl = DFNameMapNameForTag(parser->document->map,attrTag); char *attrValue = (char *)xmalloc(attrValueLen+1); memcpy(attrValue,attrValueStart,attrValueLen); attrValue[attrValueLen] = '\0'; if (parser->compatibility != NULL) { switch (attrTag) { case MC_IGNORABLE: case MC_PROCESSCONTENT: case MC_MUSTUNDERSTAND: DFMarkupCompatibilityProcessAttr(parser->compatibility,attrTag,attrValue,parser->document->map); break; default: { MCAction action = DFMarkupCompatibilityLookup(parser->compatibility,attrTagDecl->namespaceID,0,0); if (action != MCActionIgnore) DFSetAttribute(element,attrTag,attrValue); break; } } } else { DFSetAttribute(element,attrTag,attrValue); } free(attrValue); } DFAppendChild(parser->parent,element); parser->parent = element; if (parser->document->root == NULL) parser->document->root = element; }
Tag DFBuiltinMapTagForName(const char *URI, const char *localName) { return DFNameMapTagForName(BuiltinMapGet(),URI,localName); }