#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
#undef XmlGetInternalEncodingNS
#define XmlGetInternalEncodingNS XmlGetInternalEncoding
+#define XmlParseXmlDeclNS XmlParseXmlDecl
#endif
#define INIT_BLOCK_SIZE 1024
#define INIT_BUFFER_SIZE 1024
+#define EXPAND_SPARE 24
+
+typedef struct binding {
+ struct prefix *prefix;
+ struct binding *nextTagBinding;
+ struct binding *prevPrefixBinding;
+ const struct attribute_id *attId;
+ XML_Char *uri;
+ int uriLen;
+ int uriAlloc;
+} BINDING;
+
+typedef struct prefix {
+ const XML_Char *name;
+ BINDING *binding;
+} PREFIX;
+
typedef struct tag {
struct tag *parent;
const char *rawName;
const XML_Char *name;
char *buf;
char *bufEnd;
+ BINDING *bindings;
} TAG;
typedef struct {
/* The XML_Char before the name is used to determine whether
an attribute has been specified. */
-typedef struct {
+typedef struct attribute_id {
XML_Char *name;
+ PREFIX *prefix;
char maybeTokenized;
+ char xmlns;
} ATTRIBUTE_ID;
typedef struct {
typedef struct {
const XML_Char *name;
+ PREFIX *prefix;
int nDefaultAtts;
int allocDefaultAtts;
DEFAULT_ATTRIBUTE *defaultAtts;
HASH_TABLE generalEntities;
HASH_TABLE elementTypes;
HASH_TABLE attributeIds;
+ HASH_TABLE prefixes;
STRING_POOL pool;
int complete;
int standalone;
const XML_Char *base;
+ PREFIX defaultPrefix;
} DTD;
typedef enum XML_Error Processor(XML_Parser parser,
const char *start, const char *end, const char **endPtr);
static enum XML_Error
doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
-static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const XML_Char *tagName, const char *s);
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s,
+ const XML_Char **tagNamePtr, BINDING **bindingsPtr);
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr);
static int
defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, const XML_Char *dfltValue);
static enum XML_Error
STRING_POOL *);
static ATTRIBUTE_ID *
getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
static enum XML_Error
storeEntityValue(XML_Parser parser, const char *start, const char *end);
static int
static void
reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
-static const XML_Char *getOpenEntityNames(XML_Parser parser);
-static int setOpenEntityNames(XML_Parser parser, const XML_Char *openEntityNames);
+static const XML_Char *getContext(XML_Parser parser);
+static int setContext(XML_Parser parser, const XML_Char *context);
static void normalizePublicId(XML_Char *s);
static int dtdInit(DTD *);
static void dtdDestroy(DTD *);
const ENCODING *encoding;
INIT_ENCODING initEncoding;
const XML_Char *protocolEncodingName;
-#ifdef XMLNS
int ns;
-#endif
void *unknownEncodingMem;
void *unknownEncodingData;
void *unknownEncodingHandlerData;
DTD dtd;
TAG *tagStack;
TAG *freeTagList;
+ BINDING *inheritedBindings;
+ BINDING *freeBindingList;
int attsSize;
ATTRIBUTE *atts;
POSITION position;
char *groupConnector;
unsigned groupSize;
int hadExternalDoctype;
+ XML_Char namespaceSeparator;
} Parser;
#define userData (((Parser *)parser)->userData)
(((Parser *)parser)->unknownEncodingHandlerData)
#define unknownEncodingRelease (((Parser *)parser)->unknownEncodingRelease)
#define protocolEncodingName (((Parser *)parser)->protocolEncodingName)
-#ifdef XMLNS
#define ns (((Parser *)parser)->ns)
-#else
-#define ns (0)
-#endif
#define prologState (((Parser *)parser)->prologState)
#define processor (((Parser *)parser)->processor)
#define errorCode (((Parser *)parser)->errorCode)
#define declAttributeId (((Parser *)parser)->declAttributeId)
#define declAttributeIsCdata (((Parser *)parser)->declAttributeIsCdata)
#define freeTagList (((Parser *)parser)->freeTagList)
+#define freeBindingList (((Parser *)parser)->freeBindingList)
+#define inheritedBindings (((Parser *)parser)->inheritedBindings)
#define tagStack (((Parser *)parser)->tagStack)
#define atts (((Parser *)parser)->atts)
#define attsSize (((Parser *)parser)->attsSize)
#define groupConnector (((Parser *)parser)->groupConnector)
#define groupSize (((Parser *)parser)->groupSize)
#define hadExternalDoctype (((Parser *)parser)->hadExternalDoctype)
+#define namespaceSeparator (((Parser *)parser)->namespaceSeparator)
XML_Parser XML_ParserCreate(const XML_Char *encodingName)
{
tagLevel = 0;
tagStack = 0;
freeTagList = 0;
+ freeBindingList = 0;
+ inheritedBindings = 0;
attsSize = INIT_ATTS_SIZE;
atts = malloc(attsSize * sizeof(ATTRIBUTE));
dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
unknownEncodingRelease = 0;
unknownEncodingData = 0;
unknownEncodingHandlerData = 0;
-#ifdef XMLNS
+ namespaceSeparator = '!';
ns = 0;
-#endif
poolInit(&tempPool);
poolInit(&temp2Pool);
protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0;
return parser;
}
-#ifdef XMLNS
-
-XML_Parser XML_ParserCreateNS(const XML_Char *encodingName)
+XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
{
XML_Parser parser = XML_ParserCreate(encodingName);
if (parser) {
XmlInitEncodingNS(&initEncoding, &encoding, 0);
ns = 1;
+ namespaceSeparator = nsSep;
}
return parser;
}
-#endif
-
XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser,
- const XML_Char *openEntityNames,
+ const XML_Char *context,
const XML_Char *encodingName)
{
XML_Parser parser = oldParser;
void *oldUserData = userData;
void *oldHandlerArg = handlerArg;
- parser = (ns ? XML_ParserCreateNS : XML_ParserCreate)(encodingName);
+ parser = (ns
+ ? XML_ParserCreateNS(encodingName, namespaceSeparator)
+ : XML_ParserCreate(encodingName));
if (!parser)
return 0;
startElementHandler = oldStartElementHandler;
handlerArg = userData;
else
handlerArg = parser;
- if (!dtdCopy(&dtd, oldDtd) || !setOpenEntityNames(parser, openEntityNames)) {
+ if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) {
XML_ParserFree(parser);
return 0;
}
return parser;
}
+static
+void destroyBindings(BINDING *bindings)
+{
+ for (;;) {
+ BINDING *b = bindings;
+ if (!b)
+ break;
+ bindings = b->nextTagBinding;
+ free(b->uri);
+ free(b);
+ }
+}
+
void XML_ParserFree(XML_Parser parser)
{
for (;;) {
p = tagStack;
tagStack = tagStack->parent;
free(p->buf);
+ destroyBindings(p->bindings);
free(p);
}
+ destroyBindings(freeBindingList);
+ destroyBindings(inheritedBindings);
poolDestroy(&tempPool);
poolDestroy(&temp2Pool);
dtdDestroy(&dtd);
return result;
}
else if (externalEntityRefHandler) {
- const XML_Char *openEntityNames;
+ const XML_Char *context;
entity->open = 1;
- openEntityNames = getOpenEntityNames(parser);
+ context = getContext(parser);
entity->open = 0;
- if (!openEntityNames)
+ if (!context)
return XML_ERROR_NO_MEMORY;
- if (!externalEntityRefHandler(parser, openEntityNames, dtd.base, entity->systemId, entity->publicId))
+ if (!externalEntityRefHandler(parser, context, dtd.base, entity->systemId, entity->publicId))
return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
}
else if (defaultHandler)
}
case XML_TOK_START_TAG_WITH_ATTS:
if (!startElementHandler) {
- enum XML_Error result = storeAtts(parser, enc, 0, s);
+ enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
if (result)
return result;
}
return XML_ERROR_NO_MEMORY;
tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
}
+ tag->bindings = 0;
tag->parent = tagStack;
tagStack = tag;
tag->rawName = s + enc->minBytesPerChar;
tag->rawName = tag->buf;
}
*toPtr = XML_T('\0');
- result = storeAtts(parser, enc, tag->name, s);
+ result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
if (result)
return result;
startElementHandler(handlerArg, tag->name, (const XML_Char **)atts);
}
case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
if (!startElementHandler) {
- enum XML_Error result = storeAtts(parser, enc, 0, s);
+ enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
if (result)
return result;
}
case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
if (startElementHandler || endElementHandler) {
const char *rawName = s + enc->minBytesPerChar;
+ enum XML_Error result;
+ BINDING *bindings = 0;
const XML_Char *name = poolStoreString(&tempPool, enc, rawName,
rawName
+ XmlNameLength(enc, rawName));
if (!name)
return XML_ERROR_NO_MEMORY;
poolFinish(&tempPool);
- if (startElementHandler) {
- enum XML_Error result = storeAtts(parser, enc, name, s);
- if (result)
- return result;
+ result = storeAtts(parser, enc, s, &name, &bindings);
+ if (result)
+ return result;
+ poolFinish(&tempPool);
+ if (startElementHandler)
startElementHandler(handlerArg, name, (const XML_Char **)atts);
- }
if (endElementHandler) {
if (startElementHandler)
*eventEndPP = *eventPP;
endElementHandler(handlerArg, name);
}
poolClear(&tempPool);
+ while (bindings) {
+ BINDING *b = bindings;
+ bindings = bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
}
else if (defaultHandler)
reportDefault(parser, enc, s, next);
return XML_ERROR_TAG_MISMATCH;
}
--tagLevel;
- if (endElementHandler) {
- if (tag->name)
- endElementHandler(handlerArg, tag->name);
- else {
- const XML_Char *name = poolStoreString(&tempPool, enc, rawName,
- rawName + len);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- endElementHandler(handlerArg, name);
- poolClear(&tempPool);
- }
- }
+ if (endElementHandler && tag->name)
+ endElementHandler(handlerArg, tag->name);
else if (defaultHandler)
reportDefault(parser, enc, s, next);
+ while (tag->bindings) {
+ BINDING *b = tag->bindings;
+ tag->bindings = tag->bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
if (tagLevel == 0)
return epilogProcessor(parser, next, end, nextPtr);
}
/* not reached */
}
-/* If tagName is non-null, build a real list of attributes,
+/* If tagNamePtr is non-null, build a real list of attributes,
otherwise just check the attributes for well-formedness. */
static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
- const XML_Char *tagName, const char *s)
+ const char *s, const XML_Char **tagNamePtr,
+ BINDING **bindingsPtr)
{
ELEMENT_TYPE *elementType = 0;
int nDefaultAtts = 0;
const XML_Char **appAtts;
+ int attIndex = 0;
int i;
int n;
-
- if (tagName) {
- elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagName, 0);
- if (elementType)
- nDefaultAtts = elementType->nDefaultAtts;
+ int nPrefixes = 0;
+ BINDING *binding;
+ const XML_Char *localPart;
+
+ if (tagNamePtr) {
+ elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, *tagNamePtr, 0);
+ if (!elementType) {
+ *tagNamePtr = poolCopyString(&dtd.pool, *tagNamePtr);
+ if (!*tagNamePtr)
+ return XML_ERROR_NO_MEMORY;
+ elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, *tagNamePtr, sizeof(ELEMENT_TYPE));
+ if (!elementType)
+ return XML_ERROR_NO_MEMORY;
+ if (ns && !setElementTypePrefix(parser, elementType))
+ return XML_ERROR_NO_MEMORY;
+ }
+ nDefaultAtts = elementType->nDefaultAtts;
}
-
n = XmlGetAttributes(enc, s, attsSize, atts);
if (n + nDefaultAtts > attsSize) {
int oldAttsSize = attsSize;
appAtts = (const XML_Char **)atts;
for (i = 0; i < n; i++) {
ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
- atts[i].name
- + XmlNameLength(enc, atts[i].name));
+ atts[i].name
+ + XmlNameLength(enc, atts[i].name));
if (!attId)
return XML_ERROR_NO_MEMORY;
if ((attId->name)[-1]) {
return XML_ERROR_DUPLICATE_ATTRIBUTE;
}
(attId->name)[-1] = 1;
- appAtts[i << 1] = attId->name;
+ appAtts[attIndex++] = attId->name;
if (!atts[i].normalized) {
enum XML_Error result;
int isCdata = 1;
&tempPool);
if (result)
return result;
- if (tagName) {
- appAtts[(i << 1) + 1] = poolStart(&tempPool);
+ if (tagNamePtr) {
+ appAtts[attIndex] = poolStart(&tempPool);
poolFinish(&tempPool);
}
else
poolDiscard(&tempPool);
}
- else if (tagName) {
- appAtts[(i << 1) + 1] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
- if (appAtts[(i << 1) + 1] == 0)
+ else if (tagNamePtr) {
+ appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
+ if (appAtts[attIndex] == 0)
return XML_ERROR_NO_MEMORY;
poolFinish(&tempPool);
}
+ if (attId->prefix && tagNamePtr) {
+ if (attId->xmlns) {
+ if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr))
+ return XML_ERROR_NO_MEMORY;
+ --attIndex;
+ }
+ else {
+ attIndex++;
+ nPrefixes++;
+ (attId->name)[-1] = 2;
+ }
+ }
+ else
+ attIndex++;
}
- if (tagName) {
+ if (tagNamePtr) {
int j;
for (j = 0; j < nDefaultAtts; j++) {
const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
if (!(da->id->name)[-1] && da->value) {
- (da->id->name)[-1] = 1;
- appAtts[i << 1] = da->id->name;
- appAtts[(i << 1) + 1] = da->value;
- i++;
+ if (da->id->prefix) {
+ if (da->id->xmlns) {
+ if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr))
+ return XML_ERROR_NO_MEMORY;
+ }
+ else {
+ (da->id->name)[-1] = 2;
+ nPrefixes++;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ else {
+ (da->id->name)[-1] = 1;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
}
}
- appAtts[i << 1] = 0;
+ appAtts[attIndex] = 0;
+ }
+ i = 0;
+ if (nPrefixes) {
+ for (; i < attIndex; i += 2) {
+ if (appAtts[i][-1] == 2) {
+ ATTRIBUTE_ID *id;
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
+ if (id->prefix->binding) {
+ int j;
+ const BINDING *b = id->prefix->binding;
+ const XML_Char *s = appAtts[i];
+ for (j = 0; j < b->uriLen; j++) {
+ if (!poolAppendChar(&tempPool, b->uri[j]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ while (*s++ != ':')
+ ;
+ do {
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_ERROR_NO_MEMORY;
+ } while (*s++);
+ appAtts[i] = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ }
+ if (!--nPrefixes)
+ break;
+ }
+ else
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ }
}
- while (i-- > 0)
- ((XML_Char *)appAtts[i << 1])[-1] = 0;
+ for (; i < attIndex; i += 2)
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ if (!tagNamePtr)
+ return XML_ERROR_NONE;
+ for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
+ binding->attId->name[-1] = 0;
+ if (elementType->prefix) {
+ binding = elementType->prefix->binding;
+ if (!binding)
+ return XML_ERROR_NONE;
+ localPart = *tagNamePtr;
+ while (*localPart++ != XML_T(':'))
+ ;
+ }
+ else if (dtd.defaultPrefix.binding) {
+ binding = dtd.defaultPrefix.binding;
+ localPart = *tagNamePtr;
+ }
+ else
+ return XML_ERROR_NONE;
+ i = binding->uriLen;
+ do {
+ if (i == binding->uriAlloc) {
+ binding->uri = realloc(binding->uri, binding->uriAlloc *= 2);
+ if (!binding->uri)
+ return XML_ERROR_NO_MEMORY;
+ }
+ binding->uri[i++] = *localPart;
+ } while (*localPart++);
+ *tagNamePtr = binding->uri;
return XML_ERROR_NONE;
}
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr)
+{
+ BINDING *b;
+ int len;
+ for (len = 0; uri[len]; len++)
+ ;
+ if (namespaceSeparator)
+ len++;
+ if (freeBindingList) {
+ b = freeBindingList;
+ if (len > b->uriAlloc) {
+ b->uri = realloc(b->uri, len + EXPAND_SPARE);
+ if (!b->uri)
+ return 0;
+ b->uriAlloc = len + EXPAND_SPARE;
+ }
+ freeBindingList = b->nextTagBinding;
+ }
+ else {
+ b = malloc(sizeof(BINDING));
+ if (!b)
+ return 0;
+ b->uri = malloc(sizeof(XML_Char) * len + EXPAND_SPARE);
+ if (!b->uri) {
+ free(b);
+ return 0;
+ }
+ b->uriAlloc = len;
+ }
+ b->uriLen = len;
+ memcpy(b->uri, uri, len * sizeof(XML_Char));
+ if (namespaceSeparator)
+ b->uri[len - 1] = namespaceSeparator;
+ b->prefix = prefix;
+ b->attId = attId;
+ b->prevPrefixBinding = b->prefix->binding;
+ b->prefix->binding = *uri == XML_T('\0') ? 0 : b;
+ b->nextTagBinding = *bindingsPtr;
+ *bindingsPtr = b;
+ return 1;
+}
+
/* The idea here is to avoid using stack for each CDATA section when
the whole file is parsed with one call. */
return XML_ERROR_NO_MEMORY;
if (declElementType->name != name)
poolDiscard(&dtd.pool);
- else
+ else {
poolFinish(&dtd.pool);
+ if (!setElementTypePrefix(parser, declElementType))
+ return XML_ERROR_NO_MEMORY;
+ }
break;
}
case XML_ROLE_ATTRIBUTE_NAME:
return 1;
}
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
+{
+ const XML_Char *name;
+ for (name = elementType->name; *name; name++) {
+ if (*name == XML_T(':')) {
+ PREFIX *prefix;
+ const XML_Char *s;
+ for (s = elementType->name; s != name; s++) {
+ if (!poolAppendChar(&dtd.pool, *s))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&dtd.pool))
+ poolFinish(&dtd.pool);
+ else
+ poolDiscard(&dtd.pool);
+ elementType->prefix = prefix;
+
+ }
+ }
+ return 1;
+}
+
static ATTRIBUTE_ID *
getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
{
return 0;
if (id->name != name)
poolDiscard(&dtd.pool);
- else
+ else {
poolFinish(&dtd.pool);
+ if (!ns)
+ ;
+ else if (name[0] == 'x'
+ && name[1] == 'm'
+ && name[2] == 'l'
+ && name[3] == 'n'
+ && name[4] == 's'
+ && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
+ if (name[5] == '\0')
+ id->prefix = &dtd.defaultPrefix;
+ else
+ id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
+ id->xmlns = 1;
+ }
+ else {
+ int i;
+ for (i = 0; name[i]; i++) {
+ if (name[i] == XML_T(':')) {
+ int j;
+ for (j = 0; j < i; j++) {
+ if (!poolAppendChar(&dtd.pool, name[j]))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+ if (id->prefix->name == poolStart(&dtd.pool))
+ poolFinish(&dtd.pool);
+ else
+ poolDiscard(&dtd.pool);
+ break;
+ }
+ }
+ }
+ }
return id;
}
+#define CONTEXT_SEP XML_T('\f')
+
static
-const XML_Char *getOpenEntityNames(XML_Parser parser)
+const XML_Char *getContext(XML_Parser parser)
{
HASH_TABLE_ITER iter;
+ int needSep = 0;
+
+ if (dtd.defaultPrefix.binding) {
+ int i;
+ int len;
+ if (!poolAppendChar(&tempPool, XML_T('=')))
+ return 0;
+ len = dtd.defaultPrefix.binding->uriLen;
+ if (namespaceSeparator != XML_T('\0'))
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
+ return 0;
+ needSep = 1;
+ }
+
+ hashTableIterInit(&iter, &(dtd.prefixes));
+ for (;;) {
+ int i;
+ int len;
+ const XML_Char *s;
+ PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
+ if (!prefix)
+ break;
+ if (!prefix->binding)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return 0;
+ for (s = prefix->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ if (!poolAppendChar(&tempPool, XML_T('=')))
+ return 0;
+ len = prefix->binding->uriLen;
+ if (namespaceSeparator != XML_T('\0'))
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
+ return 0;
+ needSep = 1;
+ }
+
hashTableIterInit(&iter, &(dtd.generalEntities));
for (;;) {
break;
if (!e->open)
continue;
- if (poolLength(&tempPool) > 0 && !poolAppendChar(&tempPool, XML_T(' ')))
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
return 0;
for (s = e->name; *s; s++)
if (!poolAppendChar(&tempPool, *s))
return 0;
+ needSep = 1;
}
if (!poolAppendChar(&tempPool, XML_T('\0')))
}
static
-int setOpenEntityNames(XML_Parser parser, const XML_Char *openEntityNames)
+int setContext(XML_Parser parser, const XML_Char *context)
{
- const XML_Char *s = openEntityNames;
- while (*openEntityNames != XML_T('\0')) {
- if (*s == XML_T(' ') || *s == XML_T('\0')) {
+ const XML_Char *s = context;
+
+ while (*context != XML_T('\0')) {
+ if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
ENTITY *e;
if (!poolAppendChar(&tempPool, XML_T('\0')))
return 0;
e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0);
if (e)
e->open = 1;
- if (*s == XML_T(' '))
+ if (*s != XML_T('\0'))
s++;
- openEntityNames = s;
+ context = s;
+ poolDiscard(&tempPool);
+ }
+ else if (*s == '=') {
+ PREFIX *prefix;
+ if (poolLength(&tempPool) == 0)
+ prefix = &dtd.defaultPrefix;
+ else {
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&tempPool))
+ poolFinish(&tempPool);
+ else
+ poolDiscard(&tempPool);
+ }
+ for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++)
+ if (!poolAppendChar(&tempPool, *context))
+ return 0;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ if (!addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings))
+ return 0;
poolDiscard(&tempPool);
+ if (*context != XML_T('\0'))
+ ++context;
+ s = context;
}
else {
if (!poolAppendChar(&tempPool, *s))
hashTableInit(&(p->generalEntities));
hashTableInit(&(p->elementTypes));
hashTableInit(&(p->attributeIds));
+ hashTableInit(&(p->prefixes));
p->complete = 1;
p->base = 0;
+ p->defaultPrefix.name = 0;
+ p->defaultPrefix.binding = 0;
return 1;
}
hashTableDestroy(&(p->generalEntities));
hashTableDestroy(&(p->elementTypes));
hashTableDestroy(&(p->attributeIds));
+ hashTableDestroy(&(p->prefixes));
poolDestroy(&(p->pool));
}
newDtd->base = tem;
}
+ /* Copy the prefix table. */
+
+ hashTableIterInit(&iter, &(oldDtd->prefixes));
+ for (;;) {
+ const XML_Char *name;
+ const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
+ if (!oldP)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldP->name);
+ if (!name)
+ return 0;
+ if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
+ return 0;
+ }
+
hashTableIterInit(&iter, &(oldDtd->attributeIds));
/* Copy the attribute id table. */
if (!newA)
return 0;
newA->maybeTokenized = oldA->maybeTokenized;
+ if (oldA->prefix) {
+ newA->xmlns = oldA->xmlns;
+ if (oldA->prefix == &oldDtd->defaultPrefix)
+ newA->prefix = &newDtd->defaultPrefix;
+ else
+ newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldA->prefix->name, 0);
+ }
}
/* Copy the element type table. */
newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
if (!newE)
return 0;
- newE->defaultAtts = (DEFAULT_ATTRIBUTE *)malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
- if (!newE->defaultAtts)
- return 0;
+ if (oldE->nDefaultAtts) {
+ newE->defaultAtts = (DEFAULT_ATTRIBUTE *)malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+ if (!newE->defaultAtts)
+ return 0;
+ }
newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
+ if (oldE->prefix)
+ newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldE->prefix->name, 0);
for (i = 0; i < newE->nDefaultAtts; i++) {
newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;