📄 valid.c
字号:
* @type: the element type
* @content: the element content tree or NULL
*
* Register a new element declaration
*
* Returns NULL if not, otherwise the entity
*/
xmlElementPtr
xmlAddElementDecl(xmlValidCtxtPtr ctxt,
xmlDtdPtr dtd, const xmlChar *name,
xmlElementTypeVal type,
xmlElementContentPtr content) {
xmlElementPtr ret;
xmlElementTablePtr table;
xmlAttributePtr oldAttributes = NULL;
xmlChar *ns, *uqname;
if (dtd == NULL) {
return(NULL);
}
if (name == NULL) {
return(NULL);
}
switch (type) {
case XML_ELEMENT_TYPE_EMPTY:
if (content != NULL) {
xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
"xmlAddElementDecl: content != NULL for EMPTY\n",
NULL);
return(NULL);
}
break;
case XML_ELEMENT_TYPE_ANY:
if (content != NULL) {
xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
"xmlAddElementDecl: content != NULL for ANY\n",
NULL);
return(NULL);
}
break;
case XML_ELEMENT_TYPE_MIXED:
if (content == NULL) {
xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
"xmlAddElementDecl: content == NULL for MIXED\n",
NULL);
return(NULL);
}
break;
case XML_ELEMENT_TYPE_ELEMENT:
if (content == NULL) {
xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
"xmlAddElementDecl: content == NULL for ELEMENT\n",
NULL);
return(NULL);
}
break;
default:
xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
"Internal: ELEMENT decl corrupted invalid type\n",
NULL);
return(NULL);
}
/*
* check if name is a QName
*/
uqname = xmlSplitQName2(name, &ns);
if (uqname != NULL)
name = uqname;
/*
* Create the Element table if needed.
*/
table = (xmlElementTablePtr) dtd->elements;
if (table == NULL) {
xmlDictPtr dict = NULL;
if (dtd->doc != NULL)
dict = dtd->doc->dict;
table = xmlHashCreateDict(0, dict);
dtd->elements = (void *) table;
}
if (table == NULL) {
xmlVErrMemory(ctxt,
"xmlAddElementDecl: Table creation failed!\n");
if (uqname != NULL)
xmlFree(uqname);
if (ns != NULL)
xmlFree(ns);
return(NULL);
}
/*
* lookup old attributes inserted on an undefined element in the
* internal subset.
*/
if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) {
ret = xmlHashLookup2(dtd->doc->intSubset->elements, name, ns);
if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) {
oldAttributes = ret->attributes;
ret->attributes = NULL;
xmlHashRemoveEntry2(dtd->doc->intSubset->elements, name, ns, NULL);
xmlFreeElement(ret);
}
}
/*
* The element may already be present if one of its attribute
* was registered first
*/
ret = xmlHashLookup2(table, name, ns);
if (ret != NULL) {
if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) {
#ifdef LIBXML_VALID_ENABLED
/*
* The element is already defined in this DTD.
*/
xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
"Redefinition of element %s\n",
name, NULL, NULL);
#endif /* LIBXML_VALID_ENABLED */
if (uqname != NULL)
xmlFree(uqname);
if (ns != NULL)
xmlFree(ns);
return(NULL);
}
if (ns != NULL) {
xmlFree(ns);
ns = NULL;
}
} else {
ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
if (ret == NULL) {
xmlVErrMemory(ctxt, "malloc failed");
if (uqname != NULL)
xmlFree(uqname);
if (ns != NULL)
xmlFree(ns);
return(NULL);
}
memset(ret, 0, sizeof(xmlElement));
ret->type = XML_ELEMENT_DECL;
/*
* fill the structure.
*/
ret->name = xmlStrdup(name);
if (ret->name == NULL) {
xmlVErrMemory(ctxt, "malloc failed");
if (uqname != NULL)
xmlFree(uqname);
if (ns != NULL)
xmlFree(ns);
xmlFree(ret);
return(NULL);
}
ret->prefix = ns;
/*
* Validity Check:
* Insertion must not fail
*/
if (xmlHashAddEntry2(table, name, ns, ret)) {
#ifdef LIBXML_VALID_ENABLED
/*
* The element is already defined in this DTD.
*/
xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
"Redefinition of element %s\n",
name, NULL, NULL);
#endif /* LIBXML_VALID_ENABLED */
xmlFreeElement(ret);
if (uqname != NULL)
xmlFree(uqname);
return(NULL);
}
/*
* For new element, may have attributes from earlier
* definition in internal subset
*/
ret->attributes = oldAttributes;
}
/*
* Finish to fill the structure.
*/
ret->etype = type;
/*
* Avoid a stupid copy when called by the parser
* and flag it by setting a special parent value
* so the parser doesn't unallocate it.
*/
if ((ctxt != NULL) &&
((ctxt->finishDtd == XML_CTXT_FINISH_DTD_0) ||
(ctxt->finishDtd == XML_CTXT_FINISH_DTD_1))) {
ret->content = content;
if (content != NULL)
content->parent = (xmlElementContentPtr) 1;
} else {
ret->content = xmlCopyDocElementContent(dtd->doc, content);
}
/*
* Link it to the DTD
*/
ret->parent = dtd;
ret->doc = dtd->doc;
if (dtd->last == NULL) {
dtd->children = dtd->last = (xmlNodePtr) ret;
} else {
dtd->last->next = (xmlNodePtr) ret;
ret->prev = dtd->last;
dtd->last = (xmlNodePtr) ret;
}
if (uqname != NULL)
xmlFree(uqname);
return(ret);
}
/**
* xmlFreeElementTable:
* @table: An element table
*
* Deallocate the memory used by an element hash table.
*/
void
xmlFreeElementTable(xmlElementTablePtr table) {
xmlHashFree(table, (xmlHashDeallocator) xmlFreeElement);
}
#ifdef LIBXML_TREE_ENABLED
/**
* xmlCopyElement:
* @elem: An element
*
* Build a copy of an element.
*
* Returns the new xmlElementPtr or NULL in case of error.
*/
static xmlElementPtr
xmlCopyElement(xmlElementPtr elem) {
xmlElementPtr cur;
cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
if (cur == NULL) {
xmlVErrMemory(NULL, "malloc failed");
return(NULL);
}
memset(cur, 0, sizeof(xmlElement));
cur->type = XML_ELEMENT_DECL;
cur->etype = elem->etype;
if (elem->name != NULL)
cur->name = xmlStrdup(elem->name);
else
cur->name = NULL;
if (elem->prefix != NULL)
cur->prefix = xmlStrdup(elem->prefix);
else
cur->prefix = NULL;
cur->content = xmlCopyElementContent(elem->content);
/* TODO : rebuild the attribute list on the copy */
cur->attributes = NULL;
return(cur);
}
/**
* xmlCopyElementTable:
* @table: An element table
*
* Build a copy of an element table.
*
* Returns the new xmlElementTablePtr or NULL in case of error.
*/
xmlElementTablePtr
xmlCopyElementTable(xmlElementTablePtr table) {
return((xmlElementTablePtr) xmlHashCopy(table,
(xmlHashCopier) xmlCopyElement));
}
#endif /* LIBXML_TREE_ENABLED */
#ifdef LIBXML_OUTPUT_ENABLED
/**
* xmlDumpElementDecl:
* @buf: the XML buffer output
* @elem: An element table
*
* This will dump the content of the element declaration as an XML
* DTD definition
*/
void
xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
if ((buf == NULL) || (elem == NULL))
return;
switch (elem->etype) {
case XML_ELEMENT_TYPE_EMPTY:
xmlBufferWriteChar(buf, "<!ELEMENT ");
if (elem->prefix != NULL) {
xmlBufferWriteCHAR(buf, elem->prefix);
xmlBufferWriteChar(buf, ":");
}
xmlBufferWriteCHAR(buf, elem->name);
xmlBufferWriteChar(buf, " EMPTY>\n");
break;
case XML_ELEMENT_TYPE_ANY:
xmlBufferWriteChar(buf, "<!ELEMENT ");
if (elem->prefix != NULL) {
xmlBufferWriteCHAR(buf, elem->prefix);
xmlBufferWriteChar(buf, ":");
}
xmlBufferWriteCHAR(buf, elem->name);
xmlBufferWriteChar(buf, " ANY>\n");
break;
case XML_ELEMENT_TYPE_MIXED:
xmlBufferWriteChar(buf, "<!ELEMENT ");
if (elem->prefix != NULL) {
xmlBufferWriteCHAR(buf, elem->prefix);
xmlBufferWriteChar(buf, ":");
}
xmlBufferWriteCHAR(buf, elem->name);
xmlBufferWriteChar(buf, " ");
xmlDumpElementContent(buf, elem->content, 1);
xmlBufferWriteChar(buf, ">\n");
break;
case XML_ELEMENT_TYPE_ELEMENT:
xmlBufferWriteChar(buf, "<!ELEMENT ");
if (elem->prefix != NULL) {
xmlBufferWriteCHAR(buf, elem->prefix);
xmlBufferWriteChar(buf, ":");
}
xmlBufferWriteCHAR(buf, elem->name);
xmlBufferWriteChar(buf, " ");
xmlDumpElementContent(buf, elem->content, 1);
xmlBufferWriteChar(buf, ">\n");
break;
default:
xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
"Internal: ELEMENT struct corrupted invalid type\n",
NULL);
}
}
/**
* xmlDumpElementDeclScan:
* @elem: An element table
* @buf: the XML buffer output
*
* This routine is used by the hash scan function. It just reverses
* the arguments.
*/
static void
xmlDumpElementDeclScan(xmlElementPtr elem, xmlBufferPtr buf) {
xmlDumpElementDecl(buf, elem);
}
/**
* xmlDumpElementTable:
* @buf: the XML buffer output
* @table: An element table
*
* This will dump the content of the element table as an XML DTD definition
*/
void
xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
if ((buf == NULL) || (table == NULL))
return;
xmlHashScan(table, (xmlHashScanner) xmlDumpElementDeclScan, buf);
}
#endif /* LIBXML_OUTPUT_ENABLED */
/**
* xmlCreateEnumeration:
* @name: the enumeration name or NULL
*
* create and initialize an enumeration attribute node.
*
* Returns the xmlEnumerationPtr just created or NULL in case
* of error.
*/
xmlEnumerationPtr
xmlCreateEnumeration(const xmlChar *name) {
xmlEnumerationPtr ret;
ret = (xmlEnumerationPtr) xmlMalloc(sizeof(xmlEnumeration));
if (ret == NULL) {
xmlVErrMemory(NULL, "malloc failed");
return(NULL);
}
memset(ret, 0, sizeof(xmlEnumeration));
if (name != NULL)
ret->name = xmlStrdup(name);
return(ret);
}
/**
* xmlFreeEnumeration:
* @cur: the tree to free.
*
* free an enumeration attribute node (recursive).
*/
void
xmlFreeEnumeration(xmlEnumerationPtr cur) {
if (cur == NULL) return;
if (cur->next != NULL) xmlFreeEnumeration(cur->next);
if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
xmlFree(cur);
}
#ifdef LIBXML_TREE_ENABLED
/**
* xmlCopyEnumeration:
* @cur: the tree to copy.
*
* Copy an enumeration attribute node (recursive).
*
* Returns the xmlEnumerationPtr just created or NULL in case
* of error.
*/
xmlEnumerationPtr
xmlCopyEnumeration(xmlEnumerationPtr cur) {
xmlEnumerationPtr ret;
if (cur == NULL) return(NULL);
ret = xmlCreateEnumeration((xmlChar *) cur->name);
if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next);
else ret->next = NULL;
return(ret);
}
#endif /* LIBXML_TREE_ENABLED */
#ifdef LIBXML_OUTPUT_ENABLED
/**
* xmlDumpEnumeration:
* @buf: the XML buffer output
* @enum: An enumeration
*
* This will dump the content of the enumeration
*/
static void
xmlDumpEnumeration(xmlBufferPtr buf, xmlEnumerationPtr cur) {
if ((buf == NULL) || (cur == NULL))
return;
xmlBufferWriteCHAR(buf, cur->name);
if (cur->next == NULL)
xmlBufferWriteChar(buf, ")");
else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -