mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2024-12-24 21:33:51 +03:00
Added copy operations for node/tree/documents, Daniel.
This commit is contained in:
parent
aa873f7b76
commit
be36afe119
@ -1,3 +1,9 @@
|
||||
Fri Nov 27 01:36:54 EST 1998 Daniel Veillard <Daniel.Veillard@w3.org>
|
||||
|
||||
* entities.[ch], tree.[ch], tester.c: added copy interfaces
|
||||
for node/trees/documents/... Biggest problem is namespace
|
||||
support when copying subtrees.
|
||||
|
||||
Sun Nov 15 19:59:47 EST 1998 Daniel Veillard <Daniel.Veillard@w3.org>
|
||||
|
||||
* parser.c, entities.c: improve entities and char ref encoding,
|
||||
|
187
entities.c
187
entities.c
@ -31,6 +31,9 @@ xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
|
||||
|
||||
/*
|
||||
* A buffer used for converting entities to their equivalent and back.
|
||||
*
|
||||
* TODO: remove this, this helps performances but forbid reentrancy in a
|
||||
* stupid way.
|
||||
*/
|
||||
static int buffer_size = 0;
|
||||
static CHAR *buffer = NULL;
|
||||
@ -47,7 +50,6 @@ void growBuffer(void) {
|
||||
/*
|
||||
* xmlFreeEntity : clean-up an entity record.
|
||||
*/
|
||||
|
||||
void xmlFreeEntity(xmlEntityPtr entity) {
|
||||
if (entity == NULL) return;
|
||||
|
||||
@ -63,12 +65,13 @@ void xmlFreeEntity(xmlEntityPtr entity) {
|
||||
}
|
||||
|
||||
/*
|
||||
* xmlAddDocEntity : register a new entity for an entities table.
|
||||
* xmlAddEntity : register a new entity for an entities table.
|
||||
*
|
||||
* TODO !!! We should check here that the combination of type
|
||||
* ExternalID and SystemID is valid.
|
||||
*/
|
||||
static void xmlAddEntity(xmlEntitiesTablePtr table, const CHAR *name, int type,
|
||||
static void
|
||||
xmlAddEntity(xmlEntitiesTablePtr table, const CHAR *name, int type,
|
||||
const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
|
||||
int i;
|
||||
xmlEntityPtr cur;
|
||||
@ -116,8 +119,10 @@ static void xmlAddEntity(xmlEntitiesTablePtr table, const CHAR *name, int type,
|
||||
table->nb_entities++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up xmlPredefinedEntities from xmlPredefinedEntityValues.
|
||||
/**
|
||||
* xmlInitializePredefinedEntities:
|
||||
*
|
||||
* Set up the predefined entities.
|
||||
*/
|
||||
void xmlInitializePredefinedEntities(void) {
|
||||
int i;
|
||||
@ -165,12 +170,19 @@ xmlGetPredefinedEntity(const CHAR *name) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* xmlAddDtdEntity : register a new entity for this DTD.
|
||||
/**
|
||||
* xmlAddDtdEntity:
|
||||
* @doc: the document
|
||||
* @name: the entity name
|
||||
* @type: the entity type XML_xxx_yyy_ENTITY
|
||||
* @ExternalID: the entity external ID if available
|
||||
* @SystemID: the entity system ID if available
|
||||
* @content: the entity content
|
||||
*
|
||||
* Register a new entity for this document DTD.
|
||||
*/
|
||||
void xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
|
||||
void
|
||||
xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
|
||||
const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
|
||||
xmlEntitiesTablePtr table;
|
||||
|
||||
@ -186,10 +198,19 @@ void xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
|
||||
xmlAddEntity(table, name, type, ExternalID, SystemID, content);
|
||||
}
|
||||
|
||||
/*
|
||||
* xmlAddDocEntity : register a new entity for this document.
|
||||
/**
|
||||
* xmlAddDocEntity:
|
||||
* @doc: the document
|
||||
* @name: the entity name
|
||||
* @type: the entity type XML_xxx_yyy_ENTITY
|
||||
* @ExternalID: the entity external ID if available
|
||||
* @SystemID: the entity system ID if available
|
||||
* @content: the entity content
|
||||
*
|
||||
* Register a new entity for this document.
|
||||
*/
|
||||
void xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
|
||||
void
|
||||
xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
|
||||
const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
|
||||
xmlEntitiesTablePtr table;
|
||||
|
||||
@ -201,11 +222,18 @@ void xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
|
||||
xmlAddEntity(doc->entities, name, type, ExternalID, SystemID, content);
|
||||
}
|
||||
|
||||
/*
|
||||
* xmlGetDtdEntity : do an entity lookup in the Dtd entity hash table and
|
||||
* returns the corrsponding entity, if found, NULL otherwise.
|
||||
/**
|
||||
* xmlGetDtdEntity:
|
||||
* @doc: the document referencing the entity
|
||||
* @name: the entity name
|
||||
*
|
||||
* Do an entity lookup in the Dtd entity hash table and
|
||||
* returns the corresponding entity, if found.
|
||||
*
|
||||
* return values: A pointer to the entity structure or NULL if not found.
|
||||
*/
|
||||
xmlEntityPtr xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name) {
|
||||
xmlEntityPtr
|
||||
xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name) {
|
||||
int i;
|
||||
xmlEntityPtr cur;
|
||||
xmlEntitiesTablePtr table;
|
||||
@ -220,12 +248,19 @@ xmlEntityPtr xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* xmlGetDocEntity : do an entity lookup in the document entity hash table and
|
||||
* returns the corrsponding entity, otherwise a lookup is done
|
||||
* in the predefined entities too.
|
||||
/**
|
||||
* xmlGetDocEntity:
|
||||
* @doc: the document referencing the entity
|
||||
* @name: the entity name
|
||||
*
|
||||
* Do an entity lookup in the document entity hash table and
|
||||
* returns the corrsponding entity, otherwise a lookup is done
|
||||
* in the predefined entities too.
|
||||
*
|
||||
* return values: A pointer to the entity structure or NULL if not found.
|
||||
*/
|
||||
xmlEntityPtr xmlGetDocEntity(xmlDocPtr doc, const CHAR *name) {
|
||||
xmlEntityPtr
|
||||
xmlGetDocEntity(xmlDocPtr doc, const CHAR *name) {
|
||||
int i;
|
||||
xmlEntityPtr cur;
|
||||
xmlEntitiesTablePtr table;
|
||||
@ -257,15 +292,24 @@ xmlEntityPtr xmlGetDocEntity(xmlDocPtr doc, const CHAR *name) {
|
||||
(((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
|
||||
(((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
|
||||
|
||||
/*
|
||||
* xmlEncodeEntities : do a global encoding of a string, replacing the
|
||||
* predefined entities and non ASCII values with their
|
||||
* entities and CharRef counterparts.
|
||||
/**
|
||||
* xmlEncodeEntities:
|
||||
* @doc: the document containing the string
|
||||
* @input: A string to convert to XML.
|
||||
*
|
||||
* Do a global encoding of a string, replacing the predefined entities
|
||||
* and non ASCII values with their entities and CharRef counterparts.
|
||||
*
|
||||
* TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
|
||||
* get erroneous.
|
||||
*
|
||||
* TODO This routine is not reentrant and this will be changed, the interface
|
||||
* should not be modified though.
|
||||
*
|
||||
* return values: A newly allocated string with the substitution done.
|
||||
*/
|
||||
|
||||
CHAR *xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
|
||||
CHAR *
|
||||
xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
|
||||
const CHAR *cur = input;
|
||||
CHAR *out = buffer;
|
||||
|
||||
@ -363,10 +407,15 @@ CHAR *xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
|
||||
return(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* xmlCreateEntitiesTable : create and initialize an enmpty hash table
|
||||
/**
|
||||
* xmlCreateEntitiesTable:
|
||||
*
|
||||
* create and initialize an empty entities hash table.
|
||||
*
|
||||
* return values: the xmlEntitiesTablePtr just created or NULL in case of error.
|
||||
*/
|
||||
xmlEntitiesTablePtr xmlCreateEntitiesTable(void) {
|
||||
xmlEntitiesTablePtr
|
||||
xmlCreateEntitiesTable(void) {
|
||||
xmlEntitiesTablePtr ret;
|
||||
|
||||
ret = (xmlEntitiesTablePtr)
|
||||
@ -389,10 +438,14 @@ xmlEntitiesTablePtr xmlCreateEntitiesTable(void) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* xmlFreeEntitiesTable : clean up and free an entities hash table.
|
||||
/**
|
||||
* xmlFreeEntitiesTable:
|
||||
* @table: An entity table
|
||||
*
|
||||
* Deallocate the memory used by an entities hash table.
|
||||
*/
|
||||
void xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
|
||||
void
|
||||
xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
|
||||
int i;
|
||||
|
||||
if (table == NULL) return;
|
||||
@ -404,10 +457,70 @@ void xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
|
||||
free(table);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the content of an entity table to the document output.
|
||||
/**
|
||||
* xmlCopyEntitiesTable:
|
||||
* @table: An entity table
|
||||
*
|
||||
* Build a copy of an entity table.
|
||||
*
|
||||
* return values: the new xmlEntitiesTablePtr or NULL in case of error.
|
||||
*/
|
||||
void xmlDumpEntitiesTable(xmlEntitiesTablePtr table) {
|
||||
xmlEntitiesTablePtr
|
||||
xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
|
||||
xmlEntitiesTablePtr ret;
|
||||
xmlEntityPtr cur, ent;
|
||||
int i;
|
||||
|
||||
ret = (xmlEntitiesTablePtr) malloc(sizeof(xmlEntitiesTable));
|
||||
if (ret == NULL) {
|
||||
fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
|
||||
return(NULL);
|
||||
}
|
||||
ret->table = (xmlEntityPtr) malloc(table->max_entities *
|
||||
sizeof(xmlEntity));
|
||||
if (ret->table == NULL) {
|
||||
fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
|
||||
free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
ret->max_entities = table->max_entities;
|
||||
ret->nb_entities = table->nb_entities;
|
||||
for (i = 0;i < ret->nb_entities;i++) {
|
||||
cur = &ret->table[i];
|
||||
ent = &table->table[i];
|
||||
cur->len = ent->len;
|
||||
cur->type = ent->type;
|
||||
if (ent->name != NULL)
|
||||
cur->name = xmlStrdup(ent->name);
|
||||
else
|
||||
cur->name = NULL;
|
||||
if (ent->ExternalID != NULL)
|
||||
cur->ExternalID = xmlStrdup(ent->ExternalID);
|
||||
else
|
||||
cur->ExternalID = NULL;
|
||||
if (ent->SystemID != NULL)
|
||||
cur->SystemID = xmlStrdup(ent->SystemID);
|
||||
else
|
||||
cur->SystemID = NULL;
|
||||
if (ent->content != NULL)
|
||||
cur->content = xmlStrdup(ent->content);
|
||||
else
|
||||
cur->content = NULL;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlDumpEntitiesTable:
|
||||
* @table: An entity table
|
||||
*
|
||||
* This will dump the content of the entity table as an XML DTD definition
|
||||
*
|
||||
* NOTE: TODO an extra parameter allowing a reentant implementation will
|
||||
* be added.
|
||||
*/
|
||||
void
|
||||
xmlDumpEntitiesTable(xmlEntitiesTablePtr table) {
|
||||
int i;
|
||||
xmlEntityPtr cur;
|
||||
|
||||
|
@ -46,7 +46,7 @@ typedef struct xmlEntity {
|
||||
typedef struct xmlEntitiesTable {
|
||||
int nb_entities; /* number of elements stored */
|
||||
int max_entities; /* maximum number of elements */
|
||||
xmlEntityPtr table; /* the table of entities */
|
||||
xmlEntityPtr table; /* the table of entities */
|
||||
} xmlEntitiesTable, *xmlEntitiesTablePtr;
|
||||
|
||||
|
||||
@ -63,10 +63,12 @@ extern xmlEntityPtr xmlGetDocEntity(xmlDocPtr doc, const CHAR *name);
|
||||
extern xmlEntityPtr xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name);
|
||||
extern CHAR *xmlEncodeEntities(xmlDocPtr doc, const CHAR *input);
|
||||
extern xmlEntitiesTablePtr xmlCreateEntitiesTable(void);
|
||||
extern xmlEntitiesTablePtr xmlCopyEntitiesTable(xmlEntitiesTablePtr table);
|
||||
extern void xmlFreeEntitiesTable(xmlEntitiesTablePtr table);
|
||||
extern void xmlDumpEntitiesTable(xmlEntitiesTablePtr table);
|
||||
extern xmlParserInputPtr xmlNewEntityInputStream(xmlParserCtxtPtr ctxt,
|
||||
xmlEntityPtr entity);
|
||||
extern xmlEntitiesTablePtr xmlCopyEntitiesTable(xmlEntitiesTablePtr table);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ typedef struct xmlEntity {
|
||||
typedef struct xmlEntitiesTable {
|
||||
int nb_entities; /* number of elements stored */
|
||||
int max_entities; /* maximum number of elements */
|
||||
xmlEntityPtr table; /* the table of entities */
|
||||
xmlEntityPtr table; /* the table of entities */
|
||||
} xmlEntitiesTable, *xmlEntitiesTablePtr;
|
||||
|
||||
|
||||
@ -63,10 +63,12 @@ extern xmlEntityPtr xmlGetDocEntity(xmlDocPtr doc, const CHAR *name);
|
||||
extern xmlEntityPtr xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name);
|
||||
extern CHAR *xmlEncodeEntities(xmlDocPtr doc, const CHAR *input);
|
||||
extern xmlEntitiesTablePtr xmlCreateEntitiesTable(void);
|
||||
extern xmlEntitiesTablePtr xmlCopyEntitiesTable(xmlEntitiesTablePtr table);
|
||||
extern void xmlFreeEntitiesTable(xmlEntitiesTablePtr table);
|
||||
extern void xmlDumpEntitiesTable(xmlEntitiesTablePtr table);
|
||||
extern xmlParserInputPtr xmlNewEntityInputStream(xmlParserCtxtPtr ctxt,
|
||||
xmlEntityPtr entity);
|
||||
extern xmlEntitiesTablePtr xmlCopyEntitiesTable(xmlEntitiesTablePtr table);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ typedef struct xmlDoc {
|
||||
int standalone; /* standalone document (no external refs) */
|
||||
struct xmlDtd *dtd; /* the document DTD if available */
|
||||
struct xmlNs *oldNs; /* Global namespace, the old way */
|
||||
void *entities; /* Hash table for general entities if any */
|
||||
void *entities; /* Hash table for general entities if any */
|
||||
struct xmlNode *root; /* the document tree */
|
||||
} xmlDoc, *xmlDocPtr;
|
||||
|
||||
@ -183,6 +183,10 @@ extern xmlAttrPtr xmlNewProp(xmlNodePtr node, const CHAR *name,
|
||||
const CHAR *value);
|
||||
extern void xmlFreePropList(xmlAttrPtr cur);
|
||||
extern void xmlFreeProp(xmlAttrPtr cur);
|
||||
extern xmlAttrPtr xmlCopyProp(xmlAttrPtr cur);
|
||||
extern xmlAttrPtr xmlCopyPropList(xmlAttrPtr cur);
|
||||
extern xmlDtdPtr xmlCopyDtd(xmlDtdPtr dtd);
|
||||
extern xmlDocPtr xmlCopyDoc(xmlDocPtr doc, int recursive);
|
||||
|
||||
/*
|
||||
* Creating new nodes
|
||||
@ -199,6 +203,8 @@ extern xmlNodePtr xmlNewTextLen(const CHAR *content, int len);
|
||||
extern xmlNodePtr xmlNewDocComment(xmlDocPtr doc, CHAR *content);
|
||||
extern xmlNodePtr xmlNewComment(CHAR *content);
|
||||
extern xmlNodePtr xmlNewReference(xmlDocPtr doc, const CHAR *name);
|
||||
extern xmlNodePtr xmlCopyNode(xmlNodePtr node, int recursive);
|
||||
extern xmlNodePtr xmlCopyNodeList(xmlNodePtr node);
|
||||
|
||||
/*
|
||||
* Navigating
|
||||
@ -226,6 +232,8 @@ extern xmlNsPtr xmlSearchNs(xmlDocPtr doc, xmlNodePtr node,
|
||||
extern xmlNsPtr xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node,
|
||||
const CHAR *href);
|
||||
extern void xmlSetNs(xmlNodePtr node, xmlNsPtr ns);
|
||||
extern xmlNsPtr xmlCopyNamespace(xmlNsPtr cur);
|
||||
extern xmlNsPtr xmlCopyNamespaceList(xmlNsPtr cur);
|
||||
|
||||
/*
|
||||
* Changing the content.
|
||||
|
58
tester.c
58
tester.c
@ -31,6 +31,7 @@
|
||||
#include "debugXML.h"
|
||||
|
||||
static int debug = 0;
|
||||
static int copy = 0;
|
||||
|
||||
/*
|
||||
* Note: there is a couple of errors introduced on purpose.
|
||||
@ -63,12 +64,12 @@ static CHAR buffer[] =
|
||||
************************************************************************/
|
||||
|
||||
int treeTest(void) {
|
||||
xmlDocPtr doc, tmp;
|
||||
xmlNodePtr tree, subtree;
|
||||
|
||||
/*
|
||||
* build a fake XML document
|
||||
*/
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr tree, subtree;
|
||||
|
||||
doc = xmlNewDoc("1.0");
|
||||
doc->root = xmlNewDocNode(doc, NULL, "EXAMPLE", NULL);
|
||||
xmlSetProp(doc->root, "prop1", "gnome is great");
|
||||
@ -81,6 +82,15 @@ int treeTest(void) {
|
||||
subtree = xmlNewChild(tree, NULL, "image", NULL);
|
||||
xmlSetProp(subtree, "href", "linus.gif");
|
||||
|
||||
/*
|
||||
* test intermediate copy if needed.
|
||||
*/
|
||||
if (copy) {
|
||||
tmp = doc;
|
||||
doc = xmlCopyDoc(doc, 1);
|
||||
xmlFreeDoc(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* print it.
|
||||
*/
|
||||
@ -94,13 +104,22 @@ int treeTest(void) {
|
||||
}
|
||||
|
||||
void parseAndPrintFile(char *filename) {
|
||||
xmlDocPtr doc;
|
||||
xmlDocPtr doc, tmp;
|
||||
|
||||
/*
|
||||
* build an XML tree from a string;
|
||||
*/
|
||||
doc = xmlParseFile(filename);
|
||||
|
||||
/*
|
||||
* test intermediate copy if needed.
|
||||
*/
|
||||
if (copy) {
|
||||
tmp = doc;
|
||||
doc = xmlCopyDoc(doc, 1);
|
||||
xmlFreeDoc(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* print it.
|
||||
*/
|
||||
@ -116,13 +135,22 @@ void parseAndPrintFile(char *filename) {
|
||||
}
|
||||
|
||||
void parseAndPrintBuffer(CHAR *buf) {
|
||||
xmlDocPtr doc;
|
||||
xmlDocPtr doc, tmp;
|
||||
|
||||
/*
|
||||
* build an XML tree from a string;
|
||||
*/
|
||||
doc = xmlParseDoc(buf);
|
||||
|
||||
/*
|
||||
* test intermediate copy if needed.
|
||||
*/
|
||||
if (copy) {
|
||||
tmp = doc;
|
||||
doc = xmlCopyDoc(doc, 1);
|
||||
xmlFreeDoc(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* print it.
|
||||
*/
|
||||
@ -139,15 +167,21 @@ void parseAndPrintBuffer(CHAR *buf) {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
int files = 0;
|
||||
|
||||
if (argc > 1) {
|
||||
for (i = 1; i < argc ; i++) {
|
||||
if ((strcmp(argv[i], "-debug")) && (strcmp(argv[i], "--debug")))
|
||||
parseAndPrintFile(argv[i]);
|
||||
else
|
||||
debug++;
|
||||
for (i = 1; i < argc ; i++) {
|
||||
if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
|
||||
debug++;
|
||||
else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
|
||||
copy++;
|
||||
}
|
||||
for (i = 1; i < argc ; i++) {
|
||||
if (argv[i][0] != '-') {
|
||||
parseAndPrintFile(argv[i]);
|
||||
files ++;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
if (files == 0) {
|
||||
printf("\nFirst test for the parser, with errors\n");
|
||||
parseAndPrintBuffer(buffer);
|
||||
printf("\nBuilding a tree from scratch and printing it\n");
|
||||
|
351
tree.c
351
tree.c
@ -133,7 +133,7 @@ xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *prefix) {
|
||||
*/
|
||||
cur = (xmlNsPtr) malloc(sizeof(xmlNs));
|
||||
if (cur == NULL) {
|
||||
fprintf(stderr, "xmlNewNs : malloc failed\n");
|
||||
fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
@ -234,7 +234,7 @@ xmlNewDtd(xmlDocPtr doc, const CHAR *name,
|
||||
const CHAR *ExternalID, const CHAR *SystemID) {
|
||||
xmlDtdPtr cur;
|
||||
|
||||
if (doc->dtd != NULL) {
|
||||
if ((doc != NULL) && (doc->dtd != NULL)) {
|
||||
fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
|
||||
/* !!! */ (char *) name, doc->name, /* !!! */ (char *)doc->dtd->name);
|
||||
}
|
||||
@ -244,7 +244,7 @@ xmlNewDtd(xmlDocPtr doc, const CHAR *name,
|
||||
*/
|
||||
cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
|
||||
if (cur == NULL) {
|
||||
fprintf(stderr, "xmlNewNs : malloc failed\n");
|
||||
fprintf(stderr, "xmlNewDtd : malloc failed\n");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
@ -262,7 +262,8 @@ xmlNewDtd(xmlDocPtr doc, const CHAR *name,
|
||||
cur->SystemID = NULL;
|
||||
cur->elements = NULL;
|
||||
cur->entities = NULL;
|
||||
doc->dtd = cur;
|
||||
if (doc != NULL)
|
||||
doc->dtd = cur;
|
||||
|
||||
return(cur);
|
||||
}
|
||||
@ -349,6 +350,7 @@ xmlFreeDoc(xmlDocPtr cur) {
|
||||
if (cur->encoding != NULL) free((char *) cur->encoding);
|
||||
if (cur->root != NULL) xmlFreeNode(cur->root);
|
||||
if (cur->dtd != NULL) xmlFreeDtd(cur->dtd);
|
||||
if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
|
||||
if (cur->entities != NULL)
|
||||
xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
|
||||
memset(cur, -1, sizeof(xmlDoc));
|
||||
@ -1270,6 +1272,347 @@ xmlUnlinkNode(xmlNodePtr cur) {
|
||||
cur->parent = NULL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Copy operations *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* xmlCopyNamespace:
|
||||
* @cur: the namespace
|
||||
*
|
||||
* Do a copy of the namespace.
|
||||
*
|
||||
* Returns: a new xmlNsPtr, or NULL in case of error.
|
||||
*/
|
||||
xmlNsPtr
|
||||
xmlCopyNamespace(xmlNsPtr cur) {
|
||||
xmlNsPtr ret;
|
||||
|
||||
if (cur == NULL) return(NULL);
|
||||
switch (cur->type) {
|
||||
case XML_GLOBAL_NAMESPACE:
|
||||
ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
|
||||
break;
|
||||
case XML_LOCAL_NAMESPACE:
|
||||
ret = xmlNewNs(NULL, cur->href, cur->prefix);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
|
||||
return(NULL);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlCopyNamespaceList:
|
||||
* @cur: the first namespace
|
||||
*
|
||||
* Do a copy of an namespace list.
|
||||
*
|
||||
* Returns: a new xmlNsPtr, or NULL in case of error.
|
||||
*/
|
||||
xmlNsPtr
|
||||
xmlCopyNamespaceList(xmlNsPtr cur) {
|
||||
xmlNsPtr ret = NULL;
|
||||
xmlNsPtr p = NULL,q;
|
||||
|
||||
while (cur != NULL) {
|
||||
q = xmlCopyNamespace(cur);
|
||||
if (p == NULL) {
|
||||
ret = p = q;
|
||||
} else {
|
||||
p->next = q;
|
||||
p = q;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlCopyProp:
|
||||
* @cur: the attribute
|
||||
*
|
||||
* Do a copy of the attribute.
|
||||
*
|
||||
* Returns: a new xmlAttrPtr, or NULL in case of error.
|
||||
*/
|
||||
xmlAttrPtr
|
||||
xmlCopyProp(xmlAttrPtr cur) {
|
||||
xmlAttrPtr ret;
|
||||
|
||||
if (cur == NULL) return(NULL);
|
||||
if (cur->val != NULL)
|
||||
ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
|
||||
else
|
||||
ret = xmlNewDocProp(NULL, cur->name, NULL);
|
||||
if (ret == NULL) return(NULL);
|
||||
if (cur->val != NULL)
|
||||
ret->val = xmlCopyNodeList(cur->val);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlCopyPropList:
|
||||
* @cur: the first attribute
|
||||
*
|
||||
* Do a copy of an attribute list.
|
||||
*
|
||||
* Returns: a new xmlAttrPtr, or NULL in case of error.
|
||||
*/
|
||||
xmlAttrPtr
|
||||
xmlCopyPropList(xmlAttrPtr cur) {
|
||||
xmlAttrPtr ret = NULL;
|
||||
xmlAttrPtr p = NULL,q;
|
||||
|
||||
while (cur != NULL) {
|
||||
q = xmlCopyProp(cur);
|
||||
if (p == NULL) {
|
||||
ret = p = q;
|
||||
} else {
|
||||
p->next = q;
|
||||
p = q;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE about the CopyNode operations !
|
||||
*
|
||||
* They are splitted into external and internal parts for one
|
||||
* tricky reason: namespaces. Doing a direct copy of a node
|
||||
* say RPM:Copyright without changing the namespace pointer to
|
||||
* something else can produce stale links. One way to do it is
|
||||
* to keep a reference counter but this doesn't work as soon
|
||||
* as one move the element or the subtree out of the scope of
|
||||
* the existing namespace. The actual solution seems to add
|
||||
* a copy of the namespace at the top of the copied tree if
|
||||
* not available in the subtree.
|
||||
* Hence two functions, the public front-end call the inner ones
|
||||
*/
|
||||
|
||||
static xmlNodePtr
|
||||
xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
|
||||
|
||||
static xmlNodePtr
|
||||
xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
|
||||
int recursive) {
|
||||
xmlNodePtr ret;
|
||||
|
||||
if (node == NULL) return(NULL);
|
||||
/*
|
||||
* Allocate a new node and fill the fields.
|
||||
*/
|
||||
ret = (xmlNodePtr) malloc(sizeof(xmlNode));
|
||||
if (ret == NULL) {
|
||||
fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ret->type = node->type;
|
||||
ret->doc = doc;
|
||||
ret->parent = parent;
|
||||
ret->next = NULL;
|
||||
ret->prev = NULL;
|
||||
ret->childs = NULL;
|
||||
ret->properties = NULL;
|
||||
if (node->name != NULL)
|
||||
ret->name = xmlStrdup(node->name);
|
||||
else
|
||||
ret->name = NULL;
|
||||
ret->ns = NULL;
|
||||
ret->nsDef = NULL;
|
||||
if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
|
||||
ret->content = xmlStrdup(node->content);
|
||||
else
|
||||
ret->content = NULL;
|
||||
#ifndef WITHOUT_CORBA
|
||||
ret->_private = NULL;
|
||||
ret->vepv = NULL;
|
||||
#endif
|
||||
if (parent != NULL)
|
||||
xmlAddChild(parent, ret);
|
||||
|
||||
if (!recursive) return(ret);
|
||||
if (node->properties != NULL)
|
||||
ret->properties = xmlCopyPropList(node->properties);
|
||||
if (node->nsDef != NULL)
|
||||
ret->nsDef = xmlCopyNamespaceList(node->nsDef);
|
||||
|
||||
if (node->ns != NULL) {
|
||||
xmlNsPtr ns;
|
||||
|
||||
ns = xmlSearchNs(doc, ret, node->ns->prefix);
|
||||
if (ns == NULL) {
|
||||
/*
|
||||
* Humm, we are copying an element whose namespace is defined
|
||||
* out of the new tree scope. Search it in the original tree
|
||||
* and add it at the top of the new tree
|
||||
*/
|
||||
ns = xmlSearchNs(node->doc, node, node->ns->prefix);
|
||||
if (ns != NULL) {
|
||||
xmlNodePtr root = ret;
|
||||
|
||||
while (root->parent != NULL) root = root->parent;
|
||||
xmlNewNs(root, ns->href, ns->prefix);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* reference the existing namespace definition in our own tree.
|
||||
*/
|
||||
ret->ns = ns;
|
||||
}
|
||||
}
|
||||
if (node->childs != NULL)
|
||||
ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static xmlNodePtr
|
||||
xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
|
||||
xmlNodePtr ret = NULL;
|
||||
xmlNodePtr p = NULL,q;
|
||||
|
||||
while (node != NULL) {
|
||||
q = xmlStaticCopyNode(node, doc, parent, 1);
|
||||
if (parent == NULL) {
|
||||
if (ret == NULL) ret = q;
|
||||
} else {
|
||||
if (ret == NULL) {
|
||||
q->prev = NULL;
|
||||
ret = p = q;
|
||||
} else {
|
||||
p->next = q;
|
||||
q->prev = p;
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlCopyNode:
|
||||
* @node: the node
|
||||
* @recursive: if 1 do a recursive copy.
|
||||
*
|
||||
* Do a copy of the node.
|
||||
*
|
||||
* Returns: a new xmlNodePtr, or NULL in case of error.
|
||||
*/
|
||||
xmlNodePtr
|
||||
xmlCopyNode(xmlNodePtr node, int recursive) {
|
||||
xmlNodePtr ret;
|
||||
|
||||
ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlCopyNodeList:
|
||||
* @node: the first node in the list.
|
||||
*
|
||||
* Do a recursive copy of the node list.
|
||||
*
|
||||
* Returns: a new xmlNodePtr, or NULL in case of error.
|
||||
*/
|
||||
xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
|
||||
xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlCopyElement:
|
||||
* @elem: the element
|
||||
*
|
||||
* Do a copy of the element definition.
|
||||
*
|
||||
* Returns: a new xmlElementPtr, or NULL in case of error.
|
||||
xmlElementPtr
|
||||
xmlCopyElement(xmlElementPtr elem) {
|
||||
xmlElementPtr ret;
|
||||
|
||||
if (elem == NULL) return(NULL);
|
||||
ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
|
||||
if (ret == NULL) return(NULL);
|
||||
if (!recursive) return(ret);
|
||||
if (elem->properties != NULL)
|
||||
ret->properties = xmlCopyPropList(elem->properties);
|
||||
|
||||
if (elem->nsDef != NULL)
|
||||
ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
|
||||
if (elem->childs != NULL)
|
||||
ret->childs = xmlCopyElementList(elem->childs);
|
||||
return(ret);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* xmlCopyDtd:
|
||||
* @dtd: the dtd
|
||||
*
|
||||
* Do a copy of the dtd.
|
||||
*
|
||||
* Returns: a new xmlDtdPtr, or NULL in case of error.
|
||||
*/
|
||||
xmlDtdPtr
|
||||
xmlCopyDtd(xmlDtdPtr dtd) {
|
||||
xmlDtdPtr ret;
|
||||
|
||||
if (dtd == NULL) return(NULL);
|
||||
ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
|
||||
if (ret == NULL) return(NULL);
|
||||
if (dtd->entities != NULL)
|
||||
ret->entities = (void *) xmlCopyEntitiesTable(
|
||||
(xmlEntitiesTablePtr) dtd->entities);
|
||||
/*
|
||||
* TODO: support for Element definitions.
|
||||
*/
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlCopyDoc:
|
||||
* @doc: the document
|
||||
* @recursive: if 1 do a recursive copy.
|
||||
*
|
||||
* Do a copy of the document info. If recursive, the content tree will
|
||||
* be copied too as well as Dtd, namespaces and entities.
|
||||
*
|
||||
* Returns: a new xmlDocPtr, or NULL in case of error.
|
||||
*/
|
||||
xmlDocPtr
|
||||
xmlCopyDoc(xmlDocPtr doc, int recursive) {
|
||||
xmlDocPtr ret;
|
||||
|
||||
if (doc == NULL) return(NULL);
|
||||
ret = xmlNewDoc(doc->version);
|
||||
if (ret == NULL) return(NULL);
|
||||
if (doc->name != NULL)
|
||||
ret->name = strdup(doc->name);
|
||||
if (doc->encoding != NULL)
|
||||
ret->encoding = xmlStrdup(doc->encoding);
|
||||
ret->compression = doc->compression;
|
||||
ret->standalone = doc->standalone;
|
||||
if (!recursive) return(ret);
|
||||
|
||||
if (doc->dtd != NULL)
|
||||
ret->dtd = xmlCopyDtd(doc->dtd);
|
||||
if (doc->entities != NULL)
|
||||
ret->entities = (void *) xmlCopyEntitiesTable(
|
||||
(xmlEntitiesTablePtr) doc->entities);
|
||||
if (doc->oldNs != NULL)
|
||||
ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
|
||||
if (doc->root != NULL)
|
||||
ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Content access functions *
|
||||
|
10
tree.h
10
tree.h
@ -155,7 +155,7 @@ typedef struct xmlDoc {
|
||||
int standalone; /* standalone document (no external refs) */
|
||||
struct xmlDtd *dtd; /* the document DTD if available */
|
||||
struct xmlNs *oldNs; /* Global namespace, the old way */
|
||||
void *entities; /* Hash table for general entities if any */
|
||||
void *entities; /* Hash table for general entities if any */
|
||||
struct xmlNode *root; /* the document tree */
|
||||
} xmlDoc, *xmlDocPtr;
|
||||
|
||||
@ -183,6 +183,10 @@ extern xmlAttrPtr xmlNewProp(xmlNodePtr node, const CHAR *name,
|
||||
const CHAR *value);
|
||||
extern void xmlFreePropList(xmlAttrPtr cur);
|
||||
extern void xmlFreeProp(xmlAttrPtr cur);
|
||||
extern xmlAttrPtr xmlCopyProp(xmlAttrPtr cur);
|
||||
extern xmlAttrPtr xmlCopyPropList(xmlAttrPtr cur);
|
||||
extern xmlDtdPtr xmlCopyDtd(xmlDtdPtr dtd);
|
||||
extern xmlDocPtr xmlCopyDoc(xmlDocPtr doc, int recursive);
|
||||
|
||||
/*
|
||||
* Creating new nodes
|
||||
@ -199,6 +203,8 @@ extern xmlNodePtr xmlNewTextLen(const CHAR *content, int len);
|
||||
extern xmlNodePtr xmlNewDocComment(xmlDocPtr doc, CHAR *content);
|
||||
extern xmlNodePtr xmlNewComment(CHAR *content);
|
||||
extern xmlNodePtr xmlNewReference(xmlDocPtr doc, const CHAR *name);
|
||||
extern xmlNodePtr xmlCopyNode(xmlNodePtr node, int recursive);
|
||||
extern xmlNodePtr xmlCopyNodeList(xmlNodePtr node);
|
||||
|
||||
/*
|
||||
* Navigating
|
||||
@ -226,6 +232,8 @@ extern xmlNsPtr xmlSearchNs(xmlDocPtr doc, xmlNodePtr node,
|
||||
extern xmlNsPtr xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node,
|
||||
const CHAR *href);
|
||||
extern void xmlSetNs(xmlNodePtr node, xmlNsPtr ns);
|
||||
extern xmlNsPtr xmlCopyNamespace(xmlNsPtr cur);
|
||||
extern xmlNsPtr xmlCopyNamespaceList(xmlNsPtr cur);
|
||||
|
||||
/*
|
||||
* Changing the content.
|
||||
|
Loading…
Reference in New Issue
Block a user