1*7c568831SAndroid Build Coastguard Worker /*
2*7c568831SAndroid Build Coastguard Worker * valid.c : part of the code use to do the DTD handling and the validity
3*7c568831SAndroid Build Coastguard Worker * checking
4*7c568831SAndroid Build Coastguard Worker *
5*7c568831SAndroid Build Coastguard Worker * See Copyright for the status of this software.
6*7c568831SAndroid Build Coastguard Worker *
7*7c568831SAndroid Build Coastguard Worker * [email protected]
8*7c568831SAndroid Build Coastguard Worker */
9*7c568831SAndroid Build Coastguard Worker
10*7c568831SAndroid Build Coastguard Worker #define IN_LIBXML
11*7c568831SAndroid Build Coastguard Worker #include "libxml.h"
12*7c568831SAndroid Build Coastguard Worker
13*7c568831SAndroid Build Coastguard Worker #include <string.h>
14*7c568831SAndroid Build Coastguard Worker #include <stdlib.h>
15*7c568831SAndroid Build Coastguard Worker
16*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
17*7c568831SAndroid Build Coastguard Worker #include <libxml/hash.h>
18*7c568831SAndroid Build Coastguard Worker #include <libxml/uri.h>
19*7c568831SAndroid Build Coastguard Worker #include <libxml/valid.h>
20*7c568831SAndroid Build Coastguard Worker #include <libxml/parser.h>
21*7c568831SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
22*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
23*7c568831SAndroid Build Coastguard Worker #include <libxml/list.h>
24*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlsave.h>
25*7c568831SAndroid Build Coastguard Worker
26*7c568831SAndroid Build Coastguard Worker #include "private/error.h"
27*7c568831SAndroid Build Coastguard Worker #include "private/parser.h"
28*7c568831SAndroid Build Coastguard Worker #include "private/regexp.h"
29*7c568831SAndroid Build Coastguard Worker #include "private/save.h"
30*7c568831SAndroid Build Coastguard Worker #include "private/tree.h"
31*7c568831SAndroid Build Coastguard Worker
32*7c568831SAndroid Build Coastguard Worker static xmlElementPtr
33*7c568831SAndroid Build Coastguard Worker xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name);
34*7c568831SAndroid Build Coastguard Worker
35*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
36*7c568831SAndroid Build Coastguard Worker static int
37*7c568831SAndroid Build Coastguard Worker xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
38*7c568831SAndroid Build Coastguard Worker const xmlChar *value);
39*7c568831SAndroid Build Coastguard Worker #endif
40*7c568831SAndroid Build Coastguard Worker /************************************************************************
41*7c568831SAndroid Build Coastguard Worker * *
42*7c568831SAndroid Build Coastguard Worker * Error handling routines *
43*7c568831SAndroid Build Coastguard Worker * *
44*7c568831SAndroid Build Coastguard Worker ************************************************************************/
45*7c568831SAndroid Build Coastguard Worker
46*7c568831SAndroid Build Coastguard Worker /**
47*7c568831SAndroid Build Coastguard Worker * xmlVErrMemory:
48*7c568831SAndroid Build Coastguard Worker * @ctxt: an XML validation parser context
49*7c568831SAndroid Build Coastguard Worker * @extra: extra information
50*7c568831SAndroid Build Coastguard Worker *
51*7c568831SAndroid Build Coastguard Worker * Handle an out of memory error
52*7c568831SAndroid Build Coastguard Worker */
53*7c568831SAndroid Build Coastguard Worker static void
xmlVErrMemory(xmlValidCtxtPtr ctxt)54*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(xmlValidCtxtPtr ctxt)
55*7c568831SAndroid Build Coastguard Worker {
56*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL) {
57*7c568831SAndroid Build Coastguard Worker if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
58*7c568831SAndroid Build Coastguard Worker xmlCtxtErrMemory(ctxt->userData);
59*7c568831SAndroid Build Coastguard Worker } else {
60*7c568831SAndroid Build Coastguard Worker xmlRaiseMemoryError(NULL, ctxt->error, ctxt->userData,
61*7c568831SAndroid Build Coastguard Worker XML_FROM_VALID, NULL);
62*7c568831SAndroid Build Coastguard Worker }
63*7c568831SAndroid Build Coastguard Worker } else {
64*7c568831SAndroid Build Coastguard Worker xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_VALID, NULL);
65*7c568831SAndroid Build Coastguard Worker }
66*7c568831SAndroid Build Coastguard Worker }
67*7c568831SAndroid Build Coastguard Worker
68*7c568831SAndroid Build Coastguard Worker static void
xmlDoErrValid(xmlValidCtxtPtr ctxt,xmlNodePtr node,xmlParserErrors code,int level,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,int int1,const char * msg,...)69*7c568831SAndroid Build Coastguard Worker xmlDoErrValid(xmlValidCtxtPtr ctxt, xmlNodePtr node,
70*7c568831SAndroid Build Coastguard Worker xmlParserErrors code, int level,
71*7c568831SAndroid Build Coastguard Worker const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
72*7c568831SAndroid Build Coastguard Worker int int1,
73*7c568831SAndroid Build Coastguard Worker const char *msg, ...) {
74*7c568831SAndroid Build Coastguard Worker xmlParserCtxtPtr pctxt = NULL;
75*7c568831SAndroid Build Coastguard Worker va_list ap;
76*7c568831SAndroid Build Coastguard Worker
77*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
78*7c568831SAndroid Build Coastguard Worker return;
79*7c568831SAndroid Build Coastguard Worker if (ctxt->flags & XML_VCTXT_USE_PCTXT)
80*7c568831SAndroid Build Coastguard Worker pctxt = ctxt->userData;
81*7c568831SAndroid Build Coastguard Worker
82*7c568831SAndroid Build Coastguard Worker va_start(ap, msg);
83*7c568831SAndroid Build Coastguard Worker if (pctxt != NULL) {
84*7c568831SAndroid Build Coastguard Worker xmlCtxtVErr(pctxt, node, XML_FROM_VALID, code, level,
85*7c568831SAndroid Build Coastguard Worker str1, str2, str3, int1, msg, ap);
86*7c568831SAndroid Build Coastguard Worker } else {
87*7c568831SAndroid Build Coastguard Worker xmlGenericErrorFunc channel = NULL;
88*7c568831SAndroid Build Coastguard Worker void *data = NULL;
89*7c568831SAndroid Build Coastguard Worker int res;
90*7c568831SAndroid Build Coastguard Worker
91*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL) {
92*7c568831SAndroid Build Coastguard Worker channel = ctxt->error;
93*7c568831SAndroid Build Coastguard Worker data = ctxt->userData;
94*7c568831SAndroid Build Coastguard Worker }
95*7c568831SAndroid Build Coastguard Worker res = xmlVRaiseError(NULL, channel, data, NULL, node,
96*7c568831SAndroid Build Coastguard Worker XML_FROM_VALID, code, level, NULL, 0,
97*7c568831SAndroid Build Coastguard Worker (const char *) str1, (const char *) str2,
98*7c568831SAndroid Build Coastguard Worker (const char *) str2, int1, 0,
99*7c568831SAndroid Build Coastguard Worker msg, ap);
100*7c568831SAndroid Build Coastguard Worker if (res < 0)
101*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
102*7c568831SAndroid Build Coastguard Worker }
103*7c568831SAndroid Build Coastguard Worker va_end(ap);
104*7c568831SAndroid Build Coastguard Worker }
105*7c568831SAndroid Build Coastguard Worker
106*7c568831SAndroid Build Coastguard Worker /**
107*7c568831SAndroid Build Coastguard Worker * xmlErrValid:
108*7c568831SAndroid Build Coastguard Worker * @ctxt: an XML validation parser context
109*7c568831SAndroid Build Coastguard Worker * @error: the error number
110*7c568831SAndroid Build Coastguard Worker * @extra: extra information
111*7c568831SAndroid Build Coastguard Worker *
112*7c568831SAndroid Build Coastguard Worker * Handle a validation error
113*7c568831SAndroid Build Coastguard Worker */
114*7c568831SAndroid Build Coastguard Worker static void LIBXML_ATTR_FORMAT(3,0)
xmlErrValid(xmlValidCtxtPtr ctxt,xmlParserErrors error,const char * msg,const char * extra)115*7c568831SAndroid Build Coastguard Worker xmlErrValid(xmlValidCtxtPtr ctxt, xmlParserErrors error,
116*7c568831SAndroid Build Coastguard Worker const char *msg, const char *extra)
117*7c568831SAndroid Build Coastguard Worker {
118*7c568831SAndroid Build Coastguard Worker xmlDoErrValid(ctxt, NULL, error, XML_ERR_ERROR, (const xmlChar *) extra,
119*7c568831SAndroid Build Coastguard Worker NULL, NULL, 0, msg, extra);
120*7c568831SAndroid Build Coastguard Worker }
121*7c568831SAndroid Build Coastguard Worker
122*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
123*7c568831SAndroid Build Coastguard Worker /**
124*7c568831SAndroid Build Coastguard Worker * xmlErrValidNode:
125*7c568831SAndroid Build Coastguard Worker * @ctxt: an XML validation parser context
126*7c568831SAndroid Build Coastguard Worker * @node: the node raising the error
127*7c568831SAndroid Build Coastguard Worker * @error: the error number
128*7c568831SAndroid Build Coastguard Worker * @str1: extra information
129*7c568831SAndroid Build Coastguard Worker * @str2: extra information
130*7c568831SAndroid Build Coastguard Worker * @str3: extra information
131*7c568831SAndroid Build Coastguard Worker *
132*7c568831SAndroid Build Coastguard Worker * Handle a validation error, provide contextual information
133*7c568831SAndroid Build Coastguard Worker */
134*7c568831SAndroid Build Coastguard Worker static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidNode(xmlValidCtxtPtr ctxt,xmlNodePtr node,xmlParserErrors error,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)135*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(xmlValidCtxtPtr ctxt,
136*7c568831SAndroid Build Coastguard Worker xmlNodePtr node, xmlParserErrors error,
137*7c568831SAndroid Build Coastguard Worker const char *msg, const xmlChar * str1,
138*7c568831SAndroid Build Coastguard Worker const xmlChar * str2, const xmlChar * str3)
139*7c568831SAndroid Build Coastguard Worker {
140*7c568831SAndroid Build Coastguard Worker xmlDoErrValid(ctxt, node, error, XML_ERR_ERROR, str1, str2, str3, 0,
141*7c568831SAndroid Build Coastguard Worker msg, str1, str2, str3);
142*7c568831SAndroid Build Coastguard Worker }
143*7c568831SAndroid Build Coastguard Worker
144*7c568831SAndroid Build Coastguard Worker /**
145*7c568831SAndroid Build Coastguard Worker * xmlErrValidNodeNr:
146*7c568831SAndroid Build Coastguard Worker * @ctxt: an XML validation parser context
147*7c568831SAndroid Build Coastguard Worker * @node: the node raising the error
148*7c568831SAndroid Build Coastguard Worker * @error: the error number
149*7c568831SAndroid Build Coastguard Worker * @str1: extra information
150*7c568831SAndroid Build Coastguard Worker * @int2: extra information
151*7c568831SAndroid Build Coastguard Worker * @str3: extra information
152*7c568831SAndroid Build Coastguard Worker *
153*7c568831SAndroid Build Coastguard Worker * Handle a validation error, provide contextual information
154*7c568831SAndroid Build Coastguard Worker */
155*7c568831SAndroid Build Coastguard Worker static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidNodeNr(xmlValidCtxtPtr ctxt,xmlNodePtr node,xmlParserErrors error,const char * msg,const xmlChar * str1,int int2,const xmlChar * str3)156*7c568831SAndroid Build Coastguard Worker xmlErrValidNodeNr(xmlValidCtxtPtr ctxt,
157*7c568831SAndroid Build Coastguard Worker xmlNodePtr node, xmlParserErrors error,
158*7c568831SAndroid Build Coastguard Worker const char *msg, const xmlChar * str1,
159*7c568831SAndroid Build Coastguard Worker int int2, const xmlChar * str3)
160*7c568831SAndroid Build Coastguard Worker {
161*7c568831SAndroid Build Coastguard Worker xmlDoErrValid(ctxt, node, error, XML_ERR_ERROR, str1, str3, NULL, int2,
162*7c568831SAndroid Build Coastguard Worker msg, str1, int2, str3);
163*7c568831SAndroid Build Coastguard Worker }
164*7c568831SAndroid Build Coastguard Worker
165*7c568831SAndroid Build Coastguard Worker /**
166*7c568831SAndroid Build Coastguard Worker * xmlErrValidWarning:
167*7c568831SAndroid Build Coastguard Worker * @ctxt: an XML validation parser context
168*7c568831SAndroid Build Coastguard Worker * @node: the node raising the error
169*7c568831SAndroid Build Coastguard Worker * @error: the error number
170*7c568831SAndroid Build Coastguard Worker * @str1: extra information
171*7c568831SAndroid Build Coastguard Worker * @str2: extra information
172*7c568831SAndroid Build Coastguard Worker * @str3: extra information
173*7c568831SAndroid Build Coastguard Worker *
174*7c568831SAndroid Build Coastguard Worker * Handle a validation error, provide contextual information
175*7c568831SAndroid Build Coastguard Worker */
176*7c568831SAndroid Build Coastguard Worker static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidWarning(xmlValidCtxtPtr ctxt,xmlNodePtr node,xmlParserErrors error,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)177*7c568831SAndroid Build Coastguard Worker xmlErrValidWarning(xmlValidCtxtPtr ctxt,
178*7c568831SAndroid Build Coastguard Worker xmlNodePtr node, xmlParserErrors error,
179*7c568831SAndroid Build Coastguard Worker const char *msg, const xmlChar * str1,
180*7c568831SAndroid Build Coastguard Worker const xmlChar * str2, const xmlChar * str3)
181*7c568831SAndroid Build Coastguard Worker {
182*7c568831SAndroid Build Coastguard Worker xmlDoErrValid(ctxt, node, error, XML_ERR_WARNING, str1, str2, str3, 0,
183*7c568831SAndroid Build Coastguard Worker msg, str1, str2, str3);
184*7c568831SAndroid Build Coastguard Worker }
185*7c568831SAndroid Build Coastguard Worker
186*7c568831SAndroid Build Coastguard Worker
187*7c568831SAndroid Build Coastguard Worker
188*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
189*7c568831SAndroid Build Coastguard Worker /*
190*7c568831SAndroid Build Coastguard Worker * If regexp are enabled we can do continuous validation without the
191*7c568831SAndroid Build Coastguard Worker * need of a tree to validate the content model. this is done in each
192*7c568831SAndroid Build Coastguard Worker * callbacks.
193*7c568831SAndroid Build Coastguard Worker * Each xmlValidState represent the validation state associated to the
194*7c568831SAndroid Build Coastguard Worker * set of nodes currently open from the document root to the current element.
195*7c568831SAndroid Build Coastguard Worker */
196*7c568831SAndroid Build Coastguard Worker
197*7c568831SAndroid Build Coastguard Worker
198*7c568831SAndroid Build Coastguard Worker typedef struct _xmlValidState {
199*7c568831SAndroid Build Coastguard Worker xmlElementPtr elemDecl; /* pointer to the content model */
200*7c568831SAndroid Build Coastguard Worker xmlNodePtr node; /* pointer to the current node */
201*7c568831SAndroid Build Coastguard Worker xmlRegExecCtxtPtr exec; /* regexp runtime */
202*7c568831SAndroid Build Coastguard Worker } _xmlValidState;
203*7c568831SAndroid Build Coastguard Worker
204*7c568831SAndroid Build Coastguard Worker
205*7c568831SAndroid Build Coastguard Worker static int
vstateVPush(xmlValidCtxtPtr ctxt,xmlElementPtr elemDecl,xmlNodePtr node)206*7c568831SAndroid Build Coastguard Worker vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
207*7c568831SAndroid Build Coastguard Worker if ((ctxt->vstateMax == 0) || (ctxt->vstateTab == NULL)) {
208*7c568831SAndroid Build Coastguard Worker ctxt->vstateMax = 10;
209*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax *
210*7c568831SAndroid Build Coastguard Worker sizeof(ctxt->vstateTab[0]));
211*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateTab == NULL) {
212*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
213*7c568831SAndroid Build Coastguard Worker return(-1);
214*7c568831SAndroid Build Coastguard Worker }
215*7c568831SAndroid Build Coastguard Worker }
216*7c568831SAndroid Build Coastguard Worker
217*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateNr >= ctxt->vstateMax) {
218*7c568831SAndroid Build Coastguard Worker xmlValidState *tmp;
219*7c568831SAndroid Build Coastguard Worker
220*7c568831SAndroid Build Coastguard Worker tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
221*7c568831SAndroid Build Coastguard Worker 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
222*7c568831SAndroid Build Coastguard Worker if (tmp == NULL) {
223*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
224*7c568831SAndroid Build Coastguard Worker return(-1);
225*7c568831SAndroid Build Coastguard Worker }
226*7c568831SAndroid Build Coastguard Worker ctxt->vstateMax *= 2;
227*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab = tmp;
228*7c568831SAndroid Build Coastguard Worker }
229*7c568831SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr];
230*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].elemDecl = elemDecl;
231*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].node = node;
232*7c568831SAndroid Build Coastguard Worker if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
233*7c568831SAndroid Build Coastguard Worker if (elemDecl->contModel == NULL)
234*7c568831SAndroid Build Coastguard Worker xmlValidBuildContentModel(ctxt, elemDecl);
235*7c568831SAndroid Build Coastguard Worker if (elemDecl->contModel != NULL) {
236*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].exec =
237*7c568831SAndroid Build Coastguard Worker xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
238*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateTab[ctxt->vstateNr].exec == NULL) {
239*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
240*7c568831SAndroid Build Coastguard Worker return(-1);
241*7c568831SAndroid Build Coastguard Worker }
242*7c568831SAndroid Build Coastguard Worker } else {
243*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
244*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
245*7c568831SAndroid Build Coastguard Worker XML_ERR_INTERNAL_ERROR,
246*7c568831SAndroid Build Coastguard Worker "Failed to build content model regexp for %s\n",
247*7c568831SAndroid Build Coastguard Worker node->name, NULL, NULL);
248*7c568831SAndroid Build Coastguard Worker }
249*7c568831SAndroid Build Coastguard Worker }
250*7c568831SAndroid Build Coastguard Worker return(ctxt->vstateNr++);
251*7c568831SAndroid Build Coastguard Worker }
252*7c568831SAndroid Build Coastguard Worker
253*7c568831SAndroid Build Coastguard Worker static int
vstateVPop(xmlValidCtxtPtr ctxt)254*7c568831SAndroid Build Coastguard Worker vstateVPop(xmlValidCtxtPtr ctxt) {
255*7c568831SAndroid Build Coastguard Worker xmlElementPtr elemDecl;
256*7c568831SAndroid Build Coastguard Worker
257*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateNr < 1) return(-1);
258*7c568831SAndroid Build Coastguard Worker ctxt->vstateNr--;
259*7c568831SAndroid Build Coastguard Worker elemDecl = ctxt->vstateTab[ctxt->vstateNr].elemDecl;
260*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].elemDecl = NULL;
261*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].node = NULL;
262*7c568831SAndroid Build Coastguard Worker if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
263*7c568831SAndroid Build Coastguard Worker xmlRegFreeExecCtxt(ctxt->vstateTab[ctxt->vstateNr].exec);
264*7c568831SAndroid Build Coastguard Worker }
265*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
266*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateNr >= 1)
267*7c568831SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr - 1];
268*7c568831SAndroid Build Coastguard Worker else
269*7c568831SAndroid Build Coastguard Worker ctxt->vstate = NULL;
270*7c568831SAndroid Build Coastguard Worker return(ctxt->vstateNr);
271*7c568831SAndroid Build Coastguard Worker }
272*7c568831SAndroid Build Coastguard Worker
273*7c568831SAndroid Build Coastguard Worker #else /* not LIBXML_REGEXP_ENABLED */
274*7c568831SAndroid Build Coastguard Worker /*
275*7c568831SAndroid Build Coastguard Worker * If regexp are not enabled, it uses a home made algorithm less
276*7c568831SAndroid Build Coastguard Worker * complex and easier to
277*7c568831SAndroid Build Coastguard Worker * debug/maintain than a generic NFA -> DFA state based algo. The
278*7c568831SAndroid Build Coastguard Worker * only restriction is on the deepness of the tree limited by the
279*7c568831SAndroid Build Coastguard Worker * size of the occurs bitfield
280*7c568831SAndroid Build Coastguard Worker *
281*7c568831SAndroid Build Coastguard Worker * this is the content of a saved state for rollbacks
282*7c568831SAndroid Build Coastguard Worker */
283*7c568831SAndroid Build Coastguard Worker
284*7c568831SAndroid Build Coastguard Worker #define ROLLBACK_OR 0
285*7c568831SAndroid Build Coastguard Worker #define ROLLBACK_PARENT 1
286*7c568831SAndroid Build Coastguard Worker
287*7c568831SAndroid Build Coastguard Worker typedef struct _xmlValidState {
288*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr cont; /* pointer to the content model subtree */
289*7c568831SAndroid Build Coastguard Worker xmlNodePtr node; /* pointer to the current node in the list */
290*7c568831SAndroid Build Coastguard Worker long occurs;/* bitfield for multiple occurrences */
291*7c568831SAndroid Build Coastguard Worker unsigned char depth; /* current depth in the overall tree */
292*7c568831SAndroid Build Coastguard Worker unsigned char state; /* ROLLBACK_XXX */
293*7c568831SAndroid Build Coastguard Worker } _xmlValidState;
294*7c568831SAndroid Build Coastguard Worker
295*7c568831SAndroid Build Coastguard Worker #define MAX_RECURSE 25000
296*7c568831SAndroid Build Coastguard Worker #define MAX_DEPTH ((sizeof(_xmlValidState.occurs)) * 8)
297*7c568831SAndroid Build Coastguard Worker #define CONT ctxt->vstate->cont
298*7c568831SAndroid Build Coastguard Worker #define NODE ctxt->vstate->node
299*7c568831SAndroid Build Coastguard Worker #define DEPTH ctxt->vstate->depth
300*7c568831SAndroid Build Coastguard Worker #define OCCURS ctxt->vstate->occurs
301*7c568831SAndroid Build Coastguard Worker #define STATE ctxt->vstate->state
302*7c568831SAndroid Build Coastguard Worker
303*7c568831SAndroid Build Coastguard Worker #define OCCURRENCE (ctxt->vstate->occurs & (1 << DEPTH))
304*7c568831SAndroid Build Coastguard Worker #define PARENT_OCCURRENCE (ctxt->vstate->occurs & ((1 << DEPTH) - 1))
305*7c568831SAndroid Build Coastguard Worker
306*7c568831SAndroid Build Coastguard Worker #define SET_OCCURRENCE ctxt->vstate->occurs |= (1 << DEPTH)
307*7c568831SAndroid Build Coastguard Worker #define RESET_OCCURRENCE ctxt->vstate->occurs &= ((1 << DEPTH) - 1)
308*7c568831SAndroid Build Coastguard Worker
309*7c568831SAndroid Build Coastguard Worker static int
vstateVPush(xmlValidCtxtPtr ctxt,xmlElementContentPtr cont,xmlNodePtr node,unsigned char depth,long occurs,unsigned char state)310*7c568831SAndroid Build Coastguard Worker vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont,
311*7c568831SAndroid Build Coastguard Worker xmlNodePtr node, unsigned char depth, long occurs,
312*7c568831SAndroid Build Coastguard Worker unsigned char state) {
313*7c568831SAndroid Build Coastguard Worker int i = ctxt->vstateNr - 1;
314*7c568831SAndroid Build Coastguard Worker
315*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateNr > MAX_RECURSE) {
316*7c568831SAndroid Build Coastguard Worker return(-1);
317*7c568831SAndroid Build Coastguard Worker }
318*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateTab == NULL) {
319*7c568831SAndroid Build Coastguard Worker ctxt->vstateMax = 8;
320*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab = (xmlValidState *) xmlMalloc(
321*7c568831SAndroid Build Coastguard Worker ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
322*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateTab == NULL) {
323*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
324*7c568831SAndroid Build Coastguard Worker return(-1);
325*7c568831SAndroid Build Coastguard Worker }
326*7c568831SAndroid Build Coastguard Worker }
327*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateNr >= ctxt->vstateMax) {
328*7c568831SAndroid Build Coastguard Worker xmlValidState *tmp;
329*7c568831SAndroid Build Coastguard Worker
330*7c568831SAndroid Build Coastguard Worker tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
331*7c568831SAndroid Build Coastguard Worker 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
332*7c568831SAndroid Build Coastguard Worker if (tmp == NULL) {
333*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
334*7c568831SAndroid Build Coastguard Worker return(-1);
335*7c568831SAndroid Build Coastguard Worker }
336*7c568831SAndroid Build Coastguard Worker ctxt->vstateMax *= 2;
337*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab = tmp;
338*7c568831SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[0];
339*7c568831SAndroid Build Coastguard Worker }
340*7c568831SAndroid Build Coastguard Worker /*
341*7c568831SAndroid Build Coastguard Worker * Don't push on the stack a state already here
342*7c568831SAndroid Build Coastguard Worker */
343*7c568831SAndroid Build Coastguard Worker if ((i >= 0) && (ctxt->vstateTab[i].cont == cont) &&
344*7c568831SAndroid Build Coastguard Worker (ctxt->vstateTab[i].node == node) &&
345*7c568831SAndroid Build Coastguard Worker (ctxt->vstateTab[i].depth == depth) &&
346*7c568831SAndroid Build Coastguard Worker (ctxt->vstateTab[i].occurs == occurs) &&
347*7c568831SAndroid Build Coastguard Worker (ctxt->vstateTab[i].state == state))
348*7c568831SAndroid Build Coastguard Worker return(ctxt->vstateNr);
349*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].cont = cont;
350*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].node = node;
351*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].depth = depth;
352*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].occurs = occurs;
353*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].state = state;
354*7c568831SAndroid Build Coastguard Worker return(ctxt->vstateNr++);
355*7c568831SAndroid Build Coastguard Worker }
356*7c568831SAndroid Build Coastguard Worker
357*7c568831SAndroid Build Coastguard Worker static int
vstateVPop(xmlValidCtxtPtr ctxt)358*7c568831SAndroid Build Coastguard Worker vstateVPop(xmlValidCtxtPtr ctxt) {
359*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateNr <= 1) return(-1);
360*7c568831SAndroid Build Coastguard Worker ctxt->vstateNr--;
361*7c568831SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[0];
362*7c568831SAndroid Build Coastguard Worker ctxt->vstate->cont = ctxt->vstateTab[ctxt->vstateNr].cont;
363*7c568831SAndroid Build Coastguard Worker ctxt->vstate->node = ctxt->vstateTab[ctxt->vstateNr].node;
364*7c568831SAndroid Build Coastguard Worker ctxt->vstate->depth = ctxt->vstateTab[ctxt->vstateNr].depth;
365*7c568831SAndroid Build Coastguard Worker ctxt->vstate->occurs = ctxt->vstateTab[ctxt->vstateNr].occurs;
366*7c568831SAndroid Build Coastguard Worker ctxt->vstate->state = ctxt->vstateTab[ctxt->vstateNr].state;
367*7c568831SAndroid Build Coastguard Worker return(ctxt->vstateNr);
368*7c568831SAndroid Build Coastguard Worker }
369*7c568831SAndroid Build Coastguard Worker
370*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
371*7c568831SAndroid Build Coastguard Worker
372*7c568831SAndroid Build Coastguard Worker static int
nodeVPush(xmlValidCtxtPtr ctxt,xmlNodePtr value)373*7c568831SAndroid Build Coastguard Worker nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value)
374*7c568831SAndroid Build Coastguard Worker {
375*7c568831SAndroid Build Coastguard Worker if (ctxt->nodeMax <= 0) {
376*7c568831SAndroid Build Coastguard Worker ctxt->nodeMax = 4;
377*7c568831SAndroid Build Coastguard Worker ctxt->nodeTab =
378*7c568831SAndroid Build Coastguard Worker (xmlNodePtr *) xmlMalloc(ctxt->nodeMax *
379*7c568831SAndroid Build Coastguard Worker sizeof(ctxt->nodeTab[0]));
380*7c568831SAndroid Build Coastguard Worker if (ctxt->nodeTab == NULL) {
381*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
382*7c568831SAndroid Build Coastguard Worker ctxt->nodeMax = 0;
383*7c568831SAndroid Build Coastguard Worker return (0);
384*7c568831SAndroid Build Coastguard Worker }
385*7c568831SAndroid Build Coastguard Worker }
386*7c568831SAndroid Build Coastguard Worker if (ctxt->nodeNr >= ctxt->nodeMax) {
387*7c568831SAndroid Build Coastguard Worker xmlNodePtr *tmp;
388*7c568831SAndroid Build Coastguard Worker tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
389*7c568831SAndroid Build Coastguard Worker ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0]));
390*7c568831SAndroid Build Coastguard Worker if (tmp == NULL) {
391*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
392*7c568831SAndroid Build Coastguard Worker return (0);
393*7c568831SAndroid Build Coastguard Worker }
394*7c568831SAndroid Build Coastguard Worker ctxt->nodeMax *= 2;
395*7c568831SAndroid Build Coastguard Worker ctxt->nodeTab = tmp;
396*7c568831SAndroid Build Coastguard Worker }
397*7c568831SAndroid Build Coastguard Worker ctxt->nodeTab[ctxt->nodeNr] = value;
398*7c568831SAndroid Build Coastguard Worker ctxt->node = value;
399*7c568831SAndroid Build Coastguard Worker return (ctxt->nodeNr++);
400*7c568831SAndroid Build Coastguard Worker }
401*7c568831SAndroid Build Coastguard Worker static xmlNodePtr
nodeVPop(xmlValidCtxtPtr ctxt)402*7c568831SAndroid Build Coastguard Worker nodeVPop(xmlValidCtxtPtr ctxt)
403*7c568831SAndroid Build Coastguard Worker {
404*7c568831SAndroid Build Coastguard Worker xmlNodePtr ret;
405*7c568831SAndroid Build Coastguard Worker
406*7c568831SAndroid Build Coastguard Worker if (ctxt->nodeNr <= 0)
407*7c568831SAndroid Build Coastguard Worker return (NULL);
408*7c568831SAndroid Build Coastguard Worker ctxt->nodeNr--;
409*7c568831SAndroid Build Coastguard Worker if (ctxt->nodeNr > 0)
410*7c568831SAndroid Build Coastguard Worker ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
411*7c568831SAndroid Build Coastguard Worker else
412*7c568831SAndroid Build Coastguard Worker ctxt->node = NULL;
413*7c568831SAndroid Build Coastguard Worker ret = ctxt->nodeTab[ctxt->nodeNr];
414*7c568831SAndroid Build Coastguard Worker ctxt->nodeTab[ctxt->nodeNr] = NULL;
415*7c568831SAndroid Build Coastguard Worker return (ret);
416*7c568831SAndroid Build Coastguard Worker }
417*7c568831SAndroid Build Coastguard Worker
418*7c568831SAndroid Build Coastguard Worker /* TODO: use hash table for accesses to elem and attribute definitions */
419*7c568831SAndroid Build Coastguard Worker
420*7c568831SAndroid Build Coastguard Worker
421*7c568831SAndroid Build Coastguard Worker #define CHECK_DTD \
422*7c568831SAndroid Build Coastguard Worker if (doc == NULL) return(0); \
423*7c568831SAndroid Build Coastguard Worker else if ((doc->intSubset == NULL) && \
424*7c568831SAndroid Build Coastguard Worker (doc->extSubset == NULL)) return(0)
425*7c568831SAndroid Build Coastguard Worker
426*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
427*7c568831SAndroid Build Coastguard Worker
428*7c568831SAndroid Build Coastguard Worker /************************************************************************
429*7c568831SAndroid Build Coastguard Worker * *
430*7c568831SAndroid Build Coastguard Worker * Content model validation based on the regexps *
431*7c568831SAndroid Build Coastguard Worker * *
432*7c568831SAndroid Build Coastguard Worker ************************************************************************/
433*7c568831SAndroid Build Coastguard Worker
434*7c568831SAndroid Build Coastguard Worker /**
435*7c568831SAndroid Build Coastguard Worker * xmlValidBuildAContentModel:
436*7c568831SAndroid Build Coastguard Worker * @content: the content model
437*7c568831SAndroid Build Coastguard Worker * @ctxt: the schema parser context
438*7c568831SAndroid Build Coastguard Worker * @name: the element name whose content is being built
439*7c568831SAndroid Build Coastguard Worker *
440*7c568831SAndroid Build Coastguard Worker * Generate the automata sequence needed for that type
441*7c568831SAndroid Build Coastguard Worker *
442*7c568831SAndroid Build Coastguard Worker * Returns 1 if successful or 0 in case of error.
443*7c568831SAndroid Build Coastguard Worker */
444*7c568831SAndroid Build Coastguard Worker static int
xmlValidBuildAContentModel(xmlElementContentPtr content,xmlValidCtxtPtr ctxt,const xmlChar * name)445*7c568831SAndroid Build Coastguard Worker xmlValidBuildAContentModel(xmlElementContentPtr content,
446*7c568831SAndroid Build Coastguard Worker xmlValidCtxtPtr ctxt,
447*7c568831SAndroid Build Coastguard Worker const xmlChar *name) {
448*7c568831SAndroid Build Coastguard Worker if (content == NULL) {
449*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR,
450*7c568831SAndroid Build Coastguard Worker "Found NULL content in content model of %s\n",
451*7c568831SAndroid Build Coastguard Worker name, NULL, NULL);
452*7c568831SAndroid Build Coastguard Worker return(0);
453*7c568831SAndroid Build Coastguard Worker }
454*7c568831SAndroid Build Coastguard Worker switch (content->type) {
455*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
456*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR,
457*7c568831SAndroid Build Coastguard Worker "Found PCDATA in content model of %s\n",
458*7c568831SAndroid Build Coastguard Worker name, NULL, NULL);
459*7c568831SAndroid Build Coastguard Worker return(0);
460*7c568831SAndroid Build Coastguard Worker break;
461*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT: {
462*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr oldstate = ctxt->state;
463*7c568831SAndroid Build Coastguard Worker xmlChar fn[50];
464*7c568831SAndroid Build Coastguard Worker xmlChar *fullname;
465*7c568831SAndroid Build Coastguard Worker
466*7c568831SAndroid Build Coastguard Worker fullname = xmlBuildQName(content->name, content->prefix, fn, 50);
467*7c568831SAndroid Build Coastguard Worker if (fullname == NULL) {
468*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
469*7c568831SAndroid Build Coastguard Worker return(0);
470*7c568831SAndroid Build Coastguard Worker }
471*7c568831SAndroid Build Coastguard Worker
472*7c568831SAndroid Build Coastguard Worker switch (content->ocur) {
473*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
474*7c568831SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewTransition(ctxt->am,
475*7c568831SAndroid Build Coastguard Worker ctxt->state, NULL, fullname, NULL);
476*7c568831SAndroid Build Coastguard Worker break;
477*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
478*7c568831SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewTransition(ctxt->am,
479*7c568831SAndroid Build Coastguard Worker ctxt->state, NULL, fullname, NULL);
480*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
481*7c568831SAndroid Build Coastguard Worker break;
482*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
483*7c568831SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewTransition(ctxt->am,
484*7c568831SAndroid Build Coastguard Worker ctxt->state, NULL, fullname, NULL);
485*7c568831SAndroid Build Coastguard Worker xmlAutomataNewTransition(ctxt->am, ctxt->state,
486*7c568831SAndroid Build Coastguard Worker ctxt->state, fullname, NULL);
487*7c568831SAndroid Build Coastguard Worker break;
488*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
489*7c568831SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
490*7c568831SAndroid Build Coastguard Worker ctxt->state, NULL);
491*7c568831SAndroid Build Coastguard Worker xmlAutomataNewTransition(ctxt->am,
492*7c568831SAndroid Build Coastguard Worker ctxt->state, ctxt->state, fullname, NULL);
493*7c568831SAndroid Build Coastguard Worker break;
494*7c568831SAndroid Build Coastguard Worker }
495*7c568831SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != content->name))
496*7c568831SAndroid Build Coastguard Worker xmlFree(fullname);
497*7c568831SAndroid Build Coastguard Worker break;
498*7c568831SAndroid Build Coastguard Worker }
499*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ: {
500*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr oldstate, oldend;
501*7c568831SAndroid Build Coastguard Worker xmlElementContentOccur ocur;
502*7c568831SAndroid Build Coastguard Worker
503*7c568831SAndroid Build Coastguard Worker /*
504*7c568831SAndroid Build Coastguard Worker * Simply iterate over the content
505*7c568831SAndroid Build Coastguard Worker */
506*7c568831SAndroid Build Coastguard Worker oldstate = ctxt->state;
507*7c568831SAndroid Build Coastguard Worker ocur = content->ocur;
508*7c568831SAndroid Build Coastguard Worker if (ocur != XML_ELEMENT_CONTENT_ONCE) {
509*7c568831SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
510*7c568831SAndroid Build Coastguard Worker oldstate = ctxt->state;
511*7c568831SAndroid Build Coastguard Worker }
512*7c568831SAndroid Build Coastguard Worker do {
513*7c568831SAndroid Build Coastguard Worker if (xmlValidBuildAContentModel(content->c1, ctxt, name) == 0)
514*7c568831SAndroid Build Coastguard Worker return(0);
515*7c568831SAndroid Build Coastguard Worker content = content->c2;
516*7c568831SAndroid Build Coastguard Worker } while ((content->type == XML_ELEMENT_CONTENT_SEQ) &&
517*7c568831SAndroid Build Coastguard Worker (content->ocur == XML_ELEMENT_CONTENT_ONCE));
518*7c568831SAndroid Build Coastguard Worker if (xmlValidBuildAContentModel(content, ctxt, name) == 0)
519*7c568831SAndroid Build Coastguard Worker return(0);
520*7c568831SAndroid Build Coastguard Worker oldend = ctxt->state;
521*7c568831SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
522*7c568831SAndroid Build Coastguard Worker switch (ocur) {
523*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
524*7c568831SAndroid Build Coastguard Worker break;
525*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
526*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
527*7c568831SAndroid Build Coastguard Worker break;
528*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
529*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
530*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
531*7c568831SAndroid Build Coastguard Worker break;
532*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
533*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
534*7c568831SAndroid Build Coastguard Worker break;
535*7c568831SAndroid Build Coastguard Worker }
536*7c568831SAndroid Build Coastguard Worker break;
537*7c568831SAndroid Build Coastguard Worker }
538*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR: {
539*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr oldstate, oldend;
540*7c568831SAndroid Build Coastguard Worker xmlElementContentOccur ocur;
541*7c568831SAndroid Build Coastguard Worker
542*7c568831SAndroid Build Coastguard Worker ocur = content->ocur;
543*7c568831SAndroid Build Coastguard Worker if ((ocur == XML_ELEMENT_CONTENT_PLUS) ||
544*7c568831SAndroid Build Coastguard Worker (ocur == XML_ELEMENT_CONTENT_MULT)) {
545*7c568831SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
546*7c568831SAndroid Build Coastguard Worker ctxt->state, NULL);
547*7c568831SAndroid Build Coastguard Worker }
548*7c568831SAndroid Build Coastguard Worker oldstate = ctxt->state;
549*7c568831SAndroid Build Coastguard Worker oldend = xmlAutomataNewState(ctxt->am);
550*7c568831SAndroid Build Coastguard Worker
551*7c568831SAndroid Build Coastguard Worker /*
552*7c568831SAndroid Build Coastguard Worker * iterate over the subtypes and remerge the end with an
553*7c568831SAndroid Build Coastguard Worker * epsilon transition
554*7c568831SAndroid Build Coastguard Worker */
555*7c568831SAndroid Build Coastguard Worker do {
556*7c568831SAndroid Build Coastguard Worker ctxt->state = oldstate;
557*7c568831SAndroid Build Coastguard Worker if (xmlValidBuildAContentModel(content->c1, ctxt, name) == 0)
558*7c568831SAndroid Build Coastguard Worker return(0);
559*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
560*7c568831SAndroid Build Coastguard Worker content = content->c2;
561*7c568831SAndroid Build Coastguard Worker } while ((content->type == XML_ELEMENT_CONTENT_OR) &&
562*7c568831SAndroid Build Coastguard Worker (content->ocur == XML_ELEMENT_CONTENT_ONCE));
563*7c568831SAndroid Build Coastguard Worker ctxt->state = oldstate;
564*7c568831SAndroid Build Coastguard Worker if (xmlValidBuildAContentModel(content, ctxt, name) == 0)
565*7c568831SAndroid Build Coastguard Worker return(0);
566*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
567*7c568831SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
568*7c568831SAndroid Build Coastguard Worker switch (ocur) {
569*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
570*7c568831SAndroid Build Coastguard Worker break;
571*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
572*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
573*7c568831SAndroid Build Coastguard Worker break;
574*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
575*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
576*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
577*7c568831SAndroid Build Coastguard Worker break;
578*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
579*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
580*7c568831SAndroid Build Coastguard Worker break;
581*7c568831SAndroid Build Coastguard Worker }
582*7c568831SAndroid Build Coastguard Worker break;
583*7c568831SAndroid Build Coastguard Worker }
584*7c568831SAndroid Build Coastguard Worker default:
585*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
586*7c568831SAndroid Build Coastguard Worker "ContentModel broken for element %s\n",
587*7c568831SAndroid Build Coastguard Worker (const char *) name);
588*7c568831SAndroid Build Coastguard Worker return(0);
589*7c568831SAndroid Build Coastguard Worker }
590*7c568831SAndroid Build Coastguard Worker return(1);
591*7c568831SAndroid Build Coastguard Worker }
592*7c568831SAndroid Build Coastguard Worker /**
593*7c568831SAndroid Build Coastguard Worker * xmlValidBuildContentModel:
594*7c568831SAndroid Build Coastguard Worker * @ctxt: a validation context
595*7c568831SAndroid Build Coastguard Worker * @elem: an element declaration node
596*7c568831SAndroid Build Coastguard Worker *
597*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
598*7c568831SAndroid Build Coastguard Worker *
599*7c568831SAndroid Build Coastguard Worker * (Re)Build the automata associated to the content model of this
600*7c568831SAndroid Build Coastguard Worker * element
601*7c568831SAndroid Build Coastguard Worker *
602*7c568831SAndroid Build Coastguard Worker * Returns 1 in case of success, 0 in case of error
603*7c568831SAndroid Build Coastguard Worker */
604*7c568831SAndroid Build Coastguard Worker int
xmlValidBuildContentModel(xmlValidCtxtPtr ctxt,xmlElementPtr elem)605*7c568831SAndroid Build Coastguard Worker xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
606*7c568831SAndroid Build Coastguard Worker int ret = 0;
607*7c568831SAndroid Build Coastguard Worker
608*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (elem == NULL))
609*7c568831SAndroid Build Coastguard Worker return(0);
610*7c568831SAndroid Build Coastguard Worker if (elem->type != XML_ELEMENT_DECL)
611*7c568831SAndroid Build Coastguard Worker return(0);
612*7c568831SAndroid Build Coastguard Worker if (elem->etype != XML_ELEMENT_TYPE_ELEMENT)
613*7c568831SAndroid Build Coastguard Worker return(1);
614*7c568831SAndroid Build Coastguard Worker /* TODO: should we rebuild in this case ? */
615*7c568831SAndroid Build Coastguard Worker if (elem->contModel != NULL) {
616*7c568831SAndroid Build Coastguard Worker if (!xmlRegexpIsDeterminist(elem->contModel)) {
617*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
618*7c568831SAndroid Build Coastguard Worker return(0);
619*7c568831SAndroid Build Coastguard Worker }
620*7c568831SAndroid Build Coastguard Worker return(1);
621*7c568831SAndroid Build Coastguard Worker }
622*7c568831SAndroid Build Coastguard Worker
623*7c568831SAndroid Build Coastguard Worker ctxt->am = xmlNewAutomata();
624*7c568831SAndroid Build Coastguard Worker if (ctxt->am == NULL) {
625*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
626*7c568831SAndroid Build Coastguard Worker return(0);
627*7c568831SAndroid Build Coastguard Worker }
628*7c568831SAndroid Build Coastguard Worker ctxt->state = xmlAutomataGetInitState(ctxt->am);
629*7c568831SAndroid Build Coastguard Worker if (xmlValidBuildAContentModel(elem->content, ctxt, elem->name) == 0)
630*7c568831SAndroid Build Coastguard Worker goto done;
631*7c568831SAndroid Build Coastguard Worker xmlAutomataSetFinalState(ctxt->am, ctxt->state);
632*7c568831SAndroid Build Coastguard Worker elem->contModel = xmlAutomataCompile(ctxt->am);
633*7c568831SAndroid Build Coastguard Worker if (elem->contModel == NULL) {
634*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
635*7c568831SAndroid Build Coastguard Worker goto done;
636*7c568831SAndroid Build Coastguard Worker }
637*7c568831SAndroid Build Coastguard Worker if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
638*7c568831SAndroid Build Coastguard Worker char expr[5000];
639*7c568831SAndroid Build Coastguard Worker expr[0] = 0;
640*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(expr, 5000, elem->content, 1);
641*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem,
642*7c568831SAndroid Build Coastguard Worker XML_DTD_CONTENT_NOT_DETERMINIST,
643*7c568831SAndroid Build Coastguard Worker "Content model of %s is not deterministic: %s\n",
644*7c568831SAndroid Build Coastguard Worker elem->name, BAD_CAST expr, NULL);
645*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
646*7c568831SAndroid Build Coastguard Worker goto done;
647*7c568831SAndroid Build Coastguard Worker }
648*7c568831SAndroid Build Coastguard Worker
649*7c568831SAndroid Build Coastguard Worker ret = 1;
650*7c568831SAndroid Build Coastguard Worker
651*7c568831SAndroid Build Coastguard Worker done:
652*7c568831SAndroid Build Coastguard Worker ctxt->state = NULL;
653*7c568831SAndroid Build Coastguard Worker xmlFreeAutomata(ctxt->am);
654*7c568831SAndroid Build Coastguard Worker ctxt->am = NULL;
655*7c568831SAndroid Build Coastguard Worker return(ret);
656*7c568831SAndroid Build Coastguard Worker }
657*7c568831SAndroid Build Coastguard Worker
658*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
659*7c568831SAndroid Build Coastguard Worker
660*7c568831SAndroid Build Coastguard Worker /****************************************************************
661*7c568831SAndroid Build Coastguard Worker * *
662*7c568831SAndroid Build Coastguard Worker * Util functions for data allocation/deallocation *
663*7c568831SAndroid Build Coastguard Worker * *
664*7c568831SAndroid Build Coastguard Worker ****************************************************************/
665*7c568831SAndroid Build Coastguard Worker
666*7c568831SAndroid Build Coastguard Worker /**
667*7c568831SAndroid Build Coastguard Worker * xmlNewValidCtxt:
668*7c568831SAndroid Build Coastguard Worker *
669*7c568831SAndroid Build Coastguard Worker * Allocate a validation context structure.
670*7c568831SAndroid Build Coastguard Worker *
671*7c568831SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the new validation context structure
672*7c568831SAndroid Build Coastguard Worker */
xmlNewValidCtxt(void)673*7c568831SAndroid Build Coastguard Worker xmlValidCtxtPtr xmlNewValidCtxt(void) {
674*7c568831SAndroid Build Coastguard Worker xmlValidCtxtPtr ret;
675*7c568831SAndroid Build Coastguard Worker
676*7c568831SAndroid Build Coastguard Worker ret = xmlMalloc(sizeof (xmlValidCtxt));
677*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
678*7c568831SAndroid Build Coastguard Worker return (NULL);
679*7c568831SAndroid Build Coastguard Worker
680*7c568831SAndroid Build Coastguard Worker (void) memset(ret, 0, sizeof (xmlValidCtxt));
681*7c568831SAndroid Build Coastguard Worker
682*7c568831SAndroid Build Coastguard Worker return (ret);
683*7c568831SAndroid Build Coastguard Worker }
684*7c568831SAndroid Build Coastguard Worker
685*7c568831SAndroid Build Coastguard Worker /**
686*7c568831SAndroid Build Coastguard Worker * xmlFreeValidCtxt:
687*7c568831SAndroid Build Coastguard Worker * @cur: the validation context to free
688*7c568831SAndroid Build Coastguard Worker *
689*7c568831SAndroid Build Coastguard Worker * Free a validation context structure.
690*7c568831SAndroid Build Coastguard Worker */
691*7c568831SAndroid Build Coastguard Worker void
xmlFreeValidCtxt(xmlValidCtxtPtr cur)692*7c568831SAndroid Build Coastguard Worker xmlFreeValidCtxt(xmlValidCtxtPtr cur) {
693*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
694*7c568831SAndroid Build Coastguard Worker return;
695*7c568831SAndroid Build Coastguard Worker if (cur->vstateTab != NULL)
696*7c568831SAndroid Build Coastguard Worker xmlFree(cur->vstateTab);
697*7c568831SAndroid Build Coastguard Worker if (cur->nodeTab != NULL)
698*7c568831SAndroid Build Coastguard Worker xmlFree(cur->nodeTab);
699*7c568831SAndroid Build Coastguard Worker xmlFree(cur);
700*7c568831SAndroid Build Coastguard Worker }
701*7c568831SAndroid Build Coastguard Worker
702*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
703*7c568831SAndroid Build Coastguard Worker
704*7c568831SAndroid Build Coastguard Worker /**
705*7c568831SAndroid Build Coastguard Worker * xmlNewDocElementContent:
706*7c568831SAndroid Build Coastguard Worker * @doc: the document
707*7c568831SAndroid Build Coastguard Worker * @name: the subelement name or NULL
708*7c568831SAndroid Build Coastguard Worker * @type: the type of element content decl
709*7c568831SAndroid Build Coastguard Worker *
710*7c568831SAndroid Build Coastguard Worker * Allocate an element content structure for the document.
711*7c568831SAndroid Build Coastguard Worker *
712*7c568831SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the new element content structure
713*7c568831SAndroid Build Coastguard Worker */
714*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr
xmlNewDocElementContent(xmlDocPtr doc,const xmlChar * name,xmlElementContentType type)715*7c568831SAndroid Build Coastguard Worker xmlNewDocElementContent(xmlDocPtr doc, const xmlChar *name,
716*7c568831SAndroid Build Coastguard Worker xmlElementContentType type) {
717*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr ret;
718*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
719*7c568831SAndroid Build Coastguard Worker
720*7c568831SAndroid Build Coastguard Worker if (doc != NULL)
721*7c568831SAndroid Build Coastguard Worker dict = doc->dict;
722*7c568831SAndroid Build Coastguard Worker
723*7c568831SAndroid Build Coastguard Worker switch(type) {
724*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT:
725*7c568831SAndroid Build Coastguard Worker if (name == NULL) {
726*7c568831SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
727*7c568831SAndroid Build Coastguard Worker "xmlNewElementContent : name == NULL !\n",
728*7c568831SAndroid Build Coastguard Worker NULL);
729*7c568831SAndroid Build Coastguard Worker }
730*7c568831SAndroid Build Coastguard Worker break;
731*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
732*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
733*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
734*7c568831SAndroid Build Coastguard Worker if (name != NULL) {
735*7c568831SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
736*7c568831SAndroid Build Coastguard Worker "xmlNewElementContent : name != NULL !\n",
737*7c568831SAndroid Build Coastguard Worker NULL);
738*7c568831SAndroid Build Coastguard Worker }
739*7c568831SAndroid Build Coastguard Worker break;
740*7c568831SAndroid Build Coastguard Worker default:
741*7c568831SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
742*7c568831SAndroid Build Coastguard Worker "Internal: ELEMENT content corrupted invalid type\n",
743*7c568831SAndroid Build Coastguard Worker NULL);
744*7c568831SAndroid Build Coastguard Worker return(NULL);
745*7c568831SAndroid Build Coastguard Worker }
746*7c568831SAndroid Build Coastguard Worker ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
747*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
748*7c568831SAndroid Build Coastguard Worker return(NULL);
749*7c568831SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlElementContent));
750*7c568831SAndroid Build Coastguard Worker ret->type = type;
751*7c568831SAndroid Build Coastguard Worker ret->ocur = XML_ELEMENT_CONTENT_ONCE;
752*7c568831SAndroid Build Coastguard Worker if (name != NULL) {
753*7c568831SAndroid Build Coastguard Worker int l;
754*7c568831SAndroid Build Coastguard Worker const xmlChar *tmp;
755*7c568831SAndroid Build Coastguard Worker
756*7c568831SAndroid Build Coastguard Worker tmp = xmlSplitQName3(name, &l);
757*7c568831SAndroid Build Coastguard Worker if (tmp == NULL) {
758*7c568831SAndroid Build Coastguard Worker if (dict == NULL)
759*7c568831SAndroid Build Coastguard Worker ret->name = xmlStrdup(name);
760*7c568831SAndroid Build Coastguard Worker else
761*7c568831SAndroid Build Coastguard Worker ret->name = xmlDictLookup(dict, name, -1);
762*7c568831SAndroid Build Coastguard Worker } else {
763*7c568831SAndroid Build Coastguard Worker if (dict == NULL) {
764*7c568831SAndroid Build Coastguard Worker ret->prefix = xmlStrndup(name, l);
765*7c568831SAndroid Build Coastguard Worker ret->name = xmlStrdup(tmp);
766*7c568831SAndroid Build Coastguard Worker } else {
767*7c568831SAndroid Build Coastguard Worker ret->prefix = xmlDictLookup(dict, name, l);
768*7c568831SAndroid Build Coastguard Worker ret->name = xmlDictLookup(dict, tmp, -1);
769*7c568831SAndroid Build Coastguard Worker }
770*7c568831SAndroid Build Coastguard Worker if (ret->prefix == NULL)
771*7c568831SAndroid Build Coastguard Worker goto error;
772*7c568831SAndroid Build Coastguard Worker }
773*7c568831SAndroid Build Coastguard Worker if (ret->name == NULL)
774*7c568831SAndroid Build Coastguard Worker goto error;
775*7c568831SAndroid Build Coastguard Worker }
776*7c568831SAndroid Build Coastguard Worker return(ret);
777*7c568831SAndroid Build Coastguard Worker
778*7c568831SAndroid Build Coastguard Worker error:
779*7c568831SAndroid Build Coastguard Worker xmlFreeDocElementContent(doc, ret);
780*7c568831SAndroid Build Coastguard Worker return(NULL);
781*7c568831SAndroid Build Coastguard Worker }
782*7c568831SAndroid Build Coastguard Worker
783*7c568831SAndroid Build Coastguard Worker /**
784*7c568831SAndroid Build Coastguard Worker * xmlNewElementContent:
785*7c568831SAndroid Build Coastguard Worker * @name: the subelement name or NULL
786*7c568831SAndroid Build Coastguard Worker * @type: the type of element content decl
787*7c568831SAndroid Build Coastguard Worker *
788*7c568831SAndroid Build Coastguard Worker * Allocate an element content structure.
789*7c568831SAndroid Build Coastguard Worker * Deprecated in favor of xmlNewDocElementContent
790*7c568831SAndroid Build Coastguard Worker *
791*7c568831SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the new element content structure
792*7c568831SAndroid Build Coastguard Worker */
793*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr
xmlNewElementContent(const xmlChar * name,xmlElementContentType type)794*7c568831SAndroid Build Coastguard Worker xmlNewElementContent(const xmlChar *name, xmlElementContentType type) {
795*7c568831SAndroid Build Coastguard Worker return(xmlNewDocElementContent(NULL, name, type));
796*7c568831SAndroid Build Coastguard Worker }
797*7c568831SAndroid Build Coastguard Worker
798*7c568831SAndroid Build Coastguard Worker /**
799*7c568831SAndroid Build Coastguard Worker * xmlCopyDocElementContent:
800*7c568831SAndroid Build Coastguard Worker * @doc: the document owning the element declaration
801*7c568831SAndroid Build Coastguard Worker * @cur: An element content pointer.
802*7c568831SAndroid Build Coastguard Worker *
803*7c568831SAndroid Build Coastguard Worker * Build a copy of an element content description.
804*7c568831SAndroid Build Coastguard Worker *
805*7c568831SAndroid Build Coastguard Worker * Returns the new xmlElementContentPtr or NULL in case of error.
806*7c568831SAndroid Build Coastguard Worker */
807*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr
xmlCopyDocElementContent(xmlDocPtr doc,xmlElementContentPtr cur)808*7c568831SAndroid Build Coastguard Worker xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
809*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr ret = NULL, prev = NULL, tmp;
810*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
811*7c568831SAndroid Build Coastguard Worker
812*7c568831SAndroid Build Coastguard Worker if (cur == NULL) return(NULL);
813*7c568831SAndroid Build Coastguard Worker
814*7c568831SAndroid Build Coastguard Worker if (doc != NULL)
815*7c568831SAndroid Build Coastguard Worker dict = doc->dict;
816*7c568831SAndroid Build Coastguard Worker
817*7c568831SAndroid Build Coastguard Worker ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
818*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
819*7c568831SAndroid Build Coastguard Worker return(NULL);
820*7c568831SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlElementContent));
821*7c568831SAndroid Build Coastguard Worker ret->type = cur->type;
822*7c568831SAndroid Build Coastguard Worker ret->ocur = cur->ocur;
823*7c568831SAndroid Build Coastguard Worker if (cur->name != NULL) {
824*7c568831SAndroid Build Coastguard Worker if (dict)
825*7c568831SAndroid Build Coastguard Worker ret->name = xmlDictLookup(dict, cur->name, -1);
826*7c568831SAndroid Build Coastguard Worker else
827*7c568831SAndroid Build Coastguard Worker ret->name = xmlStrdup(cur->name);
828*7c568831SAndroid Build Coastguard Worker if (ret->name == NULL)
829*7c568831SAndroid Build Coastguard Worker goto error;
830*7c568831SAndroid Build Coastguard Worker }
831*7c568831SAndroid Build Coastguard Worker
832*7c568831SAndroid Build Coastguard Worker if (cur->prefix != NULL) {
833*7c568831SAndroid Build Coastguard Worker if (dict)
834*7c568831SAndroid Build Coastguard Worker ret->prefix = xmlDictLookup(dict, cur->prefix, -1);
835*7c568831SAndroid Build Coastguard Worker else
836*7c568831SAndroid Build Coastguard Worker ret->prefix = xmlStrdup(cur->prefix);
837*7c568831SAndroid Build Coastguard Worker if (ret->prefix == NULL)
838*7c568831SAndroid Build Coastguard Worker goto error;
839*7c568831SAndroid Build Coastguard Worker }
840*7c568831SAndroid Build Coastguard Worker if (cur->c1 != NULL) {
841*7c568831SAndroid Build Coastguard Worker ret->c1 = xmlCopyDocElementContent(doc, cur->c1);
842*7c568831SAndroid Build Coastguard Worker if (ret->c1 == NULL)
843*7c568831SAndroid Build Coastguard Worker goto error;
844*7c568831SAndroid Build Coastguard Worker ret->c1->parent = ret;
845*7c568831SAndroid Build Coastguard Worker }
846*7c568831SAndroid Build Coastguard Worker if (cur->c2 != NULL) {
847*7c568831SAndroid Build Coastguard Worker prev = ret;
848*7c568831SAndroid Build Coastguard Worker cur = cur->c2;
849*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
850*7c568831SAndroid Build Coastguard Worker tmp = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
851*7c568831SAndroid Build Coastguard Worker if (tmp == NULL)
852*7c568831SAndroid Build Coastguard Worker goto error;
853*7c568831SAndroid Build Coastguard Worker memset(tmp, 0, sizeof(xmlElementContent));
854*7c568831SAndroid Build Coastguard Worker tmp->type = cur->type;
855*7c568831SAndroid Build Coastguard Worker tmp->ocur = cur->ocur;
856*7c568831SAndroid Build Coastguard Worker prev->c2 = tmp;
857*7c568831SAndroid Build Coastguard Worker tmp->parent = prev;
858*7c568831SAndroid Build Coastguard Worker if (cur->name != NULL) {
859*7c568831SAndroid Build Coastguard Worker if (dict)
860*7c568831SAndroid Build Coastguard Worker tmp->name = xmlDictLookup(dict, cur->name, -1);
861*7c568831SAndroid Build Coastguard Worker else
862*7c568831SAndroid Build Coastguard Worker tmp->name = xmlStrdup(cur->name);
863*7c568831SAndroid Build Coastguard Worker if (tmp->name == NULL)
864*7c568831SAndroid Build Coastguard Worker goto error;
865*7c568831SAndroid Build Coastguard Worker }
866*7c568831SAndroid Build Coastguard Worker
867*7c568831SAndroid Build Coastguard Worker if (cur->prefix != NULL) {
868*7c568831SAndroid Build Coastguard Worker if (dict)
869*7c568831SAndroid Build Coastguard Worker tmp->prefix = xmlDictLookup(dict, cur->prefix, -1);
870*7c568831SAndroid Build Coastguard Worker else
871*7c568831SAndroid Build Coastguard Worker tmp->prefix = xmlStrdup(cur->prefix);
872*7c568831SAndroid Build Coastguard Worker if (tmp->prefix == NULL)
873*7c568831SAndroid Build Coastguard Worker goto error;
874*7c568831SAndroid Build Coastguard Worker }
875*7c568831SAndroid Build Coastguard Worker if (cur->c1 != NULL) {
876*7c568831SAndroid Build Coastguard Worker tmp->c1 = xmlCopyDocElementContent(doc,cur->c1);
877*7c568831SAndroid Build Coastguard Worker if (tmp->c1 == NULL)
878*7c568831SAndroid Build Coastguard Worker goto error;
879*7c568831SAndroid Build Coastguard Worker tmp->c1->parent = tmp;
880*7c568831SAndroid Build Coastguard Worker }
881*7c568831SAndroid Build Coastguard Worker prev = tmp;
882*7c568831SAndroid Build Coastguard Worker cur = cur->c2;
883*7c568831SAndroid Build Coastguard Worker }
884*7c568831SAndroid Build Coastguard Worker }
885*7c568831SAndroid Build Coastguard Worker return(ret);
886*7c568831SAndroid Build Coastguard Worker
887*7c568831SAndroid Build Coastguard Worker error:
888*7c568831SAndroid Build Coastguard Worker xmlFreeElementContent(ret);
889*7c568831SAndroid Build Coastguard Worker return(NULL);
890*7c568831SAndroid Build Coastguard Worker }
891*7c568831SAndroid Build Coastguard Worker
892*7c568831SAndroid Build Coastguard Worker /**
893*7c568831SAndroid Build Coastguard Worker * xmlCopyElementContent:
894*7c568831SAndroid Build Coastguard Worker * @cur: An element content pointer.
895*7c568831SAndroid Build Coastguard Worker *
896*7c568831SAndroid Build Coastguard Worker * Build a copy of an element content description.
897*7c568831SAndroid Build Coastguard Worker * Deprecated, use xmlCopyDocElementContent instead
898*7c568831SAndroid Build Coastguard Worker *
899*7c568831SAndroid Build Coastguard Worker * Returns the new xmlElementContentPtr or NULL in case of error.
900*7c568831SAndroid Build Coastguard Worker */
901*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr
xmlCopyElementContent(xmlElementContentPtr cur)902*7c568831SAndroid Build Coastguard Worker xmlCopyElementContent(xmlElementContentPtr cur) {
903*7c568831SAndroid Build Coastguard Worker return(xmlCopyDocElementContent(NULL, cur));
904*7c568831SAndroid Build Coastguard Worker }
905*7c568831SAndroid Build Coastguard Worker
906*7c568831SAndroid Build Coastguard Worker /**
907*7c568831SAndroid Build Coastguard Worker * xmlFreeDocElementContent:
908*7c568831SAndroid Build Coastguard Worker * @doc: the document owning the element declaration
909*7c568831SAndroid Build Coastguard Worker * @cur: the element content tree to free
910*7c568831SAndroid Build Coastguard Worker *
911*7c568831SAndroid Build Coastguard Worker * Free an element content structure. The whole subtree is removed.
912*7c568831SAndroid Build Coastguard Worker */
913*7c568831SAndroid Build Coastguard Worker void
xmlFreeDocElementContent(xmlDocPtr doc,xmlElementContentPtr cur)914*7c568831SAndroid Build Coastguard Worker xmlFreeDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
915*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
916*7c568831SAndroid Build Coastguard Worker size_t depth = 0;
917*7c568831SAndroid Build Coastguard Worker
918*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
919*7c568831SAndroid Build Coastguard Worker return;
920*7c568831SAndroid Build Coastguard Worker if (doc != NULL)
921*7c568831SAndroid Build Coastguard Worker dict = doc->dict;
922*7c568831SAndroid Build Coastguard Worker
923*7c568831SAndroid Build Coastguard Worker while (1) {
924*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr parent;
925*7c568831SAndroid Build Coastguard Worker
926*7c568831SAndroid Build Coastguard Worker while ((cur->c1 != NULL) || (cur->c2 != NULL)) {
927*7c568831SAndroid Build Coastguard Worker cur = (cur->c1 != NULL) ? cur->c1 : cur->c2;
928*7c568831SAndroid Build Coastguard Worker depth += 1;
929*7c568831SAndroid Build Coastguard Worker }
930*7c568831SAndroid Build Coastguard Worker
931*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
932*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
933*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT:
934*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
935*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
936*7c568831SAndroid Build Coastguard Worker break;
937*7c568831SAndroid Build Coastguard Worker default:
938*7c568831SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
939*7c568831SAndroid Build Coastguard Worker "Internal: ELEMENT content corrupted invalid type\n",
940*7c568831SAndroid Build Coastguard Worker NULL);
941*7c568831SAndroid Build Coastguard Worker return;
942*7c568831SAndroid Build Coastguard Worker }
943*7c568831SAndroid Build Coastguard Worker if (dict) {
944*7c568831SAndroid Build Coastguard Worker if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))
945*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) cur->name);
946*7c568831SAndroid Build Coastguard Worker if ((cur->prefix != NULL) && (!xmlDictOwns(dict, cur->prefix)))
947*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) cur->prefix);
948*7c568831SAndroid Build Coastguard Worker } else {
949*7c568831SAndroid Build Coastguard Worker if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
950*7c568831SAndroid Build Coastguard Worker if (cur->prefix != NULL) xmlFree((xmlChar *) cur->prefix);
951*7c568831SAndroid Build Coastguard Worker }
952*7c568831SAndroid Build Coastguard Worker parent = cur->parent;
953*7c568831SAndroid Build Coastguard Worker if ((depth == 0) || (parent == NULL)) {
954*7c568831SAndroid Build Coastguard Worker xmlFree(cur);
955*7c568831SAndroid Build Coastguard Worker break;
956*7c568831SAndroid Build Coastguard Worker }
957*7c568831SAndroid Build Coastguard Worker if (cur == parent->c1)
958*7c568831SAndroid Build Coastguard Worker parent->c1 = NULL;
959*7c568831SAndroid Build Coastguard Worker else
960*7c568831SAndroid Build Coastguard Worker parent->c2 = NULL;
961*7c568831SAndroid Build Coastguard Worker xmlFree(cur);
962*7c568831SAndroid Build Coastguard Worker
963*7c568831SAndroid Build Coastguard Worker if (parent->c2 != NULL) {
964*7c568831SAndroid Build Coastguard Worker cur = parent->c2;
965*7c568831SAndroid Build Coastguard Worker } else {
966*7c568831SAndroid Build Coastguard Worker depth -= 1;
967*7c568831SAndroid Build Coastguard Worker cur = parent;
968*7c568831SAndroid Build Coastguard Worker }
969*7c568831SAndroid Build Coastguard Worker }
970*7c568831SAndroid Build Coastguard Worker }
971*7c568831SAndroid Build Coastguard Worker
972*7c568831SAndroid Build Coastguard Worker /**
973*7c568831SAndroid Build Coastguard Worker * xmlFreeElementContent:
974*7c568831SAndroid Build Coastguard Worker * @cur: the element content tree to free
975*7c568831SAndroid Build Coastguard Worker *
976*7c568831SAndroid Build Coastguard Worker * Free an element content structure. The whole subtree is removed.
977*7c568831SAndroid Build Coastguard Worker * Deprecated, use xmlFreeDocElementContent instead
978*7c568831SAndroid Build Coastguard Worker */
979*7c568831SAndroid Build Coastguard Worker void
xmlFreeElementContent(xmlElementContentPtr cur)980*7c568831SAndroid Build Coastguard Worker xmlFreeElementContent(xmlElementContentPtr cur) {
981*7c568831SAndroid Build Coastguard Worker xmlFreeDocElementContent(NULL, cur);
982*7c568831SAndroid Build Coastguard Worker }
983*7c568831SAndroid Build Coastguard Worker
984*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_OUTPUT_ENABLED
985*7c568831SAndroid Build Coastguard Worker /**
986*7c568831SAndroid Build Coastguard Worker * xmlSprintfElementContent:
987*7c568831SAndroid Build Coastguard Worker * @buf: an output buffer
988*7c568831SAndroid Build Coastguard Worker * @content: An element table
989*7c568831SAndroid Build Coastguard Worker * @englob: 1 if one must print the englobing parenthesis, 0 otherwise
990*7c568831SAndroid Build Coastguard Worker *
991*7c568831SAndroid Build Coastguard Worker * Deprecated, unsafe, use xmlSnprintfElementContent
992*7c568831SAndroid Build Coastguard Worker */
993*7c568831SAndroid Build Coastguard Worker void
xmlSprintfElementContent(char * buf ATTRIBUTE_UNUSED,xmlElementContentPtr content ATTRIBUTE_UNUSED,int englob ATTRIBUTE_UNUSED)994*7c568831SAndroid Build Coastguard Worker xmlSprintfElementContent(char *buf ATTRIBUTE_UNUSED,
995*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr content ATTRIBUTE_UNUSED,
996*7c568831SAndroid Build Coastguard Worker int englob ATTRIBUTE_UNUSED) {
997*7c568831SAndroid Build Coastguard Worker }
998*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_OUTPUT_ENABLED */
999*7c568831SAndroid Build Coastguard Worker
1000*7c568831SAndroid Build Coastguard Worker /**
1001*7c568831SAndroid Build Coastguard Worker * xmlSnprintfElementContent:
1002*7c568831SAndroid Build Coastguard Worker * @buf: an output buffer
1003*7c568831SAndroid Build Coastguard Worker * @size: the buffer size
1004*7c568831SAndroid Build Coastguard Worker * @content: An element table
1005*7c568831SAndroid Build Coastguard Worker * @englob: 1 if one must print the englobing parenthesis, 0 otherwise
1006*7c568831SAndroid Build Coastguard Worker *
1007*7c568831SAndroid Build Coastguard Worker * This will dump the content of the element content definition
1008*7c568831SAndroid Build Coastguard Worker * Intended just for the debug routine
1009*7c568831SAndroid Build Coastguard Worker */
1010*7c568831SAndroid Build Coastguard Worker void
xmlSnprintfElementContent(char * buf,int size,xmlElementContentPtr content,int englob)1011*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int englob) {
1012*7c568831SAndroid Build Coastguard Worker int len;
1013*7c568831SAndroid Build Coastguard Worker
1014*7c568831SAndroid Build Coastguard Worker if (content == NULL) return;
1015*7c568831SAndroid Build Coastguard Worker len = strlen(buf);
1016*7c568831SAndroid Build Coastguard Worker if (size - len < 50) {
1017*7c568831SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
1018*7c568831SAndroid Build Coastguard Worker strcat(buf, " ...");
1019*7c568831SAndroid Build Coastguard Worker return;
1020*7c568831SAndroid Build Coastguard Worker }
1021*7c568831SAndroid Build Coastguard Worker if (englob) strcat(buf, "(");
1022*7c568831SAndroid Build Coastguard Worker switch (content->type) {
1023*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
1024*7c568831SAndroid Build Coastguard Worker strcat(buf, "#PCDATA");
1025*7c568831SAndroid Build Coastguard Worker break;
1026*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT: {
1027*7c568831SAndroid Build Coastguard Worker int qnameLen = xmlStrlen(content->name);
1028*7c568831SAndroid Build Coastguard Worker
1029*7c568831SAndroid Build Coastguard Worker if (content->prefix != NULL)
1030*7c568831SAndroid Build Coastguard Worker qnameLen += xmlStrlen(content->prefix) + 1;
1031*7c568831SAndroid Build Coastguard Worker if (size - len < qnameLen + 10) {
1032*7c568831SAndroid Build Coastguard Worker strcat(buf, " ...");
1033*7c568831SAndroid Build Coastguard Worker return;
1034*7c568831SAndroid Build Coastguard Worker }
1035*7c568831SAndroid Build Coastguard Worker if (content->prefix != NULL) {
1036*7c568831SAndroid Build Coastguard Worker strcat(buf, (char *) content->prefix);
1037*7c568831SAndroid Build Coastguard Worker strcat(buf, ":");
1038*7c568831SAndroid Build Coastguard Worker }
1039*7c568831SAndroid Build Coastguard Worker if (content->name != NULL)
1040*7c568831SAndroid Build Coastguard Worker strcat(buf, (char *) content->name);
1041*7c568831SAndroid Build Coastguard Worker break;
1042*7c568831SAndroid Build Coastguard Worker }
1043*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
1044*7c568831SAndroid Build Coastguard Worker if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
1045*7c568831SAndroid Build Coastguard Worker (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
1046*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c1, 1);
1047*7c568831SAndroid Build Coastguard Worker else
1048*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c1, 0);
1049*7c568831SAndroid Build Coastguard Worker len = strlen(buf);
1050*7c568831SAndroid Build Coastguard Worker if (size - len < 50) {
1051*7c568831SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
1052*7c568831SAndroid Build Coastguard Worker strcat(buf, " ...");
1053*7c568831SAndroid Build Coastguard Worker return;
1054*7c568831SAndroid Build Coastguard Worker }
1055*7c568831SAndroid Build Coastguard Worker strcat(buf, " , ");
1056*7c568831SAndroid Build Coastguard Worker if (((content->c2->type == XML_ELEMENT_CONTENT_OR) ||
1057*7c568831SAndroid Build Coastguard Worker (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) &&
1058*7c568831SAndroid Build Coastguard Worker (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT))
1059*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c2, 1);
1060*7c568831SAndroid Build Coastguard Worker else
1061*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c2, 0);
1062*7c568831SAndroid Build Coastguard Worker break;
1063*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
1064*7c568831SAndroid Build Coastguard Worker if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
1065*7c568831SAndroid Build Coastguard Worker (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
1066*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c1, 1);
1067*7c568831SAndroid Build Coastguard Worker else
1068*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c1, 0);
1069*7c568831SAndroid Build Coastguard Worker len = strlen(buf);
1070*7c568831SAndroid Build Coastguard Worker if (size - len < 50) {
1071*7c568831SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
1072*7c568831SAndroid Build Coastguard Worker strcat(buf, " ...");
1073*7c568831SAndroid Build Coastguard Worker return;
1074*7c568831SAndroid Build Coastguard Worker }
1075*7c568831SAndroid Build Coastguard Worker strcat(buf, " | ");
1076*7c568831SAndroid Build Coastguard Worker if (((content->c2->type == XML_ELEMENT_CONTENT_SEQ) ||
1077*7c568831SAndroid Build Coastguard Worker (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) &&
1078*7c568831SAndroid Build Coastguard Worker (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT))
1079*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c2, 1);
1080*7c568831SAndroid Build Coastguard Worker else
1081*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c2, 0);
1082*7c568831SAndroid Build Coastguard Worker break;
1083*7c568831SAndroid Build Coastguard Worker }
1084*7c568831SAndroid Build Coastguard Worker if (size - strlen(buf) <= 2) return;
1085*7c568831SAndroid Build Coastguard Worker if (englob)
1086*7c568831SAndroid Build Coastguard Worker strcat(buf, ")");
1087*7c568831SAndroid Build Coastguard Worker switch (content->ocur) {
1088*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
1089*7c568831SAndroid Build Coastguard Worker break;
1090*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
1091*7c568831SAndroid Build Coastguard Worker strcat(buf, "?");
1092*7c568831SAndroid Build Coastguard Worker break;
1093*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
1094*7c568831SAndroid Build Coastguard Worker strcat(buf, "*");
1095*7c568831SAndroid Build Coastguard Worker break;
1096*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
1097*7c568831SAndroid Build Coastguard Worker strcat(buf, "+");
1098*7c568831SAndroid Build Coastguard Worker break;
1099*7c568831SAndroid Build Coastguard Worker }
1100*7c568831SAndroid Build Coastguard Worker }
1101*7c568831SAndroid Build Coastguard Worker
1102*7c568831SAndroid Build Coastguard Worker /****************************************************************
1103*7c568831SAndroid Build Coastguard Worker * *
1104*7c568831SAndroid Build Coastguard Worker * Registration of DTD declarations *
1105*7c568831SAndroid Build Coastguard Worker * *
1106*7c568831SAndroid Build Coastguard Worker ****************************************************************/
1107*7c568831SAndroid Build Coastguard Worker
1108*7c568831SAndroid Build Coastguard Worker /**
1109*7c568831SAndroid Build Coastguard Worker * xmlFreeElement:
1110*7c568831SAndroid Build Coastguard Worker * @elem: An element
1111*7c568831SAndroid Build Coastguard Worker *
1112*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by an element definition
1113*7c568831SAndroid Build Coastguard Worker */
1114*7c568831SAndroid Build Coastguard Worker static void
xmlFreeElement(xmlElementPtr elem)1115*7c568831SAndroid Build Coastguard Worker xmlFreeElement(xmlElementPtr elem) {
1116*7c568831SAndroid Build Coastguard Worker if (elem == NULL) return;
1117*7c568831SAndroid Build Coastguard Worker xmlUnlinkNode((xmlNodePtr) elem);
1118*7c568831SAndroid Build Coastguard Worker xmlFreeDocElementContent(elem->doc, elem->content);
1119*7c568831SAndroid Build Coastguard Worker if (elem->name != NULL)
1120*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) elem->name);
1121*7c568831SAndroid Build Coastguard Worker if (elem->prefix != NULL)
1122*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) elem->prefix);
1123*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
1124*7c568831SAndroid Build Coastguard Worker if (elem->contModel != NULL)
1125*7c568831SAndroid Build Coastguard Worker xmlRegFreeRegexp(elem->contModel);
1126*7c568831SAndroid Build Coastguard Worker #endif
1127*7c568831SAndroid Build Coastguard Worker xmlFree(elem);
1128*7c568831SAndroid Build Coastguard Worker }
1129*7c568831SAndroid Build Coastguard Worker
1130*7c568831SAndroid Build Coastguard Worker
1131*7c568831SAndroid Build Coastguard Worker /**
1132*7c568831SAndroid Build Coastguard Worker * xmlAddElementDecl:
1133*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
1134*7c568831SAndroid Build Coastguard Worker * @dtd: pointer to the DTD
1135*7c568831SAndroid Build Coastguard Worker * @name: the entity name
1136*7c568831SAndroid Build Coastguard Worker * @type: the element type
1137*7c568831SAndroid Build Coastguard Worker * @content: the element content tree or NULL
1138*7c568831SAndroid Build Coastguard Worker *
1139*7c568831SAndroid Build Coastguard Worker * Register a new element declaration
1140*7c568831SAndroid Build Coastguard Worker *
1141*7c568831SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the entity
1142*7c568831SAndroid Build Coastguard Worker */
1143*7c568831SAndroid Build Coastguard Worker xmlElementPtr
xmlAddElementDecl(xmlValidCtxtPtr ctxt,xmlDtdPtr dtd,const xmlChar * name,xmlElementTypeVal type,xmlElementContentPtr content)1144*7c568831SAndroid Build Coastguard Worker xmlAddElementDecl(xmlValidCtxtPtr ctxt,
1145*7c568831SAndroid Build Coastguard Worker xmlDtdPtr dtd, const xmlChar *name,
1146*7c568831SAndroid Build Coastguard Worker xmlElementTypeVal type,
1147*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr content) {
1148*7c568831SAndroid Build Coastguard Worker xmlElementPtr ret;
1149*7c568831SAndroid Build Coastguard Worker xmlElementTablePtr table;
1150*7c568831SAndroid Build Coastguard Worker xmlAttributePtr oldAttributes = NULL;
1151*7c568831SAndroid Build Coastguard Worker const xmlChar *localName;
1152*7c568831SAndroid Build Coastguard Worker xmlChar *prefix = NULL;
1153*7c568831SAndroid Build Coastguard Worker
1154*7c568831SAndroid Build Coastguard Worker if (dtd == NULL) {
1155*7c568831SAndroid Build Coastguard Worker return(NULL);
1156*7c568831SAndroid Build Coastguard Worker }
1157*7c568831SAndroid Build Coastguard Worker if (name == NULL) {
1158*7c568831SAndroid Build Coastguard Worker return(NULL);
1159*7c568831SAndroid Build Coastguard Worker }
1160*7c568831SAndroid Build Coastguard Worker
1161*7c568831SAndroid Build Coastguard Worker switch (type) {
1162*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_EMPTY:
1163*7c568831SAndroid Build Coastguard Worker if (content != NULL) {
1164*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
1165*7c568831SAndroid Build Coastguard Worker "xmlAddElementDecl: content != NULL for EMPTY\n",
1166*7c568831SAndroid Build Coastguard Worker NULL);
1167*7c568831SAndroid Build Coastguard Worker return(NULL);
1168*7c568831SAndroid Build Coastguard Worker }
1169*7c568831SAndroid Build Coastguard Worker break;
1170*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ANY:
1171*7c568831SAndroid Build Coastguard Worker if (content != NULL) {
1172*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
1173*7c568831SAndroid Build Coastguard Worker "xmlAddElementDecl: content != NULL for ANY\n",
1174*7c568831SAndroid Build Coastguard Worker NULL);
1175*7c568831SAndroid Build Coastguard Worker return(NULL);
1176*7c568831SAndroid Build Coastguard Worker }
1177*7c568831SAndroid Build Coastguard Worker break;
1178*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_MIXED:
1179*7c568831SAndroid Build Coastguard Worker if (content == NULL) {
1180*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
1181*7c568831SAndroid Build Coastguard Worker "xmlAddElementDecl: content == NULL for MIXED\n",
1182*7c568831SAndroid Build Coastguard Worker NULL);
1183*7c568831SAndroid Build Coastguard Worker return(NULL);
1184*7c568831SAndroid Build Coastguard Worker }
1185*7c568831SAndroid Build Coastguard Worker break;
1186*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ELEMENT:
1187*7c568831SAndroid Build Coastguard Worker if (content == NULL) {
1188*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
1189*7c568831SAndroid Build Coastguard Worker "xmlAddElementDecl: content == NULL for ELEMENT\n",
1190*7c568831SAndroid Build Coastguard Worker NULL);
1191*7c568831SAndroid Build Coastguard Worker return(NULL);
1192*7c568831SAndroid Build Coastguard Worker }
1193*7c568831SAndroid Build Coastguard Worker break;
1194*7c568831SAndroid Build Coastguard Worker default:
1195*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_ERR_ARGUMENT,
1196*7c568831SAndroid Build Coastguard Worker "xmlAddElementDecl: invalid type\n", NULL);
1197*7c568831SAndroid Build Coastguard Worker return(NULL);
1198*7c568831SAndroid Build Coastguard Worker }
1199*7c568831SAndroid Build Coastguard Worker
1200*7c568831SAndroid Build Coastguard Worker /*
1201*7c568831SAndroid Build Coastguard Worker * check if name is a QName
1202*7c568831SAndroid Build Coastguard Worker */
1203*7c568831SAndroid Build Coastguard Worker localName = xmlSplitQName4(name, &prefix);
1204*7c568831SAndroid Build Coastguard Worker if (localName == NULL)
1205*7c568831SAndroid Build Coastguard Worker goto mem_error;
1206*7c568831SAndroid Build Coastguard Worker
1207*7c568831SAndroid Build Coastguard Worker /*
1208*7c568831SAndroid Build Coastguard Worker * Create the Element table if needed.
1209*7c568831SAndroid Build Coastguard Worker */
1210*7c568831SAndroid Build Coastguard Worker table = (xmlElementTablePtr) dtd->elements;
1211*7c568831SAndroid Build Coastguard Worker if (table == NULL) {
1212*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
1213*7c568831SAndroid Build Coastguard Worker
1214*7c568831SAndroid Build Coastguard Worker if (dtd->doc != NULL)
1215*7c568831SAndroid Build Coastguard Worker dict = dtd->doc->dict;
1216*7c568831SAndroid Build Coastguard Worker table = xmlHashCreateDict(0, dict);
1217*7c568831SAndroid Build Coastguard Worker if (table == NULL)
1218*7c568831SAndroid Build Coastguard Worker goto mem_error;
1219*7c568831SAndroid Build Coastguard Worker dtd->elements = (void *) table;
1220*7c568831SAndroid Build Coastguard Worker }
1221*7c568831SAndroid Build Coastguard Worker
1222*7c568831SAndroid Build Coastguard Worker /*
1223*7c568831SAndroid Build Coastguard Worker * lookup old attributes inserted on an undefined element in the
1224*7c568831SAndroid Build Coastguard Worker * internal subset.
1225*7c568831SAndroid Build Coastguard Worker */
1226*7c568831SAndroid Build Coastguard Worker if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) {
1227*7c568831SAndroid Build Coastguard Worker ret = xmlHashLookup2(dtd->doc->intSubset->elements, localName, prefix);
1228*7c568831SAndroid Build Coastguard Worker if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) {
1229*7c568831SAndroid Build Coastguard Worker oldAttributes = ret->attributes;
1230*7c568831SAndroid Build Coastguard Worker ret->attributes = NULL;
1231*7c568831SAndroid Build Coastguard Worker xmlHashRemoveEntry2(dtd->doc->intSubset->elements, localName, prefix,
1232*7c568831SAndroid Build Coastguard Worker NULL);
1233*7c568831SAndroid Build Coastguard Worker xmlFreeElement(ret);
1234*7c568831SAndroid Build Coastguard Worker }
1235*7c568831SAndroid Build Coastguard Worker }
1236*7c568831SAndroid Build Coastguard Worker
1237*7c568831SAndroid Build Coastguard Worker /*
1238*7c568831SAndroid Build Coastguard Worker * The element may already be present if one of its attribute
1239*7c568831SAndroid Build Coastguard Worker * was registered first
1240*7c568831SAndroid Build Coastguard Worker */
1241*7c568831SAndroid Build Coastguard Worker ret = xmlHashLookup2(table, localName, prefix);
1242*7c568831SAndroid Build Coastguard Worker if (ret != NULL) {
1243*7c568831SAndroid Build Coastguard Worker if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) {
1244*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
1245*7c568831SAndroid Build Coastguard Worker /*
1246*7c568831SAndroid Build Coastguard Worker * The element is already defined in this DTD.
1247*7c568831SAndroid Build Coastguard Worker */
1248*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
1249*7c568831SAndroid Build Coastguard Worker "Redefinition of element %s\n",
1250*7c568831SAndroid Build Coastguard Worker name, NULL, NULL);
1251*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
1252*7c568831SAndroid Build Coastguard Worker if (prefix != NULL)
1253*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
1254*7c568831SAndroid Build Coastguard Worker return(NULL);
1255*7c568831SAndroid Build Coastguard Worker }
1256*7c568831SAndroid Build Coastguard Worker if (prefix != NULL) {
1257*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
1258*7c568831SAndroid Build Coastguard Worker prefix = NULL;
1259*7c568831SAndroid Build Coastguard Worker }
1260*7c568831SAndroid Build Coastguard Worker } else {
1261*7c568831SAndroid Build Coastguard Worker int res;
1262*7c568831SAndroid Build Coastguard Worker
1263*7c568831SAndroid Build Coastguard Worker ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
1264*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1265*7c568831SAndroid Build Coastguard Worker goto mem_error;
1266*7c568831SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlElement));
1267*7c568831SAndroid Build Coastguard Worker ret->type = XML_ELEMENT_DECL;
1268*7c568831SAndroid Build Coastguard Worker
1269*7c568831SAndroid Build Coastguard Worker /*
1270*7c568831SAndroid Build Coastguard Worker * fill the structure.
1271*7c568831SAndroid Build Coastguard Worker */
1272*7c568831SAndroid Build Coastguard Worker ret->name = xmlStrdup(localName);
1273*7c568831SAndroid Build Coastguard Worker if (ret->name == NULL) {
1274*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
1275*7c568831SAndroid Build Coastguard Worker goto mem_error;
1276*7c568831SAndroid Build Coastguard Worker }
1277*7c568831SAndroid Build Coastguard Worker ret->prefix = prefix;
1278*7c568831SAndroid Build Coastguard Worker prefix = NULL;
1279*7c568831SAndroid Build Coastguard Worker
1280*7c568831SAndroid Build Coastguard Worker /*
1281*7c568831SAndroid Build Coastguard Worker * Validity Check:
1282*7c568831SAndroid Build Coastguard Worker * Insertion must not fail
1283*7c568831SAndroid Build Coastguard Worker */
1284*7c568831SAndroid Build Coastguard Worker res = xmlHashAdd2(table, localName, ret->prefix, ret);
1285*7c568831SAndroid Build Coastguard Worker if (res <= 0) {
1286*7c568831SAndroid Build Coastguard Worker xmlFreeElement(ret);
1287*7c568831SAndroid Build Coastguard Worker goto mem_error;
1288*7c568831SAndroid Build Coastguard Worker }
1289*7c568831SAndroid Build Coastguard Worker /*
1290*7c568831SAndroid Build Coastguard Worker * For new element, may have attributes from earlier
1291*7c568831SAndroid Build Coastguard Worker * definition in internal subset
1292*7c568831SAndroid Build Coastguard Worker */
1293*7c568831SAndroid Build Coastguard Worker ret->attributes = oldAttributes;
1294*7c568831SAndroid Build Coastguard Worker }
1295*7c568831SAndroid Build Coastguard Worker
1296*7c568831SAndroid Build Coastguard Worker /*
1297*7c568831SAndroid Build Coastguard Worker * Finish to fill the structure.
1298*7c568831SAndroid Build Coastguard Worker */
1299*7c568831SAndroid Build Coastguard Worker ret->etype = type;
1300*7c568831SAndroid Build Coastguard Worker /*
1301*7c568831SAndroid Build Coastguard Worker * Avoid a stupid copy when called by the parser
1302*7c568831SAndroid Build Coastguard Worker * and flag it by setting a special parent value
1303*7c568831SAndroid Build Coastguard Worker * so the parser doesn't unallocate it.
1304*7c568831SAndroid Build Coastguard Worker */
1305*7c568831SAndroid Build Coastguard Worker if (content != NULL) {
1306*7c568831SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->flags & XML_VCTXT_USE_PCTXT)) {
1307*7c568831SAndroid Build Coastguard Worker ret->content = content;
1308*7c568831SAndroid Build Coastguard Worker content->parent = (xmlElementContentPtr) 1;
1309*7c568831SAndroid Build Coastguard Worker } else if (content != NULL){
1310*7c568831SAndroid Build Coastguard Worker ret->content = xmlCopyDocElementContent(dtd->doc, content);
1311*7c568831SAndroid Build Coastguard Worker if (ret->content == NULL)
1312*7c568831SAndroid Build Coastguard Worker goto mem_error;
1313*7c568831SAndroid Build Coastguard Worker }
1314*7c568831SAndroid Build Coastguard Worker }
1315*7c568831SAndroid Build Coastguard Worker
1316*7c568831SAndroid Build Coastguard Worker /*
1317*7c568831SAndroid Build Coastguard Worker * Link it to the DTD
1318*7c568831SAndroid Build Coastguard Worker */
1319*7c568831SAndroid Build Coastguard Worker ret->parent = dtd;
1320*7c568831SAndroid Build Coastguard Worker ret->doc = dtd->doc;
1321*7c568831SAndroid Build Coastguard Worker if (dtd->last == NULL) {
1322*7c568831SAndroid Build Coastguard Worker dtd->children = dtd->last = (xmlNodePtr) ret;
1323*7c568831SAndroid Build Coastguard Worker } else {
1324*7c568831SAndroid Build Coastguard Worker dtd->last->next = (xmlNodePtr) ret;
1325*7c568831SAndroid Build Coastguard Worker ret->prev = dtd->last;
1326*7c568831SAndroid Build Coastguard Worker dtd->last = (xmlNodePtr) ret;
1327*7c568831SAndroid Build Coastguard Worker }
1328*7c568831SAndroid Build Coastguard Worker if (prefix != NULL)
1329*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
1330*7c568831SAndroid Build Coastguard Worker return(ret);
1331*7c568831SAndroid Build Coastguard Worker
1332*7c568831SAndroid Build Coastguard Worker mem_error:
1333*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
1334*7c568831SAndroid Build Coastguard Worker if (prefix != NULL)
1335*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
1336*7c568831SAndroid Build Coastguard Worker return(NULL);
1337*7c568831SAndroid Build Coastguard Worker }
1338*7c568831SAndroid Build Coastguard Worker
1339*7c568831SAndroid Build Coastguard Worker static void
xmlFreeElementTableEntry(void * elem,const xmlChar * name ATTRIBUTE_UNUSED)1340*7c568831SAndroid Build Coastguard Worker xmlFreeElementTableEntry(void *elem, const xmlChar *name ATTRIBUTE_UNUSED) {
1341*7c568831SAndroid Build Coastguard Worker xmlFreeElement((xmlElementPtr) elem);
1342*7c568831SAndroid Build Coastguard Worker }
1343*7c568831SAndroid Build Coastguard Worker
1344*7c568831SAndroid Build Coastguard Worker /**
1345*7c568831SAndroid Build Coastguard Worker * xmlFreeElementTable:
1346*7c568831SAndroid Build Coastguard Worker * @table: An element table
1347*7c568831SAndroid Build Coastguard Worker *
1348*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by an element hash table.
1349*7c568831SAndroid Build Coastguard Worker */
1350*7c568831SAndroid Build Coastguard Worker void
xmlFreeElementTable(xmlElementTablePtr table)1351*7c568831SAndroid Build Coastguard Worker xmlFreeElementTable(xmlElementTablePtr table) {
1352*7c568831SAndroid Build Coastguard Worker xmlHashFree(table, xmlFreeElementTableEntry);
1353*7c568831SAndroid Build Coastguard Worker }
1354*7c568831SAndroid Build Coastguard Worker
1355*7c568831SAndroid Build Coastguard Worker /**
1356*7c568831SAndroid Build Coastguard Worker * xmlCopyElement:
1357*7c568831SAndroid Build Coastguard Worker * @elem: An element
1358*7c568831SAndroid Build Coastguard Worker *
1359*7c568831SAndroid Build Coastguard Worker * Build a copy of an element.
1360*7c568831SAndroid Build Coastguard Worker *
1361*7c568831SAndroid Build Coastguard Worker * Returns the new xmlElementPtr or NULL in case of error.
1362*7c568831SAndroid Build Coastguard Worker */
1363*7c568831SAndroid Build Coastguard Worker static void *
xmlCopyElement(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)1364*7c568831SAndroid Build Coastguard Worker xmlCopyElement(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
1365*7c568831SAndroid Build Coastguard Worker xmlElementPtr elem = (xmlElementPtr) payload;
1366*7c568831SAndroid Build Coastguard Worker xmlElementPtr cur;
1367*7c568831SAndroid Build Coastguard Worker
1368*7c568831SAndroid Build Coastguard Worker cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
1369*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
1370*7c568831SAndroid Build Coastguard Worker return(NULL);
1371*7c568831SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlElement));
1372*7c568831SAndroid Build Coastguard Worker cur->type = XML_ELEMENT_DECL;
1373*7c568831SAndroid Build Coastguard Worker cur->etype = elem->etype;
1374*7c568831SAndroid Build Coastguard Worker if (elem->name != NULL) {
1375*7c568831SAndroid Build Coastguard Worker cur->name = xmlStrdup(elem->name);
1376*7c568831SAndroid Build Coastguard Worker if (cur->name == NULL)
1377*7c568831SAndroid Build Coastguard Worker goto error;
1378*7c568831SAndroid Build Coastguard Worker }
1379*7c568831SAndroid Build Coastguard Worker if (elem->prefix != NULL) {
1380*7c568831SAndroid Build Coastguard Worker cur->prefix = xmlStrdup(elem->prefix);
1381*7c568831SAndroid Build Coastguard Worker if (cur->prefix == NULL)
1382*7c568831SAndroid Build Coastguard Worker goto error;
1383*7c568831SAndroid Build Coastguard Worker }
1384*7c568831SAndroid Build Coastguard Worker if (elem->content != NULL) {
1385*7c568831SAndroid Build Coastguard Worker cur->content = xmlCopyElementContent(elem->content);
1386*7c568831SAndroid Build Coastguard Worker if (cur->content == NULL)
1387*7c568831SAndroid Build Coastguard Worker goto error;
1388*7c568831SAndroid Build Coastguard Worker }
1389*7c568831SAndroid Build Coastguard Worker /* TODO : rebuild the attribute list on the copy */
1390*7c568831SAndroid Build Coastguard Worker cur->attributes = NULL;
1391*7c568831SAndroid Build Coastguard Worker return(cur);
1392*7c568831SAndroid Build Coastguard Worker
1393*7c568831SAndroid Build Coastguard Worker error:
1394*7c568831SAndroid Build Coastguard Worker xmlFreeElement(cur);
1395*7c568831SAndroid Build Coastguard Worker return(NULL);
1396*7c568831SAndroid Build Coastguard Worker }
1397*7c568831SAndroid Build Coastguard Worker
1398*7c568831SAndroid Build Coastguard Worker /**
1399*7c568831SAndroid Build Coastguard Worker * xmlCopyElementTable:
1400*7c568831SAndroid Build Coastguard Worker * @table: An element table
1401*7c568831SAndroid Build Coastguard Worker *
1402*7c568831SAndroid Build Coastguard Worker * Build a copy of an element table.
1403*7c568831SAndroid Build Coastguard Worker *
1404*7c568831SAndroid Build Coastguard Worker * Returns the new xmlElementTablePtr or NULL in case of error.
1405*7c568831SAndroid Build Coastguard Worker */
1406*7c568831SAndroid Build Coastguard Worker xmlElementTablePtr
xmlCopyElementTable(xmlElementTablePtr table)1407*7c568831SAndroid Build Coastguard Worker xmlCopyElementTable(xmlElementTablePtr table) {
1408*7c568831SAndroid Build Coastguard Worker return(xmlHashCopySafe(table, xmlCopyElement, xmlFreeElementTableEntry));
1409*7c568831SAndroid Build Coastguard Worker }
1410*7c568831SAndroid Build Coastguard Worker
1411*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_OUTPUT_ENABLED
1412*7c568831SAndroid Build Coastguard Worker /**
1413*7c568831SAndroid Build Coastguard Worker * xmlDumpElementDecl:
1414*7c568831SAndroid Build Coastguard Worker * @buf: the XML buffer output
1415*7c568831SAndroid Build Coastguard Worker * @elem: An element table
1416*7c568831SAndroid Build Coastguard Worker *
1417*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Use xmlSaveTree.
1418*7c568831SAndroid Build Coastguard Worker *
1419*7c568831SAndroid Build Coastguard Worker * This will dump the content of the element declaration as an XML
1420*7c568831SAndroid Build Coastguard Worker * DTD definition
1421*7c568831SAndroid Build Coastguard Worker */
1422*7c568831SAndroid Build Coastguard Worker void
xmlDumpElementDecl(xmlBufferPtr buf,xmlElementPtr elem)1423*7c568831SAndroid Build Coastguard Worker xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
1424*7c568831SAndroid Build Coastguard Worker xmlSaveCtxtPtr save;
1425*7c568831SAndroid Build Coastguard Worker
1426*7c568831SAndroid Build Coastguard Worker if ((buf == NULL) || (elem == NULL))
1427*7c568831SAndroid Build Coastguard Worker return;
1428*7c568831SAndroid Build Coastguard Worker
1429*7c568831SAndroid Build Coastguard Worker save = xmlSaveToBuffer(buf, NULL, 0);
1430*7c568831SAndroid Build Coastguard Worker xmlSaveTree(save, (xmlNodePtr) elem);
1431*7c568831SAndroid Build Coastguard Worker if (xmlSaveFinish(save) != XML_ERR_OK)
1432*7c568831SAndroid Build Coastguard Worker xmlFree(xmlBufferDetach(buf));
1433*7c568831SAndroid Build Coastguard Worker }
1434*7c568831SAndroid Build Coastguard Worker
1435*7c568831SAndroid Build Coastguard Worker /**
1436*7c568831SAndroid Build Coastguard Worker * xmlDumpElementDeclScan:
1437*7c568831SAndroid Build Coastguard Worker * @elem: An element table
1438*7c568831SAndroid Build Coastguard Worker * @buf: the XML buffer output
1439*7c568831SAndroid Build Coastguard Worker *
1440*7c568831SAndroid Build Coastguard Worker * This routine is used by the hash scan function. It just reverses
1441*7c568831SAndroid Build Coastguard Worker * the arguments.
1442*7c568831SAndroid Build Coastguard Worker */
1443*7c568831SAndroid Build Coastguard Worker static void
xmlDumpElementDeclScan(void * elem,void * save,const xmlChar * name ATTRIBUTE_UNUSED)1444*7c568831SAndroid Build Coastguard Worker xmlDumpElementDeclScan(void *elem, void *save,
1445*7c568831SAndroid Build Coastguard Worker const xmlChar *name ATTRIBUTE_UNUSED) {
1446*7c568831SAndroid Build Coastguard Worker xmlSaveTree(save, elem);
1447*7c568831SAndroid Build Coastguard Worker }
1448*7c568831SAndroid Build Coastguard Worker
1449*7c568831SAndroid Build Coastguard Worker /**
1450*7c568831SAndroid Build Coastguard Worker * xmlDumpElementTable:
1451*7c568831SAndroid Build Coastguard Worker * @buf: the XML buffer output
1452*7c568831SAndroid Build Coastguard Worker * @table: An element table
1453*7c568831SAndroid Build Coastguard Worker *
1454*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Don't use.
1455*7c568831SAndroid Build Coastguard Worker *
1456*7c568831SAndroid Build Coastguard Worker * This will dump the content of the element table as an XML DTD definition
1457*7c568831SAndroid Build Coastguard Worker */
1458*7c568831SAndroid Build Coastguard Worker void
xmlDumpElementTable(xmlBufferPtr buf,xmlElementTablePtr table)1459*7c568831SAndroid Build Coastguard Worker xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
1460*7c568831SAndroid Build Coastguard Worker xmlSaveCtxtPtr save;
1461*7c568831SAndroid Build Coastguard Worker
1462*7c568831SAndroid Build Coastguard Worker if ((buf == NULL) || (table == NULL))
1463*7c568831SAndroid Build Coastguard Worker return;
1464*7c568831SAndroid Build Coastguard Worker
1465*7c568831SAndroid Build Coastguard Worker save = xmlSaveToBuffer(buf, NULL, 0);
1466*7c568831SAndroid Build Coastguard Worker xmlHashScan(table, xmlDumpElementDeclScan, save);
1467*7c568831SAndroid Build Coastguard Worker if (xmlSaveFinish(save) != XML_ERR_OK)
1468*7c568831SAndroid Build Coastguard Worker xmlFree(xmlBufferDetach(buf));
1469*7c568831SAndroid Build Coastguard Worker }
1470*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_OUTPUT_ENABLED */
1471*7c568831SAndroid Build Coastguard Worker
1472*7c568831SAndroid Build Coastguard Worker /**
1473*7c568831SAndroid Build Coastguard Worker * xmlCreateEnumeration:
1474*7c568831SAndroid Build Coastguard Worker * @name: the enumeration name or NULL
1475*7c568831SAndroid Build Coastguard Worker *
1476*7c568831SAndroid Build Coastguard Worker * create and initialize an enumeration attribute node.
1477*7c568831SAndroid Build Coastguard Worker *
1478*7c568831SAndroid Build Coastguard Worker * Returns the xmlEnumerationPtr just created or NULL in case
1479*7c568831SAndroid Build Coastguard Worker * of error.
1480*7c568831SAndroid Build Coastguard Worker */
1481*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr
xmlCreateEnumeration(const xmlChar * name)1482*7c568831SAndroid Build Coastguard Worker xmlCreateEnumeration(const xmlChar *name) {
1483*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr ret;
1484*7c568831SAndroid Build Coastguard Worker
1485*7c568831SAndroid Build Coastguard Worker ret = (xmlEnumerationPtr) xmlMalloc(sizeof(xmlEnumeration));
1486*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1487*7c568831SAndroid Build Coastguard Worker return(NULL);
1488*7c568831SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlEnumeration));
1489*7c568831SAndroid Build Coastguard Worker
1490*7c568831SAndroid Build Coastguard Worker if (name != NULL) {
1491*7c568831SAndroid Build Coastguard Worker ret->name = xmlStrdup(name);
1492*7c568831SAndroid Build Coastguard Worker if (ret->name == NULL) {
1493*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
1494*7c568831SAndroid Build Coastguard Worker return(NULL);
1495*7c568831SAndroid Build Coastguard Worker }
1496*7c568831SAndroid Build Coastguard Worker }
1497*7c568831SAndroid Build Coastguard Worker
1498*7c568831SAndroid Build Coastguard Worker return(ret);
1499*7c568831SAndroid Build Coastguard Worker }
1500*7c568831SAndroid Build Coastguard Worker
1501*7c568831SAndroid Build Coastguard Worker /**
1502*7c568831SAndroid Build Coastguard Worker * xmlFreeEnumeration:
1503*7c568831SAndroid Build Coastguard Worker * @cur: the tree to free.
1504*7c568831SAndroid Build Coastguard Worker *
1505*7c568831SAndroid Build Coastguard Worker * free an enumeration attribute node (recursive).
1506*7c568831SAndroid Build Coastguard Worker */
1507*7c568831SAndroid Build Coastguard Worker void
xmlFreeEnumeration(xmlEnumerationPtr cur)1508*7c568831SAndroid Build Coastguard Worker xmlFreeEnumeration(xmlEnumerationPtr cur) {
1509*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
1510*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr next = cur->next;
1511*7c568831SAndroid Build Coastguard Worker
1512*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) cur->name);
1513*7c568831SAndroid Build Coastguard Worker xmlFree(cur);
1514*7c568831SAndroid Build Coastguard Worker
1515*7c568831SAndroid Build Coastguard Worker cur = next;
1516*7c568831SAndroid Build Coastguard Worker }
1517*7c568831SAndroid Build Coastguard Worker }
1518*7c568831SAndroid Build Coastguard Worker
1519*7c568831SAndroid Build Coastguard Worker /**
1520*7c568831SAndroid Build Coastguard Worker * xmlCopyEnumeration:
1521*7c568831SAndroid Build Coastguard Worker * @cur: the tree to copy.
1522*7c568831SAndroid Build Coastguard Worker *
1523*7c568831SAndroid Build Coastguard Worker * Copy an enumeration attribute node (recursive).
1524*7c568831SAndroid Build Coastguard Worker *
1525*7c568831SAndroid Build Coastguard Worker * Returns the xmlEnumerationPtr just created or NULL in case
1526*7c568831SAndroid Build Coastguard Worker * of error.
1527*7c568831SAndroid Build Coastguard Worker */
1528*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr
xmlCopyEnumeration(xmlEnumerationPtr cur)1529*7c568831SAndroid Build Coastguard Worker xmlCopyEnumeration(xmlEnumerationPtr cur) {
1530*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr ret = NULL;
1531*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr last = NULL;
1532*7c568831SAndroid Build Coastguard Worker
1533*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
1534*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr copy = xmlCreateEnumeration(cur->name);
1535*7c568831SAndroid Build Coastguard Worker
1536*7c568831SAndroid Build Coastguard Worker if (copy == NULL) {
1537*7c568831SAndroid Build Coastguard Worker xmlFreeEnumeration(ret);
1538*7c568831SAndroid Build Coastguard Worker return(NULL);
1539*7c568831SAndroid Build Coastguard Worker }
1540*7c568831SAndroid Build Coastguard Worker
1541*7c568831SAndroid Build Coastguard Worker if (ret == NULL) {
1542*7c568831SAndroid Build Coastguard Worker ret = last = copy;
1543*7c568831SAndroid Build Coastguard Worker } else {
1544*7c568831SAndroid Build Coastguard Worker last->next = copy;
1545*7c568831SAndroid Build Coastguard Worker last = copy;
1546*7c568831SAndroid Build Coastguard Worker }
1547*7c568831SAndroid Build Coastguard Worker
1548*7c568831SAndroid Build Coastguard Worker cur = cur->next;
1549*7c568831SAndroid Build Coastguard Worker }
1550*7c568831SAndroid Build Coastguard Worker
1551*7c568831SAndroid Build Coastguard Worker return(ret);
1552*7c568831SAndroid Build Coastguard Worker }
1553*7c568831SAndroid Build Coastguard Worker
1554*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
1555*7c568831SAndroid Build Coastguard Worker /**
1556*7c568831SAndroid Build Coastguard Worker * xmlScanIDAttributeDecl:
1557*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
1558*7c568831SAndroid Build Coastguard Worker * @elem: the element name
1559*7c568831SAndroid Build Coastguard Worker * @err: whether to raise errors here
1560*7c568831SAndroid Build Coastguard Worker *
1561*7c568831SAndroid Build Coastguard Worker * Verify that the element don't have too many ID attributes
1562*7c568831SAndroid Build Coastguard Worker * declared.
1563*7c568831SAndroid Build Coastguard Worker *
1564*7c568831SAndroid Build Coastguard Worker * Returns the number of ID attributes found.
1565*7c568831SAndroid Build Coastguard Worker */
1566*7c568831SAndroid Build Coastguard Worker static int
xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt,xmlElementPtr elem,int err)1567*7c568831SAndroid Build Coastguard Worker xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt, xmlElementPtr elem, int err) {
1568*7c568831SAndroid Build Coastguard Worker xmlAttributePtr cur;
1569*7c568831SAndroid Build Coastguard Worker int ret = 0;
1570*7c568831SAndroid Build Coastguard Worker
1571*7c568831SAndroid Build Coastguard Worker if (elem == NULL) return(0);
1572*7c568831SAndroid Build Coastguard Worker cur = elem->attributes;
1573*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
1574*7c568831SAndroid Build Coastguard Worker if (cur->atype == XML_ATTRIBUTE_ID) {
1575*7c568831SAndroid Build Coastguard Worker ret ++;
1576*7c568831SAndroid Build Coastguard Worker if ((ret > 1) && (err))
1577*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_MULTIPLE_ID,
1578*7c568831SAndroid Build Coastguard Worker "Element %s has too many ID attributes defined : %s\n",
1579*7c568831SAndroid Build Coastguard Worker elem->name, cur->name, NULL);
1580*7c568831SAndroid Build Coastguard Worker }
1581*7c568831SAndroid Build Coastguard Worker cur = cur->nexth;
1582*7c568831SAndroid Build Coastguard Worker }
1583*7c568831SAndroid Build Coastguard Worker return(ret);
1584*7c568831SAndroid Build Coastguard Worker }
1585*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
1586*7c568831SAndroid Build Coastguard Worker
1587*7c568831SAndroid Build Coastguard Worker /**
1588*7c568831SAndroid Build Coastguard Worker * xmlFreeAttribute:
1589*7c568831SAndroid Build Coastguard Worker * @elem: An attribute
1590*7c568831SAndroid Build Coastguard Worker *
1591*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by an attribute definition
1592*7c568831SAndroid Build Coastguard Worker */
1593*7c568831SAndroid Build Coastguard Worker static void
xmlFreeAttribute(xmlAttributePtr attr)1594*7c568831SAndroid Build Coastguard Worker xmlFreeAttribute(xmlAttributePtr attr) {
1595*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict;
1596*7c568831SAndroid Build Coastguard Worker
1597*7c568831SAndroid Build Coastguard Worker if (attr == NULL) return;
1598*7c568831SAndroid Build Coastguard Worker if (attr->doc != NULL)
1599*7c568831SAndroid Build Coastguard Worker dict = attr->doc->dict;
1600*7c568831SAndroid Build Coastguard Worker else
1601*7c568831SAndroid Build Coastguard Worker dict = NULL;
1602*7c568831SAndroid Build Coastguard Worker xmlUnlinkNode((xmlNodePtr) attr);
1603*7c568831SAndroid Build Coastguard Worker if (attr->tree != NULL)
1604*7c568831SAndroid Build Coastguard Worker xmlFreeEnumeration(attr->tree);
1605*7c568831SAndroid Build Coastguard Worker if (dict) {
1606*7c568831SAndroid Build Coastguard Worker if ((attr->elem != NULL) && (!xmlDictOwns(dict, attr->elem)))
1607*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->elem);
1608*7c568831SAndroid Build Coastguard Worker if ((attr->name != NULL) && (!xmlDictOwns(dict, attr->name)))
1609*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->name);
1610*7c568831SAndroid Build Coastguard Worker if ((attr->prefix != NULL) && (!xmlDictOwns(dict, attr->prefix)))
1611*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->prefix);
1612*7c568831SAndroid Build Coastguard Worker if ((attr->defaultValue != NULL) &&
1613*7c568831SAndroid Build Coastguard Worker (!xmlDictOwns(dict, attr->defaultValue)))
1614*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->defaultValue);
1615*7c568831SAndroid Build Coastguard Worker } else {
1616*7c568831SAndroid Build Coastguard Worker if (attr->elem != NULL)
1617*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->elem);
1618*7c568831SAndroid Build Coastguard Worker if (attr->name != NULL)
1619*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->name);
1620*7c568831SAndroid Build Coastguard Worker if (attr->defaultValue != NULL)
1621*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->defaultValue);
1622*7c568831SAndroid Build Coastguard Worker if (attr->prefix != NULL)
1623*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->prefix);
1624*7c568831SAndroid Build Coastguard Worker }
1625*7c568831SAndroid Build Coastguard Worker xmlFree(attr);
1626*7c568831SAndroid Build Coastguard Worker }
1627*7c568831SAndroid Build Coastguard Worker
1628*7c568831SAndroid Build Coastguard Worker
1629*7c568831SAndroid Build Coastguard Worker /**
1630*7c568831SAndroid Build Coastguard Worker * xmlAddAttributeDecl:
1631*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
1632*7c568831SAndroid Build Coastguard Worker * @dtd: pointer to the DTD
1633*7c568831SAndroid Build Coastguard Worker * @elem: the element name
1634*7c568831SAndroid Build Coastguard Worker * @name: the attribute name
1635*7c568831SAndroid Build Coastguard Worker * @ns: the attribute namespace prefix
1636*7c568831SAndroid Build Coastguard Worker * @type: the attribute type
1637*7c568831SAndroid Build Coastguard Worker * @def: the attribute default type
1638*7c568831SAndroid Build Coastguard Worker * @defaultValue: the attribute default value
1639*7c568831SAndroid Build Coastguard Worker * @tree: if it's an enumeration, the associated list
1640*7c568831SAndroid Build Coastguard Worker *
1641*7c568831SAndroid Build Coastguard Worker * Register a new attribute declaration
1642*7c568831SAndroid Build Coastguard Worker * Note that @tree becomes the ownership of the DTD
1643*7c568831SAndroid Build Coastguard Worker *
1644*7c568831SAndroid Build Coastguard Worker * Returns NULL if not new, otherwise the attribute decl
1645*7c568831SAndroid Build Coastguard Worker */
1646*7c568831SAndroid Build Coastguard Worker xmlAttributePtr
xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,xmlDtdPtr dtd,const xmlChar * elem,const xmlChar * name,const xmlChar * ns,xmlAttributeType type,xmlAttributeDefault def,const xmlChar * defaultValue,xmlEnumerationPtr tree)1647*7c568831SAndroid Build Coastguard Worker xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,
1648*7c568831SAndroid Build Coastguard Worker xmlDtdPtr dtd, const xmlChar *elem,
1649*7c568831SAndroid Build Coastguard Worker const xmlChar *name, const xmlChar *ns,
1650*7c568831SAndroid Build Coastguard Worker xmlAttributeType type, xmlAttributeDefault def,
1651*7c568831SAndroid Build Coastguard Worker const xmlChar *defaultValue, xmlEnumerationPtr tree) {
1652*7c568831SAndroid Build Coastguard Worker xmlAttributePtr ret = NULL;
1653*7c568831SAndroid Build Coastguard Worker xmlAttributeTablePtr table;
1654*7c568831SAndroid Build Coastguard Worker xmlElementPtr elemDef;
1655*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
1656*7c568831SAndroid Build Coastguard Worker int res;
1657*7c568831SAndroid Build Coastguard Worker
1658*7c568831SAndroid Build Coastguard Worker if (dtd == NULL) {
1659*7c568831SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1660*7c568831SAndroid Build Coastguard Worker return(NULL);
1661*7c568831SAndroid Build Coastguard Worker }
1662*7c568831SAndroid Build Coastguard Worker if (name == NULL) {
1663*7c568831SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1664*7c568831SAndroid Build Coastguard Worker return(NULL);
1665*7c568831SAndroid Build Coastguard Worker }
1666*7c568831SAndroid Build Coastguard Worker if (elem == NULL) {
1667*7c568831SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1668*7c568831SAndroid Build Coastguard Worker return(NULL);
1669*7c568831SAndroid Build Coastguard Worker }
1670*7c568831SAndroid Build Coastguard Worker if (dtd->doc != NULL)
1671*7c568831SAndroid Build Coastguard Worker dict = dtd->doc->dict;
1672*7c568831SAndroid Build Coastguard Worker
1673*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
1674*7c568831SAndroid Build Coastguard Worker /*
1675*7c568831SAndroid Build Coastguard Worker * Check the type and possibly the default value.
1676*7c568831SAndroid Build Coastguard Worker */
1677*7c568831SAndroid Build Coastguard Worker switch (type) {
1678*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_CDATA:
1679*7c568831SAndroid Build Coastguard Worker break;
1680*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ID:
1681*7c568831SAndroid Build Coastguard Worker break;
1682*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREF:
1683*7c568831SAndroid Build Coastguard Worker break;
1684*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREFS:
1685*7c568831SAndroid Build Coastguard Worker break;
1686*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITY:
1687*7c568831SAndroid Build Coastguard Worker break;
1688*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITIES:
1689*7c568831SAndroid Build Coastguard Worker break;
1690*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKEN:
1691*7c568831SAndroid Build Coastguard Worker break;
1692*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKENS:
1693*7c568831SAndroid Build Coastguard Worker break;
1694*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENUMERATION:
1695*7c568831SAndroid Build Coastguard Worker break;
1696*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NOTATION:
1697*7c568831SAndroid Build Coastguard Worker break;
1698*7c568831SAndroid Build Coastguard Worker default:
1699*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_ERR_ARGUMENT,
1700*7c568831SAndroid Build Coastguard Worker "xmlAddAttributeDecl: invalid type\n", NULL);
1701*7c568831SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1702*7c568831SAndroid Build Coastguard Worker return(NULL);
1703*7c568831SAndroid Build Coastguard Worker }
1704*7c568831SAndroid Build Coastguard Worker if ((defaultValue != NULL) &&
1705*7c568831SAndroid Build Coastguard Worker (!xmlValidateAttributeValueInternal(dtd->doc, type, defaultValue))) {
1706*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_DEFAULT,
1707*7c568831SAndroid Build Coastguard Worker "Attribute %s of %s: invalid default value\n",
1708*7c568831SAndroid Build Coastguard Worker elem, name, defaultValue);
1709*7c568831SAndroid Build Coastguard Worker defaultValue = NULL;
1710*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL)
1711*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
1712*7c568831SAndroid Build Coastguard Worker }
1713*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
1714*7c568831SAndroid Build Coastguard Worker
1715*7c568831SAndroid Build Coastguard Worker /*
1716*7c568831SAndroid Build Coastguard Worker * Check first that an attribute defined in the external subset wasn't
1717*7c568831SAndroid Build Coastguard Worker * already defined in the internal subset
1718*7c568831SAndroid Build Coastguard Worker */
1719*7c568831SAndroid Build Coastguard Worker if ((dtd->doc != NULL) && (dtd->doc->extSubset == dtd) &&
1720*7c568831SAndroid Build Coastguard Worker (dtd->doc->intSubset != NULL) &&
1721*7c568831SAndroid Build Coastguard Worker (dtd->doc->intSubset->attributes != NULL)) {
1722*7c568831SAndroid Build Coastguard Worker ret = xmlHashLookup3(dtd->doc->intSubset->attributes, name, ns, elem);
1723*7c568831SAndroid Build Coastguard Worker if (ret != NULL) {
1724*7c568831SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1725*7c568831SAndroid Build Coastguard Worker return(NULL);
1726*7c568831SAndroid Build Coastguard Worker }
1727*7c568831SAndroid Build Coastguard Worker }
1728*7c568831SAndroid Build Coastguard Worker
1729*7c568831SAndroid Build Coastguard Worker /*
1730*7c568831SAndroid Build Coastguard Worker * Create the Attribute table if needed.
1731*7c568831SAndroid Build Coastguard Worker */
1732*7c568831SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) dtd->attributes;
1733*7c568831SAndroid Build Coastguard Worker if (table == NULL) {
1734*7c568831SAndroid Build Coastguard Worker table = xmlHashCreateDict(0, dict);
1735*7c568831SAndroid Build Coastguard Worker dtd->attributes = (void *) table;
1736*7c568831SAndroid Build Coastguard Worker }
1737*7c568831SAndroid Build Coastguard Worker if (table == NULL)
1738*7c568831SAndroid Build Coastguard Worker goto mem_error;
1739*7c568831SAndroid Build Coastguard Worker
1740*7c568831SAndroid Build Coastguard Worker ret = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
1741*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1742*7c568831SAndroid Build Coastguard Worker goto mem_error;
1743*7c568831SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlAttribute));
1744*7c568831SAndroid Build Coastguard Worker ret->type = XML_ATTRIBUTE_DECL;
1745*7c568831SAndroid Build Coastguard Worker
1746*7c568831SAndroid Build Coastguard Worker /*
1747*7c568831SAndroid Build Coastguard Worker * fill the structure.
1748*7c568831SAndroid Build Coastguard Worker */
1749*7c568831SAndroid Build Coastguard Worker ret->atype = type;
1750*7c568831SAndroid Build Coastguard Worker /*
1751*7c568831SAndroid Build Coastguard Worker * doc must be set before possible error causes call
1752*7c568831SAndroid Build Coastguard Worker * to xmlFreeAttribute (because it's used to check on
1753*7c568831SAndroid Build Coastguard Worker * dict use)
1754*7c568831SAndroid Build Coastguard Worker */
1755*7c568831SAndroid Build Coastguard Worker ret->doc = dtd->doc;
1756*7c568831SAndroid Build Coastguard Worker if (dict) {
1757*7c568831SAndroid Build Coastguard Worker ret->name = xmlDictLookup(dict, name, -1);
1758*7c568831SAndroid Build Coastguard Worker ret->elem = xmlDictLookup(dict, elem, -1);
1759*7c568831SAndroid Build Coastguard Worker } else {
1760*7c568831SAndroid Build Coastguard Worker ret->name = xmlStrdup(name);
1761*7c568831SAndroid Build Coastguard Worker ret->elem = xmlStrdup(elem);
1762*7c568831SAndroid Build Coastguard Worker }
1763*7c568831SAndroid Build Coastguard Worker if ((ret->name == NULL) || (ret->elem == NULL))
1764*7c568831SAndroid Build Coastguard Worker goto mem_error;
1765*7c568831SAndroid Build Coastguard Worker if (ns != NULL) {
1766*7c568831SAndroid Build Coastguard Worker if (dict)
1767*7c568831SAndroid Build Coastguard Worker ret->prefix = xmlDictLookup(dict, ns, -1);
1768*7c568831SAndroid Build Coastguard Worker else
1769*7c568831SAndroid Build Coastguard Worker ret->prefix = xmlStrdup(ns);
1770*7c568831SAndroid Build Coastguard Worker if (ret->prefix == NULL)
1771*7c568831SAndroid Build Coastguard Worker goto mem_error;
1772*7c568831SAndroid Build Coastguard Worker }
1773*7c568831SAndroid Build Coastguard Worker ret->def = def;
1774*7c568831SAndroid Build Coastguard Worker ret->tree = tree;
1775*7c568831SAndroid Build Coastguard Worker tree = NULL;
1776*7c568831SAndroid Build Coastguard Worker if (defaultValue != NULL) {
1777*7c568831SAndroid Build Coastguard Worker if (dict)
1778*7c568831SAndroid Build Coastguard Worker ret->defaultValue = xmlDictLookup(dict, defaultValue, -1);
1779*7c568831SAndroid Build Coastguard Worker else
1780*7c568831SAndroid Build Coastguard Worker ret->defaultValue = xmlStrdup(defaultValue);
1781*7c568831SAndroid Build Coastguard Worker if (ret->defaultValue == NULL)
1782*7c568831SAndroid Build Coastguard Worker goto mem_error;
1783*7c568831SAndroid Build Coastguard Worker }
1784*7c568831SAndroid Build Coastguard Worker
1785*7c568831SAndroid Build Coastguard Worker elemDef = xmlGetDtdElementDesc2(ctxt, dtd, elem);
1786*7c568831SAndroid Build Coastguard Worker if (elemDef == NULL)
1787*7c568831SAndroid Build Coastguard Worker goto mem_error;
1788*7c568831SAndroid Build Coastguard Worker
1789*7c568831SAndroid Build Coastguard Worker /*
1790*7c568831SAndroid Build Coastguard Worker * Validity Check:
1791*7c568831SAndroid Build Coastguard Worker * Search the DTD for previous declarations of the ATTLIST
1792*7c568831SAndroid Build Coastguard Worker */
1793*7c568831SAndroid Build Coastguard Worker res = xmlHashAdd3(table, ret->name, ret->prefix, ret->elem, ret);
1794*7c568831SAndroid Build Coastguard Worker if (res <= 0) {
1795*7c568831SAndroid Build Coastguard Worker if (res < 0)
1796*7c568831SAndroid Build Coastguard Worker goto mem_error;
1797*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
1798*7c568831SAndroid Build Coastguard Worker /*
1799*7c568831SAndroid Build Coastguard Worker * The attribute is already defined in this DTD.
1800*7c568831SAndroid Build Coastguard Worker */
1801*7c568831SAndroid Build Coastguard Worker xmlErrValidWarning(ctxt, (xmlNodePtr) dtd,
1802*7c568831SAndroid Build Coastguard Worker XML_DTD_ATTRIBUTE_REDEFINED,
1803*7c568831SAndroid Build Coastguard Worker "Attribute %s of element %s: already defined\n",
1804*7c568831SAndroid Build Coastguard Worker name, elem, NULL);
1805*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
1806*7c568831SAndroid Build Coastguard Worker xmlFreeAttribute(ret);
1807*7c568831SAndroid Build Coastguard Worker return(NULL);
1808*7c568831SAndroid Build Coastguard Worker }
1809*7c568831SAndroid Build Coastguard Worker
1810*7c568831SAndroid Build Coastguard Worker /*
1811*7c568831SAndroid Build Coastguard Worker * Validity Check:
1812*7c568831SAndroid Build Coastguard Worker * Multiple ID per element
1813*7c568831SAndroid Build Coastguard Worker */
1814*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
1815*7c568831SAndroid Build Coastguard Worker if ((type == XML_ATTRIBUTE_ID) &&
1816*7c568831SAndroid Build Coastguard Worker (xmlScanIDAttributeDecl(ctxt, elemDef, 1) != 0)) {
1817*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_MULTIPLE_ID,
1818*7c568831SAndroid Build Coastguard Worker "Element %s has too may ID attributes defined : %s\n",
1819*7c568831SAndroid Build Coastguard Worker elem, name, NULL);
1820*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL)
1821*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
1822*7c568831SAndroid Build Coastguard Worker }
1823*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
1824*7c568831SAndroid Build Coastguard Worker
1825*7c568831SAndroid Build Coastguard Worker /*
1826*7c568831SAndroid Build Coastguard Worker * Insert namespace default def first they need to be
1827*7c568831SAndroid Build Coastguard Worker * processed first.
1828*7c568831SAndroid Build Coastguard Worker */
1829*7c568831SAndroid Build Coastguard Worker if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) ||
1830*7c568831SAndroid Build Coastguard Worker ((ret->prefix != NULL &&
1831*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) {
1832*7c568831SAndroid Build Coastguard Worker ret->nexth = elemDef->attributes;
1833*7c568831SAndroid Build Coastguard Worker elemDef->attributes = ret;
1834*7c568831SAndroid Build Coastguard Worker } else {
1835*7c568831SAndroid Build Coastguard Worker xmlAttributePtr tmp = elemDef->attributes;
1836*7c568831SAndroid Build Coastguard Worker
1837*7c568831SAndroid Build Coastguard Worker while ((tmp != NULL) &&
1838*7c568831SAndroid Build Coastguard Worker ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) ||
1839*7c568831SAndroid Build Coastguard Worker ((ret->prefix != NULL &&
1840*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) {
1841*7c568831SAndroid Build Coastguard Worker if (tmp->nexth == NULL)
1842*7c568831SAndroid Build Coastguard Worker break;
1843*7c568831SAndroid Build Coastguard Worker tmp = tmp->nexth;
1844*7c568831SAndroid Build Coastguard Worker }
1845*7c568831SAndroid Build Coastguard Worker if (tmp != NULL) {
1846*7c568831SAndroid Build Coastguard Worker ret->nexth = tmp->nexth;
1847*7c568831SAndroid Build Coastguard Worker tmp->nexth = ret;
1848*7c568831SAndroid Build Coastguard Worker } else {
1849*7c568831SAndroid Build Coastguard Worker ret->nexth = elemDef->attributes;
1850*7c568831SAndroid Build Coastguard Worker elemDef->attributes = ret;
1851*7c568831SAndroid Build Coastguard Worker }
1852*7c568831SAndroid Build Coastguard Worker }
1853*7c568831SAndroid Build Coastguard Worker
1854*7c568831SAndroid Build Coastguard Worker /*
1855*7c568831SAndroid Build Coastguard Worker * Link it to the DTD
1856*7c568831SAndroid Build Coastguard Worker */
1857*7c568831SAndroid Build Coastguard Worker ret->parent = dtd;
1858*7c568831SAndroid Build Coastguard Worker if (dtd->last == NULL) {
1859*7c568831SAndroid Build Coastguard Worker dtd->children = dtd->last = (xmlNodePtr) ret;
1860*7c568831SAndroid Build Coastguard Worker } else {
1861*7c568831SAndroid Build Coastguard Worker dtd->last->next = (xmlNodePtr) ret;
1862*7c568831SAndroid Build Coastguard Worker ret->prev = dtd->last;
1863*7c568831SAndroid Build Coastguard Worker dtd->last = (xmlNodePtr) ret;
1864*7c568831SAndroid Build Coastguard Worker }
1865*7c568831SAndroid Build Coastguard Worker return(ret);
1866*7c568831SAndroid Build Coastguard Worker
1867*7c568831SAndroid Build Coastguard Worker mem_error:
1868*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
1869*7c568831SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1870*7c568831SAndroid Build Coastguard Worker xmlFreeAttribute(ret);
1871*7c568831SAndroid Build Coastguard Worker return(NULL);
1872*7c568831SAndroid Build Coastguard Worker }
1873*7c568831SAndroid Build Coastguard Worker
1874*7c568831SAndroid Build Coastguard Worker static void
xmlFreeAttributeTableEntry(void * attr,const xmlChar * name ATTRIBUTE_UNUSED)1875*7c568831SAndroid Build Coastguard Worker xmlFreeAttributeTableEntry(void *attr, const xmlChar *name ATTRIBUTE_UNUSED) {
1876*7c568831SAndroid Build Coastguard Worker xmlFreeAttribute((xmlAttributePtr) attr);
1877*7c568831SAndroid Build Coastguard Worker }
1878*7c568831SAndroid Build Coastguard Worker
1879*7c568831SAndroid Build Coastguard Worker /**
1880*7c568831SAndroid Build Coastguard Worker * xmlFreeAttributeTable:
1881*7c568831SAndroid Build Coastguard Worker * @table: An attribute table
1882*7c568831SAndroid Build Coastguard Worker *
1883*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by an entities hash table.
1884*7c568831SAndroid Build Coastguard Worker */
1885*7c568831SAndroid Build Coastguard Worker void
xmlFreeAttributeTable(xmlAttributeTablePtr table)1886*7c568831SAndroid Build Coastguard Worker xmlFreeAttributeTable(xmlAttributeTablePtr table) {
1887*7c568831SAndroid Build Coastguard Worker xmlHashFree(table, xmlFreeAttributeTableEntry);
1888*7c568831SAndroid Build Coastguard Worker }
1889*7c568831SAndroid Build Coastguard Worker
1890*7c568831SAndroid Build Coastguard Worker /**
1891*7c568831SAndroid Build Coastguard Worker * xmlCopyAttribute:
1892*7c568831SAndroid Build Coastguard Worker * @attr: An attribute
1893*7c568831SAndroid Build Coastguard Worker *
1894*7c568831SAndroid Build Coastguard Worker * Build a copy of an attribute.
1895*7c568831SAndroid Build Coastguard Worker *
1896*7c568831SAndroid Build Coastguard Worker * Returns the new xmlAttributePtr or NULL in case of error.
1897*7c568831SAndroid Build Coastguard Worker */
1898*7c568831SAndroid Build Coastguard Worker static void *
xmlCopyAttribute(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)1899*7c568831SAndroid Build Coastguard Worker xmlCopyAttribute(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
1900*7c568831SAndroid Build Coastguard Worker xmlAttributePtr attr = (xmlAttributePtr) payload;
1901*7c568831SAndroid Build Coastguard Worker xmlAttributePtr cur;
1902*7c568831SAndroid Build Coastguard Worker
1903*7c568831SAndroid Build Coastguard Worker cur = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
1904*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
1905*7c568831SAndroid Build Coastguard Worker return(NULL);
1906*7c568831SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlAttribute));
1907*7c568831SAndroid Build Coastguard Worker cur->type = XML_ATTRIBUTE_DECL;
1908*7c568831SAndroid Build Coastguard Worker cur->atype = attr->atype;
1909*7c568831SAndroid Build Coastguard Worker cur->def = attr->def;
1910*7c568831SAndroid Build Coastguard Worker if (attr->tree != NULL) {
1911*7c568831SAndroid Build Coastguard Worker cur->tree = xmlCopyEnumeration(attr->tree);
1912*7c568831SAndroid Build Coastguard Worker if (cur->tree == NULL)
1913*7c568831SAndroid Build Coastguard Worker goto error;
1914*7c568831SAndroid Build Coastguard Worker }
1915*7c568831SAndroid Build Coastguard Worker if (attr->elem != NULL) {
1916*7c568831SAndroid Build Coastguard Worker cur->elem = xmlStrdup(attr->elem);
1917*7c568831SAndroid Build Coastguard Worker if (cur->elem == NULL)
1918*7c568831SAndroid Build Coastguard Worker goto error;
1919*7c568831SAndroid Build Coastguard Worker }
1920*7c568831SAndroid Build Coastguard Worker if (attr->name != NULL) {
1921*7c568831SAndroid Build Coastguard Worker cur->name = xmlStrdup(attr->name);
1922*7c568831SAndroid Build Coastguard Worker if (cur->name == NULL)
1923*7c568831SAndroid Build Coastguard Worker goto error;
1924*7c568831SAndroid Build Coastguard Worker }
1925*7c568831SAndroid Build Coastguard Worker if (attr->prefix != NULL) {
1926*7c568831SAndroid Build Coastguard Worker cur->prefix = xmlStrdup(attr->prefix);
1927*7c568831SAndroid Build Coastguard Worker if (cur->prefix == NULL)
1928*7c568831SAndroid Build Coastguard Worker goto error;
1929*7c568831SAndroid Build Coastguard Worker }
1930*7c568831SAndroid Build Coastguard Worker if (attr->defaultValue != NULL) {
1931*7c568831SAndroid Build Coastguard Worker cur->defaultValue = xmlStrdup(attr->defaultValue);
1932*7c568831SAndroid Build Coastguard Worker if (cur->defaultValue == NULL)
1933*7c568831SAndroid Build Coastguard Worker goto error;
1934*7c568831SAndroid Build Coastguard Worker }
1935*7c568831SAndroid Build Coastguard Worker return(cur);
1936*7c568831SAndroid Build Coastguard Worker
1937*7c568831SAndroid Build Coastguard Worker error:
1938*7c568831SAndroid Build Coastguard Worker xmlFreeAttribute(cur);
1939*7c568831SAndroid Build Coastguard Worker return(NULL);
1940*7c568831SAndroid Build Coastguard Worker }
1941*7c568831SAndroid Build Coastguard Worker
1942*7c568831SAndroid Build Coastguard Worker /**
1943*7c568831SAndroid Build Coastguard Worker * xmlCopyAttributeTable:
1944*7c568831SAndroid Build Coastguard Worker * @table: An attribute table
1945*7c568831SAndroid Build Coastguard Worker *
1946*7c568831SAndroid Build Coastguard Worker * Build a copy of an attribute table.
1947*7c568831SAndroid Build Coastguard Worker *
1948*7c568831SAndroid Build Coastguard Worker * Returns the new xmlAttributeTablePtr or NULL in case of error.
1949*7c568831SAndroid Build Coastguard Worker */
1950*7c568831SAndroid Build Coastguard Worker xmlAttributeTablePtr
xmlCopyAttributeTable(xmlAttributeTablePtr table)1951*7c568831SAndroid Build Coastguard Worker xmlCopyAttributeTable(xmlAttributeTablePtr table) {
1952*7c568831SAndroid Build Coastguard Worker return(xmlHashCopySafe(table, xmlCopyAttribute,
1953*7c568831SAndroid Build Coastguard Worker xmlFreeAttributeTableEntry));
1954*7c568831SAndroid Build Coastguard Worker }
1955*7c568831SAndroid Build Coastguard Worker
1956*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_OUTPUT_ENABLED
1957*7c568831SAndroid Build Coastguard Worker /**
1958*7c568831SAndroid Build Coastguard Worker * xmlDumpAttributeDecl:
1959*7c568831SAndroid Build Coastguard Worker * @buf: the XML buffer output
1960*7c568831SAndroid Build Coastguard Worker * @attr: An attribute declaration
1961*7c568831SAndroid Build Coastguard Worker *
1962*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Use xmlSaveTree.
1963*7c568831SAndroid Build Coastguard Worker *
1964*7c568831SAndroid Build Coastguard Worker * This will dump the content of the attribute declaration as an XML
1965*7c568831SAndroid Build Coastguard Worker * DTD definition
1966*7c568831SAndroid Build Coastguard Worker */
1967*7c568831SAndroid Build Coastguard Worker void
xmlDumpAttributeDecl(xmlBufferPtr buf,xmlAttributePtr attr)1968*7c568831SAndroid Build Coastguard Worker xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
1969*7c568831SAndroid Build Coastguard Worker xmlSaveCtxtPtr save;
1970*7c568831SAndroid Build Coastguard Worker
1971*7c568831SAndroid Build Coastguard Worker if ((buf == NULL) || (attr == NULL))
1972*7c568831SAndroid Build Coastguard Worker return;
1973*7c568831SAndroid Build Coastguard Worker
1974*7c568831SAndroid Build Coastguard Worker save = xmlSaveToBuffer(buf, NULL, 0);
1975*7c568831SAndroid Build Coastguard Worker xmlSaveTree(save, (xmlNodePtr) attr);
1976*7c568831SAndroid Build Coastguard Worker if (xmlSaveFinish(save) != XML_ERR_OK)
1977*7c568831SAndroid Build Coastguard Worker xmlFree(xmlBufferDetach(buf));
1978*7c568831SAndroid Build Coastguard Worker }
1979*7c568831SAndroid Build Coastguard Worker
1980*7c568831SAndroid Build Coastguard Worker /**
1981*7c568831SAndroid Build Coastguard Worker * xmlDumpAttributeDeclScan:
1982*7c568831SAndroid Build Coastguard Worker * @attr: An attribute declaration
1983*7c568831SAndroid Build Coastguard Worker * @buf: the XML buffer output
1984*7c568831SAndroid Build Coastguard Worker *
1985*7c568831SAndroid Build Coastguard Worker * This is used with the hash scan function - just reverses arguments
1986*7c568831SAndroid Build Coastguard Worker */
1987*7c568831SAndroid Build Coastguard Worker static void
xmlDumpAttributeDeclScan(void * attr,void * save,const xmlChar * name ATTRIBUTE_UNUSED)1988*7c568831SAndroid Build Coastguard Worker xmlDumpAttributeDeclScan(void *attr, void *save,
1989*7c568831SAndroid Build Coastguard Worker const xmlChar *name ATTRIBUTE_UNUSED) {
1990*7c568831SAndroid Build Coastguard Worker xmlSaveTree(save, attr);
1991*7c568831SAndroid Build Coastguard Worker }
1992*7c568831SAndroid Build Coastguard Worker
1993*7c568831SAndroid Build Coastguard Worker /**
1994*7c568831SAndroid Build Coastguard Worker * xmlDumpAttributeTable:
1995*7c568831SAndroid Build Coastguard Worker * @buf: the XML buffer output
1996*7c568831SAndroid Build Coastguard Worker * @table: An attribute table
1997*7c568831SAndroid Build Coastguard Worker *
1998*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Don't use.
1999*7c568831SAndroid Build Coastguard Worker *
2000*7c568831SAndroid Build Coastguard Worker * This will dump the content of the attribute table as an XML DTD definition
2001*7c568831SAndroid Build Coastguard Worker */
2002*7c568831SAndroid Build Coastguard Worker void
xmlDumpAttributeTable(xmlBufferPtr buf,xmlAttributeTablePtr table)2003*7c568831SAndroid Build Coastguard Worker xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
2004*7c568831SAndroid Build Coastguard Worker xmlSaveCtxtPtr save;
2005*7c568831SAndroid Build Coastguard Worker
2006*7c568831SAndroid Build Coastguard Worker if ((buf == NULL) || (table == NULL))
2007*7c568831SAndroid Build Coastguard Worker return;
2008*7c568831SAndroid Build Coastguard Worker
2009*7c568831SAndroid Build Coastguard Worker save = xmlSaveToBuffer(buf, NULL, 0);
2010*7c568831SAndroid Build Coastguard Worker xmlHashScan(table, xmlDumpAttributeDeclScan, save);
2011*7c568831SAndroid Build Coastguard Worker if (xmlSaveFinish(save) != XML_ERR_OK)
2012*7c568831SAndroid Build Coastguard Worker xmlFree(xmlBufferDetach(buf));
2013*7c568831SAndroid Build Coastguard Worker }
2014*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_OUTPUT_ENABLED */
2015*7c568831SAndroid Build Coastguard Worker
2016*7c568831SAndroid Build Coastguard Worker /************************************************************************
2017*7c568831SAndroid Build Coastguard Worker * *
2018*7c568831SAndroid Build Coastguard Worker * NOTATIONs *
2019*7c568831SAndroid Build Coastguard Worker * *
2020*7c568831SAndroid Build Coastguard Worker ************************************************************************/
2021*7c568831SAndroid Build Coastguard Worker /**
2022*7c568831SAndroid Build Coastguard Worker * xmlFreeNotation:
2023*7c568831SAndroid Build Coastguard Worker * @not: A notation
2024*7c568831SAndroid Build Coastguard Worker *
2025*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by an notation definition
2026*7c568831SAndroid Build Coastguard Worker */
2027*7c568831SAndroid Build Coastguard Worker static void
xmlFreeNotation(xmlNotationPtr nota)2028*7c568831SAndroid Build Coastguard Worker xmlFreeNotation(xmlNotationPtr nota) {
2029*7c568831SAndroid Build Coastguard Worker if (nota == NULL) return;
2030*7c568831SAndroid Build Coastguard Worker if (nota->name != NULL)
2031*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) nota->name);
2032*7c568831SAndroid Build Coastguard Worker if (nota->PublicID != NULL)
2033*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) nota->PublicID);
2034*7c568831SAndroid Build Coastguard Worker if (nota->SystemID != NULL)
2035*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) nota->SystemID);
2036*7c568831SAndroid Build Coastguard Worker xmlFree(nota);
2037*7c568831SAndroid Build Coastguard Worker }
2038*7c568831SAndroid Build Coastguard Worker
2039*7c568831SAndroid Build Coastguard Worker
2040*7c568831SAndroid Build Coastguard Worker /**
2041*7c568831SAndroid Build Coastguard Worker * xmlAddNotationDecl:
2042*7c568831SAndroid Build Coastguard Worker * @dtd: pointer to the DTD
2043*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
2044*7c568831SAndroid Build Coastguard Worker * @name: the entity name
2045*7c568831SAndroid Build Coastguard Worker * @PublicID: the public identifier or NULL
2046*7c568831SAndroid Build Coastguard Worker * @SystemID: the system identifier or NULL
2047*7c568831SAndroid Build Coastguard Worker *
2048*7c568831SAndroid Build Coastguard Worker * Register a new notation declaration
2049*7c568831SAndroid Build Coastguard Worker *
2050*7c568831SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the entity
2051*7c568831SAndroid Build Coastguard Worker */
2052*7c568831SAndroid Build Coastguard Worker xmlNotationPtr
xmlAddNotationDecl(xmlValidCtxtPtr ctxt,xmlDtdPtr dtd,const xmlChar * name,const xmlChar * PublicID,const xmlChar * SystemID)2053*7c568831SAndroid Build Coastguard Worker xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd,
2054*7c568831SAndroid Build Coastguard Worker const xmlChar *name,
2055*7c568831SAndroid Build Coastguard Worker const xmlChar *PublicID, const xmlChar *SystemID) {
2056*7c568831SAndroid Build Coastguard Worker xmlNotationPtr ret = NULL;
2057*7c568831SAndroid Build Coastguard Worker xmlNotationTablePtr table;
2058*7c568831SAndroid Build Coastguard Worker int res;
2059*7c568831SAndroid Build Coastguard Worker
2060*7c568831SAndroid Build Coastguard Worker if (dtd == NULL) {
2061*7c568831SAndroid Build Coastguard Worker return(NULL);
2062*7c568831SAndroid Build Coastguard Worker }
2063*7c568831SAndroid Build Coastguard Worker if (name == NULL) {
2064*7c568831SAndroid Build Coastguard Worker return(NULL);
2065*7c568831SAndroid Build Coastguard Worker }
2066*7c568831SAndroid Build Coastguard Worker if ((PublicID == NULL) && (SystemID == NULL)) {
2067*7c568831SAndroid Build Coastguard Worker return(NULL);
2068*7c568831SAndroid Build Coastguard Worker }
2069*7c568831SAndroid Build Coastguard Worker
2070*7c568831SAndroid Build Coastguard Worker /*
2071*7c568831SAndroid Build Coastguard Worker * Create the Notation table if needed.
2072*7c568831SAndroid Build Coastguard Worker */
2073*7c568831SAndroid Build Coastguard Worker table = (xmlNotationTablePtr) dtd->notations;
2074*7c568831SAndroid Build Coastguard Worker if (table == NULL) {
2075*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
2076*7c568831SAndroid Build Coastguard Worker if (dtd->doc != NULL)
2077*7c568831SAndroid Build Coastguard Worker dict = dtd->doc->dict;
2078*7c568831SAndroid Build Coastguard Worker
2079*7c568831SAndroid Build Coastguard Worker dtd->notations = table = xmlHashCreateDict(0, dict);
2080*7c568831SAndroid Build Coastguard Worker if (table == NULL)
2081*7c568831SAndroid Build Coastguard Worker goto mem_error;
2082*7c568831SAndroid Build Coastguard Worker }
2083*7c568831SAndroid Build Coastguard Worker
2084*7c568831SAndroid Build Coastguard Worker ret = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
2085*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
2086*7c568831SAndroid Build Coastguard Worker goto mem_error;
2087*7c568831SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlNotation));
2088*7c568831SAndroid Build Coastguard Worker
2089*7c568831SAndroid Build Coastguard Worker /*
2090*7c568831SAndroid Build Coastguard Worker * fill the structure.
2091*7c568831SAndroid Build Coastguard Worker */
2092*7c568831SAndroid Build Coastguard Worker ret->name = xmlStrdup(name);
2093*7c568831SAndroid Build Coastguard Worker if (ret->name == NULL)
2094*7c568831SAndroid Build Coastguard Worker goto mem_error;
2095*7c568831SAndroid Build Coastguard Worker if (SystemID != NULL) {
2096*7c568831SAndroid Build Coastguard Worker ret->SystemID = xmlStrdup(SystemID);
2097*7c568831SAndroid Build Coastguard Worker if (ret->SystemID == NULL)
2098*7c568831SAndroid Build Coastguard Worker goto mem_error;
2099*7c568831SAndroid Build Coastguard Worker }
2100*7c568831SAndroid Build Coastguard Worker if (PublicID != NULL) {
2101*7c568831SAndroid Build Coastguard Worker ret->PublicID = xmlStrdup(PublicID);
2102*7c568831SAndroid Build Coastguard Worker if (ret->PublicID == NULL)
2103*7c568831SAndroid Build Coastguard Worker goto mem_error;
2104*7c568831SAndroid Build Coastguard Worker }
2105*7c568831SAndroid Build Coastguard Worker
2106*7c568831SAndroid Build Coastguard Worker /*
2107*7c568831SAndroid Build Coastguard Worker * Validity Check:
2108*7c568831SAndroid Build Coastguard Worker * Check the DTD for previous declarations of the ATTLIST
2109*7c568831SAndroid Build Coastguard Worker */
2110*7c568831SAndroid Build Coastguard Worker res = xmlHashAdd(table, name, ret);
2111*7c568831SAndroid Build Coastguard Worker if (res <= 0) {
2112*7c568831SAndroid Build Coastguard Worker if (res < 0)
2113*7c568831SAndroid Build Coastguard Worker goto mem_error;
2114*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
2115*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_NOTATION_REDEFINED,
2116*7c568831SAndroid Build Coastguard Worker "xmlAddNotationDecl: %s already defined\n",
2117*7c568831SAndroid Build Coastguard Worker (const char *) name);
2118*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
2119*7c568831SAndroid Build Coastguard Worker xmlFreeNotation(ret);
2120*7c568831SAndroid Build Coastguard Worker return(NULL);
2121*7c568831SAndroid Build Coastguard Worker }
2122*7c568831SAndroid Build Coastguard Worker return(ret);
2123*7c568831SAndroid Build Coastguard Worker
2124*7c568831SAndroid Build Coastguard Worker mem_error:
2125*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
2126*7c568831SAndroid Build Coastguard Worker xmlFreeNotation(ret);
2127*7c568831SAndroid Build Coastguard Worker return(NULL);
2128*7c568831SAndroid Build Coastguard Worker }
2129*7c568831SAndroid Build Coastguard Worker
2130*7c568831SAndroid Build Coastguard Worker static void
xmlFreeNotationTableEntry(void * nota,const xmlChar * name ATTRIBUTE_UNUSED)2131*7c568831SAndroid Build Coastguard Worker xmlFreeNotationTableEntry(void *nota, const xmlChar *name ATTRIBUTE_UNUSED) {
2132*7c568831SAndroid Build Coastguard Worker xmlFreeNotation((xmlNotationPtr) nota);
2133*7c568831SAndroid Build Coastguard Worker }
2134*7c568831SAndroid Build Coastguard Worker
2135*7c568831SAndroid Build Coastguard Worker /**
2136*7c568831SAndroid Build Coastguard Worker * xmlFreeNotationTable:
2137*7c568831SAndroid Build Coastguard Worker * @table: An notation table
2138*7c568831SAndroid Build Coastguard Worker *
2139*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by an entities hash table.
2140*7c568831SAndroid Build Coastguard Worker */
2141*7c568831SAndroid Build Coastguard Worker void
xmlFreeNotationTable(xmlNotationTablePtr table)2142*7c568831SAndroid Build Coastguard Worker xmlFreeNotationTable(xmlNotationTablePtr table) {
2143*7c568831SAndroid Build Coastguard Worker xmlHashFree(table, xmlFreeNotationTableEntry);
2144*7c568831SAndroid Build Coastguard Worker }
2145*7c568831SAndroid Build Coastguard Worker
2146*7c568831SAndroid Build Coastguard Worker /**
2147*7c568831SAndroid Build Coastguard Worker * xmlCopyNotation:
2148*7c568831SAndroid Build Coastguard Worker * @nota: A notation
2149*7c568831SAndroid Build Coastguard Worker *
2150*7c568831SAndroid Build Coastguard Worker * Build a copy of a notation.
2151*7c568831SAndroid Build Coastguard Worker *
2152*7c568831SAndroid Build Coastguard Worker * Returns the new xmlNotationPtr or NULL in case of error.
2153*7c568831SAndroid Build Coastguard Worker */
2154*7c568831SAndroid Build Coastguard Worker static void *
xmlCopyNotation(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)2155*7c568831SAndroid Build Coastguard Worker xmlCopyNotation(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
2156*7c568831SAndroid Build Coastguard Worker xmlNotationPtr nota = (xmlNotationPtr) payload;
2157*7c568831SAndroid Build Coastguard Worker xmlNotationPtr cur;
2158*7c568831SAndroid Build Coastguard Worker
2159*7c568831SAndroid Build Coastguard Worker cur = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
2160*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
2161*7c568831SAndroid Build Coastguard Worker return(NULL);
2162*7c568831SAndroid Build Coastguard Worker memset(cur, 0, sizeof(*cur));
2163*7c568831SAndroid Build Coastguard Worker if (nota->name != NULL) {
2164*7c568831SAndroid Build Coastguard Worker cur->name = xmlStrdup(nota->name);
2165*7c568831SAndroid Build Coastguard Worker if (cur->name == NULL)
2166*7c568831SAndroid Build Coastguard Worker goto error;
2167*7c568831SAndroid Build Coastguard Worker }
2168*7c568831SAndroid Build Coastguard Worker if (nota->PublicID != NULL) {
2169*7c568831SAndroid Build Coastguard Worker cur->PublicID = xmlStrdup(nota->PublicID);
2170*7c568831SAndroid Build Coastguard Worker if (cur->PublicID == NULL)
2171*7c568831SAndroid Build Coastguard Worker goto error;
2172*7c568831SAndroid Build Coastguard Worker }
2173*7c568831SAndroid Build Coastguard Worker if (nota->SystemID != NULL) {
2174*7c568831SAndroid Build Coastguard Worker cur->SystemID = xmlStrdup(nota->SystemID);
2175*7c568831SAndroid Build Coastguard Worker if (cur->SystemID == NULL)
2176*7c568831SAndroid Build Coastguard Worker goto error;
2177*7c568831SAndroid Build Coastguard Worker }
2178*7c568831SAndroid Build Coastguard Worker return(cur);
2179*7c568831SAndroid Build Coastguard Worker
2180*7c568831SAndroid Build Coastguard Worker error:
2181*7c568831SAndroid Build Coastguard Worker xmlFreeNotation(cur);
2182*7c568831SAndroid Build Coastguard Worker return(NULL);
2183*7c568831SAndroid Build Coastguard Worker }
2184*7c568831SAndroid Build Coastguard Worker
2185*7c568831SAndroid Build Coastguard Worker /**
2186*7c568831SAndroid Build Coastguard Worker * xmlCopyNotationTable:
2187*7c568831SAndroid Build Coastguard Worker * @table: A notation table
2188*7c568831SAndroid Build Coastguard Worker *
2189*7c568831SAndroid Build Coastguard Worker * Build a copy of a notation table.
2190*7c568831SAndroid Build Coastguard Worker *
2191*7c568831SAndroid Build Coastguard Worker * Returns the new xmlNotationTablePtr or NULL in case of error.
2192*7c568831SAndroid Build Coastguard Worker */
2193*7c568831SAndroid Build Coastguard Worker xmlNotationTablePtr
xmlCopyNotationTable(xmlNotationTablePtr table)2194*7c568831SAndroid Build Coastguard Worker xmlCopyNotationTable(xmlNotationTablePtr table) {
2195*7c568831SAndroid Build Coastguard Worker return(xmlHashCopySafe(table, xmlCopyNotation, xmlFreeNotationTableEntry));
2196*7c568831SAndroid Build Coastguard Worker }
2197*7c568831SAndroid Build Coastguard Worker
2198*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_OUTPUT_ENABLED
2199*7c568831SAndroid Build Coastguard Worker /**
2200*7c568831SAndroid Build Coastguard Worker * xmlDumpNotationDecl:
2201*7c568831SAndroid Build Coastguard Worker * @buf: the XML buffer output
2202*7c568831SAndroid Build Coastguard Worker * @nota: A notation declaration
2203*7c568831SAndroid Build Coastguard Worker *
2204*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Don't use.
2205*7c568831SAndroid Build Coastguard Worker *
2206*7c568831SAndroid Build Coastguard Worker * This will dump the content the notation declaration as an XML DTD definition
2207*7c568831SAndroid Build Coastguard Worker */
2208*7c568831SAndroid Build Coastguard Worker void
xmlDumpNotationDecl(xmlBufferPtr buf,xmlNotationPtr nota)2209*7c568831SAndroid Build Coastguard Worker xmlDumpNotationDecl(xmlBufferPtr buf, xmlNotationPtr nota) {
2210*7c568831SAndroid Build Coastguard Worker xmlSaveCtxtPtr save;
2211*7c568831SAndroid Build Coastguard Worker
2212*7c568831SAndroid Build Coastguard Worker if ((buf == NULL) || (nota == NULL))
2213*7c568831SAndroid Build Coastguard Worker return;
2214*7c568831SAndroid Build Coastguard Worker
2215*7c568831SAndroid Build Coastguard Worker save = xmlSaveToBuffer(buf, NULL, 0);
2216*7c568831SAndroid Build Coastguard Worker xmlSaveNotationDecl(save, nota);
2217*7c568831SAndroid Build Coastguard Worker if (xmlSaveFinish(save) != XML_ERR_OK)
2218*7c568831SAndroid Build Coastguard Worker xmlFree(xmlBufferDetach(buf));
2219*7c568831SAndroid Build Coastguard Worker }
2220*7c568831SAndroid Build Coastguard Worker
2221*7c568831SAndroid Build Coastguard Worker /**
2222*7c568831SAndroid Build Coastguard Worker * xmlDumpNotationTable:
2223*7c568831SAndroid Build Coastguard Worker * @buf: the XML buffer output
2224*7c568831SAndroid Build Coastguard Worker * @table: A notation table
2225*7c568831SAndroid Build Coastguard Worker *
2226*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Don't use.
2227*7c568831SAndroid Build Coastguard Worker *
2228*7c568831SAndroid Build Coastguard Worker * This will dump the content of the notation table as an XML DTD definition
2229*7c568831SAndroid Build Coastguard Worker */
2230*7c568831SAndroid Build Coastguard Worker void
xmlDumpNotationTable(xmlBufferPtr buf,xmlNotationTablePtr table)2231*7c568831SAndroid Build Coastguard Worker xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
2232*7c568831SAndroid Build Coastguard Worker xmlSaveCtxtPtr save;
2233*7c568831SAndroid Build Coastguard Worker
2234*7c568831SAndroid Build Coastguard Worker if ((buf == NULL) || (table == NULL))
2235*7c568831SAndroid Build Coastguard Worker return;
2236*7c568831SAndroid Build Coastguard Worker
2237*7c568831SAndroid Build Coastguard Worker save = xmlSaveToBuffer(buf, NULL, 0);
2238*7c568831SAndroid Build Coastguard Worker xmlSaveNotationTable(save, table);
2239*7c568831SAndroid Build Coastguard Worker if (xmlSaveFinish(save) != XML_ERR_OK)
2240*7c568831SAndroid Build Coastguard Worker xmlFree(xmlBufferDetach(buf));
2241*7c568831SAndroid Build Coastguard Worker }
2242*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_OUTPUT_ENABLED */
2243*7c568831SAndroid Build Coastguard Worker
2244*7c568831SAndroid Build Coastguard Worker /************************************************************************
2245*7c568831SAndroid Build Coastguard Worker * *
2246*7c568831SAndroid Build Coastguard Worker * IDs *
2247*7c568831SAndroid Build Coastguard Worker * *
2248*7c568831SAndroid Build Coastguard Worker ************************************************************************/
2249*7c568831SAndroid Build Coastguard Worker /**
2250*7c568831SAndroid Build Coastguard Worker * DICT_FREE:
2251*7c568831SAndroid Build Coastguard Worker * @str: a string
2252*7c568831SAndroid Build Coastguard Worker *
2253*7c568831SAndroid Build Coastguard Worker * Free a string if it is not owned by the "dict" dictionary in the
2254*7c568831SAndroid Build Coastguard Worker * current scope
2255*7c568831SAndroid Build Coastguard Worker */
2256*7c568831SAndroid Build Coastguard Worker #define DICT_FREE(str) \
2257*7c568831SAndroid Build Coastguard Worker if ((str) && ((!dict) || \
2258*7c568831SAndroid Build Coastguard Worker (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
2259*7c568831SAndroid Build Coastguard Worker xmlFree((char *)(str));
2260*7c568831SAndroid Build Coastguard Worker
2261*7c568831SAndroid Build Coastguard Worker static int
xmlIsStreaming(xmlValidCtxtPtr ctxt)2262*7c568831SAndroid Build Coastguard Worker xmlIsStreaming(xmlValidCtxtPtr ctxt) {
2263*7c568831SAndroid Build Coastguard Worker xmlParserCtxtPtr pctxt;
2264*7c568831SAndroid Build Coastguard Worker
2265*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
2266*7c568831SAndroid Build Coastguard Worker return(0);
2267*7c568831SAndroid Build Coastguard Worker if ((ctxt->flags & XML_VCTXT_USE_PCTXT) == 0)
2268*7c568831SAndroid Build Coastguard Worker return(0);
2269*7c568831SAndroid Build Coastguard Worker pctxt = ctxt->userData;
2270*7c568831SAndroid Build Coastguard Worker return(pctxt->parseMode == XML_PARSE_READER);
2271*7c568831SAndroid Build Coastguard Worker }
2272*7c568831SAndroid Build Coastguard Worker
2273*7c568831SAndroid Build Coastguard Worker /**
2274*7c568831SAndroid Build Coastguard Worker * xmlFreeID:
2275*7c568831SAndroid Build Coastguard Worker * @not: A id
2276*7c568831SAndroid Build Coastguard Worker *
2277*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by an id definition
2278*7c568831SAndroid Build Coastguard Worker */
2279*7c568831SAndroid Build Coastguard Worker static void
xmlFreeID(xmlIDPtr id)2280*7c568831SAndroid Build Coastguard Worker xmlFreeID(xmlIDPtr id) {
2281*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
2282*7c568831SAndroid Build Coastguard Worker
2283*7c568831SAndroid Build Coastguard Worker if (id == NULL) return;
2284*7c568831SAndroid Build Coastguard Worker
2285*7c568831SAndroid Build Coastguard Worker if (id->doc != NULL)
2286*7c568831SAndroid Build Coastguard Worker dict = id->doc->dict;
2287*7c568831SAndroid Build Coastguard Worker
2288*7c568831SAndroid Build Coastguard Worker if (id->value != NULL)
2289*7c568831SAndroid Build Coastguard Worker DICT_FREE(id->value)
2290*7c568831SAndroid Build Coastguard Worker if (id->name != NULL)
2291*7c568831SAndroid Build Coastguard Worker DICT_FREE(id->name)
2292*7c568831SAndroid Build Coastguard Worker if (id->attr != NULL) {
2293*7c568831SAndroid Build Coastguard Worker id->attr->id = NULL;
2294*7c568831SAndroid Build Coastguard Worker id->attr->atype = 0;
2295*7c568831SAndroid Build Coastguard Worker }
2296*7c568831SAndroid Build Coastguard Worker
2297*7c568831SAndroid Build Coastguard Worker xmlFree(id);
2298*7c568831SAndroid Build Coastguard Worker }
2299*7c568831SAndroid Build Coastguard Worker
2300*7c568831SAndroid Build Coastguard Worker
2301*7c568831SAndroid Build Coastguard Worker /**
2302*7c568831SAndroid Build Coastguard Worker * xmlAddIDInternal:
2303*7c568831SAndroid Build Coastguard Worker * @attr: the attribute holding the ID
2304*7c568831SAndroid Build Coastguard Worker * @value: the attribute (ID) value
2305*7c568831SAndroid Build Coastguard Worker * @idPtr: pointer to resulting ID
2306*7c568831SAndroid Build Coastguard Worker *
2307*7c568831SAndroid Build Coastguard Worker * Register a new id declaration
2308*7c568831SAndroid Build Coastguard Worker *
2309*7c568831SAndroid Build Coastguard Worker * Returns 1 on success, 0 if the ID already exists, -1 if a memory
2310*7c568831SAndroid Build Coastguard Worker * allocation fails.
2311*7c568831SAndroid Build Coastguard Worker */
2312*7c568831SAndroid Build Coastguard Worker static int
xmlAddIDInternal(xmlAttrPtr attr,const xmlChar * value,xmlIDPtr * idPtr)2313*7c568831SAndroid Build Coastguard Worker xmlAddIDInternal(xmlAttrPtr attr, const xmlChar *value, xmlIDPtr *idPtr) {
2314*7c568831SAndroid Build Coastguard Worker xmlDocPtr doc;
2315*7c568831SAndroid Build Coastguard Worker xmlIDPtr id;
2316*7c568831SAndroid Build Coastguard Worker xmlIDTablePtr table;
2317*7c568831SAndroid Build Coastguard Worker int ret;
2318*7c568831SAndroid Build Coastguard Worker
2319*7c568831SAndroid Build Coastguard Worker if (idPtr != NULL)
2320*7c568831SAndroid Build Coastguard Worker *idPtr = NULL;
2321*7c568831SAndroid Build Coastguard Worker if ((value == NULL) || (value[0] == 0))
2322*7c568831SAndroid Build Coastguard Worker return(0);
2323*7c568831SAndroid Build Coastguard Worker if (attr == NULL)
2324*7c568831SAndroid Build Coastguard Worker return(0);
2325*7c568831SAndroid Build Coastguard Worker
2326*7c568831SAndroid Build Coastguard Worker doc = attr->doc;
2327*7c568831SAndroid Build Coastguard Worker if (doc == NULL)
2328*7c568831SAndroid Build Coastguard Worker return(0);
2329*7c568831SAndroid Build Coastguard Worker
2330*7c568831SAndroid Build Coastguard Worker /*
2331*7c568831SAndroid Build Coastguard Worker * Create the ID table if needed.
2332*7c568831SAndroid Build Coastguard Worker */
2333*7c568831SAndroid Build Coastguard Worker table = (xmlIDTablePtr) doc->ids;
2334*7c568831SAndroid Build Coastguard Worker if (table == NULL) {
2335*7c568831SAndroid Build Coastguard Worker doc->ids = table = xmlHashCreateDict(0, doc->dict);
2336*7c568831SAndroid Build Coastguard Worker if (table == NULL)
2337*7c568831SAndroid Build Coastguard Worker return(-1);
2338*7c568831SAndroid Build Coastguard Worker } else {
2339*7c568831SAndroid Build Coastguard Worker id = xmlHashLookup(table, value);
2340*7c568831SAndroid Build Coastguard Worker if (id != NULL)
2341*7c568831SAndroid Build Coastguard Worker return(0);
2342*7c568831SAndroid Build Coastguard Worker }
2343*7c568831SAndroid Build Coastguard Worker
2344*7c568831SAndroid Build Coastguard Worker id = (xmlIDPtr) xmlMalloc(sizeof(xmlID));
2345*7c568831SAndroid Build Coastguard Worker if (id == NULL)
2346*7c568831SAndroid Build Coastguard Worker return(-1);
2347*7c568831SAndroid Build Coastguard Worker memset(id, 0, sizeof(*id));
2348*7c568831SAndroid Build Coastguard Worker
2349*7c568831SAndroid Build Coastguard Worker /*
2350*7c568831SAndroid Build Coastguard Worker * fill the structure.
2351*7c568831SAndroid Build Coastguard Worker */
2352*7c568831SAndroid Build Coastguard Worker id->doc = doc;
2353*7c568831SAndroid Build Coastguard Worker id->value = xmlStrdup(value);
2354*7c568831SAndroid Build Coastguard Worker if (id->value == NULL) {
2355*7c568831SAndroid Build Coastguard Worker xmlFreeID(id);
2356*7c568831SAndroid Build Coastguard Worker return(-1);
2357*7c568831SAndroid Build Coastguard Worker }
2358*7c568831SAndroid Build Coastguard Worker
2359*7c568831SAndroid Build Coastguard Worker if (attr->id != NULL)
2360*7c568831SAndroid Build Coastguard Worker xmlRemoveID(doc, attr);
2361*7c568831SAndroid Build Coastguard Worker
2362*7c568831SAndroid Build Coastguard Worker if (xmlHashAddEntry(table, value, id) < 0) {
2363*7c568831SAndroid Build Coastguard Worker xmlFreeID(id);
2364*7c568831SAndroid Build Coastguard Worker return(-1);
2365*7c568831SAndroid Build Coastguard Worker }
2366*7c568831SAndroid Build Coastguard Worker
2367*7c568831SAndroid Build Coastguard Worker ret = 1;
2368*7c568831SAndroid Build Coastguard Worker if (idPtr != NULL)
2369*7c568831SAndroid Build Coastguard Worker *idPtr = id;
2370*7c568831SAndroid Build Coastguard Worker
2371*7c568831SAndroid Build Coastguard Worker id->attr = attr;
2372*7c568831SAndroid Build Coastguard Worker id->lineno = xmlGetLineNo(attr->parent);
2373*7c568831SAndroid Build Coastguard Worker attr->atype = XML_ATTRIBUTE_ID;
2374*7c568831SAndroid Build Coastguard Worker attr->id = id;
2375*7c568831SAndroid Build Coastguard Worker
2376*7c568831SAndroid Build Coastguard Worker return(ret);
2377*7c568831SAndroid Build Coastguard Worker }
2378*7c568831SAndroid Build Coastguard Worker
2379*7c568831SAndroid Build Coastguard Worker /**
2380*7c568831SAndroid Build Coastguard Worker * xmlAddIDSafe:
2381*7c568831SAndroid Build Coastguard Worker * @attr: the attribute holding the ID
2382*7c568831SAndroid Build Coastguard Worker * @value: the attribute (ID) value
2383*7c568831SAndroid Build Coastguard Worker *
2384*7c568831SAndroid Build Coastguard Worker * Register a new id declaration
2385*7c568831SAndroid Build Coastguard Worker *
2386*7c568831SAndroid Build Coastguard Worker * Available since 2.13.0.
2387*7c568831SAndroid Build Coastguard Worker *
2388*7c568831SAndroid Build Coastguard Worker * Returns 1 on success, 0 if the ID already exists, -1 if a memory
2389*7c568831SAndroid Build Coastguard Worker * allocation fails.
2390*7c568831SAndroid Build Coastguard Worker */
2391*7c568831SAndroid Build Coastguard Worker int
xmlAddIDSafe(xmlAttrPtr attr,const xmlChar * value)2392*7c568831SAndroid Build Coastguard Worker xmlAddIDSafe(xmlAttrPtr attr, const xmlChar *value) {
2393*7c568831SAndroid Build Coastguard Worker return(xmlAddIDInternal(attr, value, NULL));
2394*7c568831SAndroid Build Coastguard Worker }
2395*7c568831SAndroid Build Coastguard Worker
2396*7c568831SAndroid Build Coastguard Worker /**
2397*7c568831SAndroid Build Coastguard Worker * xmlAddID:
2398*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
2399*7c568831SAndroid Build Coastguard Worker * @doc: pointer to the document
2400*7c568831SAndroid Build Coastguard Worker * @value: the value name
2401*7c568831SAndroid Build Coastguard Worker * @attr: the attribute holding the ID
2402*7c568831SAndroid Build Coastguard Worker *
2403*7c568831SAndroid Build Coastguard Worker * Register a new id declaration
2404*7c568831SAndroid Build Coastguard Worker *
2405*7c568831SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the new xmlIDPtr
2406*7c568831SAndroid Build Coastguard Worker */
2407*7c568831SAndroid Build Coastguard Worker xmlIDPtr
xmlAddID(xmlValidCtxtPtr ctxt,xmlDocPtr doc,const xmlChar * value,xmlAttrPtr attr)2408*7c568831SAndroid Build Coastguard Worker xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
2409*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr) {
2410*7c568831SAndroid Build Coastguard Worker xmlIDPtr id;
2411*7c568831SAndroid Build Coastguard Worker int res;
2412*7c568831SAndroid Build Coastguard Worker
2413*7c568831SAndroid Build Coastguard Worker if ((attr == NULL) || (doc != attr->doc))
2414*7c568831SAndroid Build Coastguard Worker return(NULL);
2415*7c568831SAndroid Build Coastguard Worker
2416*7c568831SAndroid Build Coastguard Worker res = xmlAddIDInternal(attr, value, &id);
2417*7c568831SAndroid Build Coastguard Worker if (res < 0) {
2418*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
2419*7c568831SAndroid Build Coastguard Worker }
2420*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
2421*7c568831SAndroid Build Coastguard Worker else if (res == 0) {
2422*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL) {
2423*7c568831SAndroid Build Coastguard Worker /*
2424*7c568831SAndroid Build Coastguard Worker * The id is already defined in this DTD.
2425*7c568831SAndroid Build Coastguard Worker */
2426*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED,
2427*7c568831SAndroid Build Coastguard Worker "ID %s already defined\n", value, NULL, NULL);
2428*7c568831SAndroid Build Coastguard Worker }
2429*7c568831SAndroid Build Coastguard Worker }
2430*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
2431*7c568831SAndroid Build Coastguard Worker
2432*7c568831SAndroid Build Coastguard Worker return(id);
2433*7c568831SAndroid Build Coastguard Worker }
2434*7c568831SAndroid Build Coastguard Worker
2435*7c568831SAndroid Build Coastguard Worker static void
xmlFreeIDTableEntry(void * id,const xmlChar * name ATTRIBUTE_UNUSED)2436*7c568831SAndroid Build Coastguard Worker xmlFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
2437*7c568831SAndroid Build Coastguard Worker xmlFreeID((xmlIDPtr) id);
2438*7c568831SAndroid Build Coastguard Worker }
2439*7c568831SAndroid Build Coastguard Worker
2440*7c568831SAndroid Build Coastguard Worker /**
2441*7c568831SAndroid Build Coastguard Worker * xmlFreeIDTable:
2442*7c568831SAndroid Build Coastguard Worker * @table: An id table
2443*7c568831SAndroid Build Coastguard Worker *
2444*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by an ID hash table.
2445*7c568831SAndroid Build Coastguard Worker */
2446*7c568831SAndroid Build Coastguard Worker void
xmlFreeIDTable(xmlIDTablePtr table)2447*7c568831SAndroid Build Coastguard Worker xmlFreeIDTable(xmlIDTablePtr table) {
2448*7c568831SAndroid Build Coastguard Worker xmlHashFree(table, xmlFreeIDTableEntry);
2449*7c568831SAndroid Build Coastguard Worker }
2450*7c568831SAndroid Build Coastguard Worker
2451*7c568831SAndroid Build Coastguard Worker /**
2452*7c568831SAndroid Build Coastguard Worker * xmlIsID:
2453*7c568831SAndroid Build Coastguard Worker * @doc: the document
2454*7c568831SAndroid Build Coastguard Worker * @elem: the element carrying the attribute
2455*7c568831SAndroid Build Coastguard Worker * @attr: the attribute
2456*7c568831SAndroid Build Coastguard Worker *
2457*7c568831SAndroid Build Coastguard Worker * Determine whether an attribute is of type ID. In case we have DTD(s)
2458*7c568831SAndroid Build Coastguard Worker * then this is done if DTD loading has been requested. In the case
2459*7c568831SAndroid Build Coastguard Worker * of HTML documents parsed with the HTML parser, then ID detection is
2460*7c568831SAndroid Build Coastguard Worker * done systematically.
2461*7c568831SAndroid Build Coastguard Worker *
2462*7c568831SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the lookup result or -1 if a memory allocation
2463*7c568831SAndroid Build Coastguard Worker * failed.
2464*7c568831SAndroid Build Coastguard Worker */
2465*7c568831SAndroid Build Coastguard Worker int
xmlIsID(xmlDocPtr doc,xmlNodePtr elem,xmlAttrPtr attr)2466*7c568831SAndroid Build Coastguard Worker xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
2467*7c568831SAndroid Build Coastguard Worker if ((attr == NULL) || (attr->name == NULL))
2468*7c568831SAndroid Build Coastguard Worker return(0);
2469*7c568831SAndroid Build Coastguard Worker
2470*7c568831SAndroid Build Coastguard Worker if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2471*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(BAD_CAST "id", attr->name))
2472*7c568831SAndroid Build Coastguard Worker return(1);
2473*7c568831SAndroid Build Coastguard Worker
2474*7c568831SAndroid Build Coastguard Worker if ((elem == NULL) || (elem->type != XML_ELEMENT_NODE))
2475*7c568831SAndroid Build Coastguard Worker return(0);
2476*7c568831SAndroid Build Coastguard Worker
2477*7c568831SAndroid Build Coastguard Worker if ((xmlStrEqual(BAD_CAST "name", attr->name)) &&
2478*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(elem->name, BAD_CAST "a")))
2479*7c568831SAndroid Build Coastguard Worker return(1);
2480*7c568831SAndroid Build Coastguard Worker } else {
2481*7c568831SAndroid Build Coastguard Worker xmlAttributePtr attrDecl = NULL;
2482*7c568831SAndroid Build Coastguard Worker xmlChar felem[50];
2483*7c568831SAndroid Build Coastguard Worker xmlChar *fullelemname;
2484*7c568831SAndroid Build Coastguard Worker const xmlChar *aprefix;
2485*7c568831SAndroid Build Coastguard Worker
2486*7c568831SAndroid Build Coastguard Worker if ((attr->ns != NULL) && (attr->ns->prefix != NULL) &&
2487*7c568831SAndroid Build Coastguard Worker (!strcmp((char *) attr->name, "id")) &&
2488*7c568831SAndroid Build Coastguard Worker (!strcmp((char *) attr->ns->prefix, "xml")))
2489*7c568831SAndroid Build Coastguard Worker return(1);
2490*7c568831SAndroid Build Coastguard Worker
2491*7c568831SAndroid Build Coastguard Worker if ((doc == NULL) ||
2492*7c568831SAndroid Build Coastguard Worker ((doc->intSubset == NULL) && (doc->extSubset == NULL)))
2493*7c568831SAndroid Build Coastguard Worker return(0);
2494*7c568831SAndroid Build Coastguard Worker
2495*7c568831SAndroid Build Coastguard Worker if ((elem == NULL) ||
2496*7c568831SAndroid Build Coastguard Worker (elem->type != XML_ELEMENT_NODE) ||
2497*7c568831SAndroid Build Coastguard Worker (elem->name == NULL))
2498*7c568831SAndroid Build Coastguard Worker return(0);
2499*7c568831SAndroid Build Coastguard Worker
2500*7c568831SAndroid Build Coastguard Worker fullelemname = (elem->ns != NULL && elem->ns->prefix != NULL) ?
2501*7c568831SAndroid Build Coastguard Worker xmlBuildQName(elem->name, elem->ns->prefix, felem, 50) :
2502*7c568831SAndroid Build Coastguard Worker (xmlChar *)elem->name;
2503*7c568831SAndroid Build Coastguard Worker if (fullelemname == NULL)
2504*7c568831SAndroid Build Coastguard Worker return(-1);
2505*7c568831SAndroid Build Coastguard Worker
2506*7c568831SAndroid Build Coastguard Worker aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL;
2507*7c568831SAndroid Build Coastguard Worker
2508*7c568831SAndroid Build Coastguard Worker if (fullelemname != NULL) {
2509*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullelemname,
2510*7c568831SAndroid Build Coastguard Worker attr->name, aprefix);
2511*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
2512*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullelemname,
2513*7c568831SAndroid Build Coastguard Worker attr->name, aprefix);
2514*7c568831SAndroid Build Coastguard Worker }
2515*7c568831SAndroid Build Coastguard Worker
2516*7c568831SAndroid Build Coastguard Worker if ((fullelemname != felem) && (fullelemname != elem->name))
2517*7c568831SAndroid Build Coastguard Worker xmlFree(fullelemname);
2518*7c568831SAndroid Build Coastguard Worker
2519*7c568831SAndroid Build Coastguard Worker if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID))
2520*7c568831SAndroid Build Coastguard Worker return(1);
2521*7c568831SAndroid Build Coastguard Worker }
2522*7c568831SAndroid Build Coastguard Worker
2523*7c568831SAndroid Build Coastguard Worker return(0);
2524*7c568831SAndroid Build Coastguard Worker }
2525*7c568831SAndroid Build Coastguard Worker
2526*7c568831SAndroid Build Coastguard Worker /**
2527*7c568831SAndroid Build Coastguard Worker * xmlRemoveID:
2528*7c568831SAndroid Build Coastguard Worker * @doc: the document
2529*7c568831SAndroid Build Coastguard Worker * @attr: the attribute
2530*7c568831SAndroid Build Coastguard Worker *
2531*7c568831SAndroid Build Coastguard Worker * Remove the given attribute from the ID table maintained internally.
2532*7c568831SAndroid Build Coastguard Worker *
2533*7c568831SAndroid Build Coastguard Worker * Returns -1 if the lookup failed and 0 otherwise
2534*7c568831SAndroid Build Coastguard Worker */
2535*7c568831SAndroid Build Coastguard Worker int
xmlRemoveID(xmlDocPtr doc,xmlAttrPtr attr)2536*7c568831SAndroid Build Coastguard Worker xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
2537*7c568831SAndroid Build Coastguard Worker xmlIDTablePtr table;
2538*7c568831SAndroid Build Coastguard Worker
2539*7c568831SAndroid Build Coastguard Worker if (doc == NULL) return(-1);
2540*7c568831SAndroid Build Coastguard Worker if ((attr == NULL) || (attr->id == NULL)) return(-1);
2541*7c568831SAndroid Build Coastguard Worker
2542*7c568831SAndroid Build Coastguard Worker table = (xmlIDTablePtr) doc->ids;
2543*7c568831SAndroid Build Coastguard Worker if (table == NULL)
2544*7c568831SAndroid Build Coastguard Worker return(-1);
2545*7c568831SAndroid Build Coastguard Worker
2546*7c568831SAndroid Build Coastguard Worker if (xmlHashRemoveEntry(table, attr->id->value, xmlFreeIDTableEntry) < 0)
2547*7c568831SAndroid Build Coastguard Worker return(-1);
2548*7c568831SAndroid Build Coastguard Worker
2549*7c568831SAndroid Build Coastguard Worker return(0);
2550*7c568831SAndroid Build Coastguard Worker }
2551*7c568831SAndroid Build Coastguard Worker
2552*7c568831SAndroid Build Coastguard Worker /**
2553*7c568831SAndroid Build Coastguard Worker * xmlGetID:
2554*7c568831SAndroid Build Coastguard Worker * @doc: pointer to the document
2555*7c568831SAndroid Build Coastguard Worker * @ID: the ID value
2556*7c568831SAndroid Build Coastguard Worker *
2557*7c568831SAndroid Build Coastguard Worker * Search the attribute declaring the given ID
2558*7c568831SAndroid Build Coastguard Worker *
2559*7c568831SAndroid Build Coastguard Worker * Returns NULL if not found, otherwise the xmlAttrPtr defining the ID
2560*7c568831SAndroid Build Coastguard Worker */
2561*7c568831SAndroid Build Coastguard Worker xmlAttrPtr
xmlGetID(xmlDocPtr doc,const xmlChar * ID)2562*7c568831SAndroid Build Coastguard Worker xmlGetID(xmlDocPtr doc, const xmlChar *ID) {
2563*7c568831SAndroid Build Coastguard Worker xmlIDTablePtr table;
2564*7c568831SAndroid Build Coastguard Worker xmlIDPtr id;
2565*7c568831SAndroid Build Coastguard Worker
2566*7c568831SAndroid Build Coastguard Worker if (doc == NULL) {
2567*7c568831SAndroid Build Coastguard Worker return(NULL);
2568*7c568831SAndroid Build Coastguard Worker }
2569*7c568831SAndroid Build Coastguard Worker
2570*7c568831SAndroid Build Coastguard Worker if (ID == NULL) {
2571*7c568831SAndroid Build Coastguard Worker return(NULL);
2572*7c568831SAndroid Build Coastguard Worker }
2573*7c568831SAndroid Build Coastguard Worker
2574*7c568831SAndroid Build Coastguard Worker table = (xmlIDTablePtr) doc->ids;
2575*7c568831SAndroid Build Coastguard Worker if (table == NULL)
2576*7c568831SAndroid Build Coastguard Worker return(NULL);
2577*7c568831SAndroid Build Coastguard Worker
2578*7c568831SAndroid Build Coastguard Worker id = xmlHashLookup(table, ID);
2579*7c568831SAndroid Build Coastguard Worker if (id == NULL)
2580*7c568831SAndroid Build Coastguard Worker return(NULL);
2581*7c568831SAndroid Build Coastguard Worker if (id->attr == NULL) {
2582*7c568831SAndroid Build Coastguard Worker /*
2583*7c568831SAndroid Build Coastguard Worker * We are operating on a stream, return a well known reference
2584*7c568831SAndroid Build Coastguard Worker * since the attribute node doesn't exist anymore
2585*7c568831SAndroid Build Coastguard Worker */
2586*7c568831SAndroid Build Coastguard Worker return((xmlAttrPtr) doc);
2587*7c568831SAndroid Build Coastguard Worker }
2588*7c568831SAndroid Build Coastguard Worker return(id->attr);
2589*7c568831SAndroid Build Coastguard Worker }
2590*7c568831SAndroid Build Coastguard Worker
2591*7c568831SAndroid Build Coastguard Worker /************************************************************************
2592*7c568831SAndroid Build Coastguard Worker * *
2593*7c568831SAndroid Build Coastguard Worker * Refs *
2594*7c568831SAndroid Build Coastguard Worker * *
2595*7c568831SAndroid Build Coastguard Worker ************************************************************************/
2596*7c568831SAndroid Build Coastguard Worker typedef struct xmlRemoveMemo_t
2597*7c568831SAndroid Build Coastguard Worker {
2598*7c568831SAndroid Build Coastguard Worker xmlListPtr l;
2599*7c568831SAndroid Build Coastguard Worker xmlAttrPtr ap;
2600*7c568831SAndroid Build Coastguard Worker } xmlRemoveMemo;
2601*7c568831SAndroid Build Coastguard Worker
2602*7c568831SAndroid Build Coastguard Worker typedef xmlRemoveMemo *xmlRemoveMemoPtr;
2603*7c568831SAndroid Build Coastguard Worker
2604*7c568831SAndroid Build Coastguard Worker typedef struct xmlValidateMemo_t
2605*7c568831SAndroid Build Coastguard Worker {
2606*7c568831SAndroid Build Coastguard Worker xmlValidCtxtPtr ctxt;
2607*7c568831SAndroid Build Coastguard Worker const xmlChar *name;
2608*7c568831SAndroid Build Coastguard Worker } xmlValidateMemo;
2609*7c568831SAndroid Build Coastguard Worker
2610*7c568831SAndroid Build Coastguard Worker typedef xmlValidateMemo *xmlValidateMemoPtr;
2611*7c568831SAndroid Build Coastguard Worker
2612*7c568831SAndroid Build Coastguard Worker /**
2613*7c568831SAndroid Build Coastguard Worker * xmlFreeRef:
2614*7c568831SAndroid Build Coastguard Worker * @lk: A list link
2615*7c568831SAndroid Build Coastguard Worker *
2616*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by a ref definition
2617*7c568831SAndroid Build Coastguard Worker */
2618*7c568831SAndroid Build Coastguard Worker static void
xmlFreeRef(xmlLinkPtr lk)2619*7c568831SAndroid Build Coastguard Worker xmlFreeRef(xmlLinkPtr lk) {
2620*7c568831SAndroid Build Coastguard Worker xmlRefPtr ref = (xmlRefPtr)xmlLinkGetData(lk);
2621*7c568831SAndroid Build Coastguard Worker if (ref == NULL) return;
2622*7c568831SAndroid Build Coastguard Worker if (ref->value != NULL)
2623*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *)ref->value);
2624*7c568831SAndroid Build Coastguard Worker if (ref->name != NULL)
2625*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *)ref->name);
2626*7c568831SAndroid Build Coastguard Worker xmlFree(ref);
2627*7c568831SAndroid Build Coastguard Worker }
2628*7c568831SAndroid Build Coastguard Worker
2629*7c568831SAndroid Build Coastguard Worker /**
2630*7c568831SAndroid Build Coastguard Worker * xmlFreeRefTableEntry:
2631*7c568831SAndroid Build Coastguard Worker * @list_ref: A list of references.
2632*7c568831SAndroid Build Coastguard Worker *
2633*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by a list of references
2634*7c568831SAndroid Build Coastguard Worker */
2635*7c568831SAndroid Build Coastguard Worker static void
xmlFreeRefTableEntry(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)2636*7c568831SAndroid Build Coastguard Worker xmlFreeRefTableEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
2637*7c568831SAndroid Build Coastguard Worker xmlListPtr list_ref = (xmlListPtr) payload;
2638*7c568831SAndroid Build Coastguard Worker if (list_ref == NULL) return;
2639*7c568831SAndroid Build Coastguard Worker xmlListDelete(list_ref);
2640*7c568831SAndroid Build Coastguard Worker }
2641*7c568831SAndroid Build Coastguard Worker
2642*7c568831SAndroid Build Coastguard Worker /**
2643*7c568831SAndroid Build Coastguard Worker * xmlWalkRemoveRef:
2644*7c568831SAndroid Build Coastguard Worker * @data: Contents of current link
2645*7c568831SAndroid Build Coastguard Worker * @user: Value supplied by the user
2646*7c568831SAndroid Build Coastguard Worker *
2647*7c568831SAndroid Build Coastguard Worker * Returns 0 to abort the walk or 1 to continue
2648*7c568831SAndroid Build Coastguard Worker */
2649*7c568831SAndroid Build Coastguard Worker static int
xmlWalkRemoveRef(const void * data,void * user)2650*7c568831SAndroid Build Coastguard Worker xmlWalkRemoveRef(const void *data, void *user)
2651*7c568831SAndroid Build Coastguard Worker {
2652*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr0 = ((xmlRefPtr)data)->attr;
2653*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr1 = ((xmlRemoveMemoPtr)user)->ap;
2654*7c568831SAndroid Build Coastguard Worker xmlListPtr ref_list = ((xmlRemoveMemoPtr)user)->l;
2655*7c568831SAndroid Build Coastguard Worker
2656*7c568831SAndroid Build Coastguard Worker if (attr0 == attr1) { /* Matched: remove and terminate walk */
2657*7c568831SAndroid Build Coastguard Worker xmlListRemoveFirst(ref_list, (void *)data);
2658*7c568831SAndroid Build Coastguard Worker return 0;
2659*7c568831SAndroid Build Coastguard Worker }
2660*7c568831SAndroid Build Coastguard Worker return 1;
2661*7c568831SAndroid Build Coastguard Worker }
2662*7c568831SAndroid Build Coastguard Worker
2663*7c568831SAndroid Build Coastguard Worker /**
2664*7c568831SAndroid Build Coastguard Worker * xmlDummyCompare
2665*7c568831SAndroid Build Coastguard Worker * @data0: Value supplied by the user
2666*7c568831SAndroid Build Coastguard Worker * @data1: Value supplied by the user
2667*7c568831SAndroid Build Coastguard Worker *
2668*7c568831SAndroid Build Coastguard Worker * Do nothing, return 0. Used to create unordered lists.
2669*7c568831SAndroid Build Coastguard Worker */
2670*7c568831SAndroid Build Coastguard Worker static int
xmlDummyCompare(const void * data0 ATTRIBUTE_UNUSED,const void * data1 ATTRIBUTE_UNUSED)2671*7c568831SAndroid Build Coastguard Worker xmlDummyCompare(const void *data0 ATTRIBUTE_UNUSED,
2672*7c568831SAndroid Build Coastguard Worker const void *data1 ATTRIBUTE_UNUSED)
2673*7c568831SAndroid Build Coastguard Worker {
2674*7c568831SAndroid Build Coastguard Worker return (0);
2675*7c568831SAndroid Build Coastguard Worker }
2676*7c568831SAndroid Build Coastguard Worker
2677*7c568831SAndroid Build Coastguard Worker /**
2678*7c568831SAndroid Build Coastguard Worker * xmlAddRef:
2679*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
2680*7c568831SAndroid Build Coastguard Worker * @doc: pointer to the document
2681*7c568831SAndroid Build Coastguard Worker * @value: the value name
2682*7c568831SAndroid Build Coastguard Worker * @attr: the attribute holding the Ref
2683*7c568831SAndroid Build Coastguard Worker *
2684*7c568831SAndroid Build Coastguard Worker * DEPRECATED, do not use. This function will be removed from the public API.
2685*7c568831SAndroid Build Coastguard Worker *
2686*7c568831SAndroid Build Coastguard Worker * Register a new ref declaration
2687*7c568831SAndroid Build Coastguard Worker *
2688*7c568831SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the new xmlRefPtr
2689*7c568831SAndroid Build Coastguard Worker */
2690*7c568831SAndroid Build Coastguard Worker xmlRefPtr
xmlAddRef(xmlValidCtxtPtr ctxt,xmlDocPtr doc,const xmlChar * value,xmlAttrPtr attr)2691*7c568831SAndroid Build Coastguard Worker xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
2692*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr) {
2693*7c568831SAndroid Build Coastguard Worker xmlRefPtr ret = NULL;
2694*7c568831SAndroid Build Coastguard Worker xmlRefTablePtr table;
2695*7c568831SAndroid Build Coastguard Worker xmlListPtr ref_list;
2696*7c568831SAndroid Build Coastguard Worker
2697*7c568831SAndroid Build Coastguard Worker if (doc == NULL) {
2698*7c568831SAndroid Build Coastguard Worker return(NULL);
2699*7c568831SAndroid Build Coastguard Worker }
2700*7c568831SAndroid Build Coastguard Worker if (value == NULL) {
2701*7c568831SAndroid Build Coastguard Worker return(NULL);
2702*7c568831SAndroid Build Coastguard Worker }
2703*7c568831SAndroid Build Coastguard Worker if (attr == NULL) {
2704*7c568831SAndroid Build Coastguard Worker return(NULL);
2705*7c568831SAndroid Build Coastguard Worker }
2706*7c568831SAndroid Build Coastguard Worker
2707*7c568831SAndroid Build Coastguard Worker /*
2708*7c568831SAndroid Build Coastguard Worker * Create the Ref table if needed.
2709*7c568831SAndroid Build Coastguard Worker */
2710*7c568831SAndroid Build Coastguard Worker table = (xmlRefTablePtr) doc->refs;
2711*7c568831SAndroid Build Coastguard Worker if (table == NULL) {
2712*7c568831SAndroid Build Coastguard Worker doc->refs = table = xmlHashCreateDict(0, doc->dict);
2713*7c568831SAndroid Build Coastguard Worker if (table == NULL)
2714*7c568831SAndroid Build Coastguard Worker goto failed;
2715*7c568831SAndroid Build Coastguard Worker }
2716*7c568831SAndroid Build Coastguard Worker
2717*7c568831SAndroid Build Coastguard Worker ret = (xmlRefPtr) xmlMalloc(sizeof(xmlRef));
2718*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
2719*7c568831SAndroid Build Coastguard Worker goto failed;
2720*7c568831SAndroid Build Coastguard Worker memset(ret, 0, sizeof(*ret));
2721*7c568831SAndroid Build Coastguard Worker
2722*7c568831SAndroid Build Coastguard Worker /*
2723*7c568831SAndroid Build Coastguard Worker * fill the structure.
2724*7c568831SAndroid Build Coastguard Worker */
2725*7c568831SAndroid Build Coastguard Worker ret->value = xmlStrdup(value);
2726*7c568831SAndroid Build Coastguard Worker if (ret->value == NULL)
2727*7c568831SAndroid Build Coastguard Worker goto failed;
2728*7c568831SAndroid Build Coastguard Worker if (xmlIsStreaming(ctxt)) {
2729*7c568831SAndroid Build Coastguard Worker /*
2730*7c568831SAndroid Build Coastguard Worker * Operating in streaming mode, attr is gonna disappear
2731*7c568831SAndroid Build Coastguard Worker */
2732*7c568831SAndroid Build Coastguard Worker ret->name = xmlStrdup(attr->name);
2733*7c568831SAndroid Build Coastguard Worker if (ret->name == NULL)
2734*7c568831SAndroid Build Coastguard Worker goto failed;
2735*7c568831SAndroid Build Coastguard Worker ret->attr = NULL;
2736*7c568831SAndroid Build Coastguard Worker } else {
2737*7c568831SAndroid Build Coastguard Worker ret->name = NULL;
2738*7c568831SAndroid Build Coastguard Worker ret->attr = attr;
2739*7c568831SAndroid Build Coastguard Worker }
2740*7c568831SAndroid Build Coastguard Worker ret->lineno = xmlGetLineNo(attr->parent);
2741*7c568831SAndroid Build Coastguard Worker
2742*7c568831SAndroid Build Coastguard Worker /* To add a reference :-
2743*7c568831SAndroid Build Coastguard Worker * References are maintained as a list of references,
2744*7c568831SAndroid Build Coastguard Worker * Lookup the entry, if no entry create new nodelist
2745*7c568831SAndroid Build Coastguard Worker * Add the owning node to the NodeList
2746*7c568831SAndroid Build Coastguard Worker * Return the ref
2747*7c568831SAndroid Build Coastguard Worker */
2748*7c568831SAndroid Build Coastguard Worker
2749*7c568831SAndroid Build Coastguard Worker ref_list = xmlHashLookup(table, value);
2750*7c568831SAndroid Build Coastguard Worker if (ref_list == NULL) {
2751*7c568831SAndroid Build Coastguard Worker int res;
2752*7c568831SAndroid Build Coastguard Worker
2753*7c568831SAndroid Build Coastguard Worker ref_list = xmlListCreate(xmlFreeRef, xmlDummyCompare);
2754*7c568831SAndroid Build Coastguard Worker if (ref_list == NULL)
2755*7c568831SAndroid Build Coastguard Worker goto failed;
2756*7c568831SAndroid Build Coastguard Worker res = xmlHashAdd(table, value, ref_list);
2757*7c568831SAndroid Build Coastguard Worker if (res <= 0) {
2758*7c568831SAndroid Build Coastguard Worker xmlListDelete(ref_list);
2759*7c568831SAndroid Build Coastguard Worker goto failed;
2760*7c568831SAndroid Build Coastguard Worker }
2761*7c568831SAndroid Build Coastguard Worker }
2762*7c568831SAndroid Build Coastguard Worker if (xmlListAppend(ref_list, ret) != 0)
2763*7c568831SAndroid Build Coastguard Worker goto failed;
2764*7c568831SAndroid Build Coastguard Worker return(ret);
2765*7c568831SAndroid Build Coastguard Worker
2766*7c568831SAndroid Build Coastguard Worker failed:
2767*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
2768*7c568831SAndroid Build Coastguard Worker if (ret != NULL) {
2769*7c568831SAndroid Build Coastguard Worker if (ret->value != NULL)
2770*7c568831SAndroid Build Coastguard Worker xmlFree((char *)ret->value);
2771*7c568831SAndroid Build Coastguard Worker if (ret->name != NULL)
2772*7c568831SAndroid Build Coastguard Worker xmlFree((char *)ret->name);
2773*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
2774*7c568831SAndroid Build Coastguard Worker }
2775*7c568831SAndroid Build Coastguard Worker return(NULL);
2776*7c568831SAndroid Build Coastguard Worker }
2777*7c568831SAndroid Build Coastguard Worker
2778*7c568831SAndroid Build Coastguard Worker /**
2779*7c568831SAndroid Build Coastguard Worker * xmlFreeRefTable:
2780*7c568831SAndroid Build Coastguard Worker * @table: An ref table
2781*7c568831SAndroid Build Coastguard Worker *
2782*7c568831SAndroid Build Coastguard Worker * DEPRECATED, do not use. This function will be removed from the public API.
2783*7c568831SAndroid Build Coastguard Worker *
2784*7c568831SAndroid Build Coastguard Worker * Deallocate the memory used by an Ref hash table.
2785*7c568831SAndroid Build Coastguard Worker */
2786*7c568831SAndroid Build Coastguard Worker void
xmlFreeRefTable(xmlRefTablePtr table)2787*7c568831SAndroid Build Coastguard Worker xmlFreeRefTable(xmlRefTablePtr table) {
2788*7c568831SAndroid Build Coastguard Worker xmlHashFree(table, xmlFreeRefTableEntry);
2789*7c568831SAndroid Build Coastguard Worker }
2790*7c568831SAndroid Build Coastguard Worker
2791*7c568831SAndroid Build Coastguard Worker /**
2792*7c568831SAndroid Build Coastguard Worker * xmlIsRef:
2793*7c568831SAndroid Build Coastguard Worker * @doc: the document
2794*7c568831SAndroid Build Coastguard Worker * @elem: the element carrying the attribute
2795*7c568831SAndroid Build Coastguard Worker * @attr: the attribute
2796*7c568831SAndroid Build Coastguard Worker *
2797*7c568831SAndroid Build Coastguard Worker * DEPRECATED, do not use. This function will be removed from the public API.
2798*7c568831SAndroid Build Coastguard Worker *
2799*7c568831SAndroid Build Coastguard Worker * Determine whether an attribute is of type Ref. In case we have DTD(s)
2800*7c568831SAndroid Build Coastguard Worker * then this is simple, otherwise we use an heuristic: name Ref (upper
2801*7c568831SAndroid Build Coastguard Worker * or lowercase).
2802*7c568831SAndroid Build Coastguard Worker *
2803*7c568831SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the lookup result
2804*7c568831SAndroid Build Coastguard Worker */
2805*7c568831SAndroid Build Coastguard Worker int
xmlIsRef(xmlDocPtr doc,xmlNodePtr elem,xmlAttrPtr attr)2806*7c568831SAndroid Build Coastguard Worker xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
2807*7c568831SAndroid Build Coastguard Worker if (attr == NULL)
2808*7c568831SAndroid Build Coastguard Worker return(0);
2809*7c568831SAndroid Build Coastguard Worker if (doc == NULL) {
2810*7c568831SAndroid Build Coastguard Worker doc = attr->doc;
2811*7c568831SAndroid Build Coastguard Worker if (doc == NULL) return(0);
2812*7c568831SAndroid Build Coastguard Worker }
2813*7c568831SAndroid Build Coastguard Worker
2814*7c568831SAndroid Build Coastguard Worker if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
2815*7c568831SAndroid Build Coastguard Worker return(0);
2816*7c568831SAndroid Build Coastguard Worker } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2817*7c568831SAndroid Build Coastguard Worker /* TODO @@@ */
2818*7c568831SAndroid Build Coastguard Worker return(0);
2819*7c568831SAndroid Build Coastguard Worker } else {
2820*7c568831SAndroid Build Coastguard Worker xmlAttributePtr attrDecl;
2821*7c568831SAndroid Build Coastguard Worker const xmlChar *aprefix;
2822*7c568831SAndroid Build Coastguard Worker
2823*7c568831SAndroid Build Coastguard Worker if (elem == NULL) return(0);
2824*7c568831SAndroid Build Coastguard Worker aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL;
2825*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name, attr->name,
2826*7c568831SAndroid Build Coastguard Worker aprefix);
2827*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
2828*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name, attr->name,
2829*7c568831SAndroid Build Coastguard Worker aprefix);
2830*7c568831SAndroid Build Coastguard Worker
2831*7c568831SAndroid Build Coastguard Worker if ((attrDecl != NULL) &&
2832*7c568831SAndroid Build Coastguard Worker (attrDecl->atype == XML_ATTRIBUTE_IDREF ||
2833*7c568831SAndroid Build Coastguard Worker attrDecl->atype == XML_ATTRIBUTE_IDREFS))
2834*7c568831SAndroid Build Coastguard Worker return(1);
2835*7c568831SAndroid Build Coastguard Worker }
2836*7c568831SAndroid Build Coastguard Worker return(0);
2837*7c568831SAndroid Build Coastguard Worker }
2838*7c568831SAndroid Build Coastguard Worker
2839*7c568831SAndroid Build Coastguard Worker /**
2840*7c568831SAndroid Build Coastguard Worker * xmlRemoveRef:
2841*7c568831SAndroid Build Coastguard Worker * @doc: the document
2842*7c568831SAndroid Build Coastguard Worker * @attr: the attribute
2843*7c568831SAndroid Build Coastguard Worker *
2844*7c568831SAndroid Build Coastguard Worker * DEPRECATED, do not use. This function will be removed from the public API.
2845*7c568831SAndroid Build Coastguard Worker *
2846*7c568831SAndroid Build Coastguard Worker * Remove the given attribute from the Ref table maintained internally.
2847*7c568831SAndroid Build Coastguard Worker *
2848*7c568831SAndroid Build Coastguard Worker * Returns -1 if the lookup failed and 0 otherwise
2849*7c568831SAndroid Build Coastguard Worker */
2850*7c568831SAndroid Build Coastguard Worker int
xmlRemoveRef(xmlDocPtr doc,xmlAttrPtr attr)2851*7c568831SAndroid Build Coastguard Worker xmlRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
2852*7c568831SAndroid Build Coastguard Worker xmlListPtr ref_list;
2853*7c568831SAndroid Build Coastguard Worker xmlRefTablePtr table;
2854*7c568831SAndroid Build Coastguard Worker xmlChar *ID;
2855*7c568831SAndroid Build Coastguard Worker xmlRemoveMemo target;
2856*7c568831SAndroid Build Coastguard Worker
2857*7c568831SAndroid Build Coastguard Worker if (doc == NULL) return(-1);
2858*7c568831SAndroid Build Coastguard Worker if (attr == NULL) return(-1);
2859*7c568831SAndroid Build Coastguard Worker
2860*7c568831SAndroid Build Coastguard Worker table = (xmlRefTablePtr) doc->refs;
2861*7c568831SAndroid Build Coastguard Worker if (table == NULL)
2862*7c568831SAndroid Build Coastguard Worker return(-1);
2863*7c568831SAndroid Build Coastguard Worker
2864*7c568831SAndroid Build Coastguard Worker ID = xmlNodeListGetString(doc, attr->children, 1);
2865*7c568831SAndroid Build Coastguard Worker if (ID == NULL)
2866*7c568831SAndroid Build Coastguard Worker return(-1);
2867*7c568831SAndroid Build Coastguard Worker
2868*7c568831SAndroid Build Coastguard Worker ref_list = xmlHashLookup(table, ID);
2869*7c568831SAndroid Build Coastguard Worker if(ref_list == NULL) {
2870*7c568831SAndroid Build Coastguard Worker xmlFree(ID);
2871*7c568831SAndroid Build Coastguard Worker return (-1);
2872*7c568831SAndroid Build Coastguard Worker }
2873*7c568831SAndroid Build Coastguard Worker
2874*7c568831SAndroid Build Coastguard Worker /* At this point, ref_list refers to a list of references which
2875*7c568831SAndroid Build Coastguard Worker * have the same key as the supplied attr. Our list of references
2876*7c568831SAndroid Build Coastguard Worker * is ordered by reference address and we don't have that information
2877*7c568831SAndroid Build Coastguard Worker * here to use when removing. We'll have to walk the list and
2878*7c568831SAndroid Build Coastguard Worker * check for a matching attribute, when we find one stop the walk
2879*7c568831SAndroid Build Coastguard Worker * and remove the entry.
2880*7c568831SAndroid Build Coastguard Worker * The list is ordered by reference, so that means we don't have the
2881*7c568831SAndroid Build Coastguard Worker * key. Passing the list and the reference to the walker means we
2882*7c568831SAndroid Build Coastguard Worker * will have enough data to be able to remove the entry.
2883*7c568831SAndroid Build Coastguard Worker */
2884*7c568831SAndroid Build Coastguard Worker target.l = ref_list;
2885*7c568831SAndroid Build Coastguard Worker target.ap = attr;
2886*7c568831SAndroid Build Coastguard Worker
2887*7c568831SAndroid Build Coastguard Worker /* Remove the supplied attr from our list */
2888*7c568831SAndroid Build Coastguard Worker xmlListWalk(ref_list, xmlWalkRemoveRef, &target);
2889*7c568831SAndroid Build Coastguard Worker
2890*7c568831SAndroid Build Coastguard Worker /*If the list is empty then remove the list entry in the hash */
2891*7c568831SAndroid Build Coastguard Worker if (xmlListEmpty(ref_list))
2892*7c568831SAndroid Build Coastguard Worker xmlHashRemoveEntry(table, ID, xmlFreeRefTableEntry);
2893*7c568831SAndroid Build Coastguard Worker xmlFree(ID);
2894*7c568831SAndroid Build Coastguard Worker return(0);
2895*7c568831SAndroid Build Coastguard Worker }
2896*7c568831SAndroid Build Coastguard Worker
2897*7c568831SAndroid Build Coastguard Worker /**
2898*7c568831SAndroid Build Coastguard Worker * xmlGetRefs:
2899*7c568831SAndroid Build Coastguard Worker * @doc: pointer to the document
2900*7c568831SAndroid Build Coastguard Worker * @ID: the ID value
2901*7c568831SAndroid Build Coastguard Worker *
2902*7c568831SAndroid Build Coastguard Worker * DEPRECATED, do not use. This function will be removed from the public API.
2903*7c568831SAndroid Build Coastguard Worker *
2904*7c568831SAndroid Build Coastguard Worker * Find the set of references for the supplied ID.
2905*7c568831SAndroid Build Coastguard Worker *
2906*7c568831SAndroid Build Coastguard Worker * Returns NULL if not found, otherwise node set for the ID.
2907*7c568831SAndroid Build Coastguard Worker */
2908*7c568831SAndroid Build Coastguard Worker xmlListPtr
xmlGetRefs(xmlDocPtr doc,const xmlChar * ID)2909*7c568831SAndroid Build Coastguard Worker xmlGetRefs(xmlDocPtr doc, const xmlChar *ID) {
2910*7c568831SAndroid Build Coastguard Worker xmlRefTablePtr table;
2911*7c568831SAndroid Build Coastguard Worker
2912*7c568831SAndroid Build Coastguard Worker if (doc == NULL) {
2913*7c568831SAndroid Build Coastguard Worker return(NULL);
2914*7c568831SAndroid Build Coastguard Worker }
2915*7c568831SAndroid Build Coastguard Worker
2916*7c568831SAndroid Build Coastguard Worker if (ID == NULL) {
2917*7c568831SAndroid Build Coastguard Worker return(NULL);
2918*7c568831SAndroid Build Coastguard Worker }
2919*7c568831SAndroid Build Coastguard Worker
2920*7c568831SAndroid Build Coastguard Worker table = (xmlRefTablePtr) doc->refs;
2921*7c568831SAndroid Build Coastguard Worker if (table == NULL)
2922*7c568831SAndroid Build Coastguard Worker return(NULL);
2923*7c568831SAndroid Build Coastguard Worker
2924*7c568831SAndroid Build Coastguard Worker return (xmlHashLookup(table, ID));
2925*7c568831SAndroid Build Coastguard Worker }
2926*7c568831SAndroid Build Coastguard Worker
2927*7c568831SAndroid Build Coastguard Worker /************************************************************************
2928*7c568831SAndroid Build Coastguard Worker * *
2929*7c568831SAndroid Build Coastguard Worker * Routines for validity checking *
2930*7c568831SAndroid Build Coastguard Worker * *
2931*7c568831SAndroid Build Coastguard Worker ************************************************************************/
2932*7c568831SAndroid Build Coastguard Worker
2933*7c568831SAndroid Build Coastguard Worker /**
2934*7c568831SAndroid Build Coastguard Worker * xmlGetDtdElementDesc:
2935*7c568831SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
2936*7c568831SAndroid Build Coastguard Worker * @name: the element name
2937*7c568831SAndroid Build Coastguard Worker *
2938*7c568831SAndroid Build Coastguard Worker * Search the DTD for the description of this element
2939*7c568831SAndroid Build Coastguard Worker *
2940*7c568831SAndroid Build Coastguard Worker * NOTE: A NULL return value can also mean that a memory allocation failed.
2941*7c568831SAndroid Build Coastguard Worker *
2942*7c568831SAndroid Build Coastguard Worker * returns the xmlElementPtr if found or NULL
2943*7c568831SAndroid Build Coastguard Worker */
2944*7c568831SAndroid Build Coastguard Worker
2945*7c568831SAndroid Build Coastguard Worker xmlElementPtr
xmlGetDtdElementDesc(xmlDtdPtr dtd,const xmlChar * name)2946*7c568831SAndroid Build Coastguard Worker xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) {
2947*7c568831SAndroid Build Coastguard Worker xmlElementTablePtr table;
2948*7c568831SAndroid Build Coastguard Worker xmlElementPtr cur;
2949*7c568831SAndroid Build Coastguard Worker const xmlChar *localname;
2950*7c568831SAndroid Build Coastguard Worker xmlChar *prefix;
2951*7c568831SAndroid Build Coastguard Worker
2952*7c568831SAndroid Build Coastguard Worker if ((dtd == NULL) || (dtd->elements == NULL) ||
2953*7c568831SAndroid Build Coastguard Worker (name == NULL))
2954*7c568831SAndroid Build Coastguard Worker return(NULL);
2955*7c568831SAndroid Build Coastguard Worker
2956*7c568831SAndroid Build Coastguard Worker table = (xmlElementTablePtr) dtd->elements;
2957*7c568831SAndroid Build Coastguard Worker if (table == NULL)
2958*7c568831SAndroid Build Coastguard Worker return(NULL);
2959*7c568831SAndroid Build Coastguard Worker
2960*7c568831SAndroid Build Coastguard Worker localname = xmlSplitQName4(name, &prefix);
2961*7c568831SAndroid Build Coastguard Worker if (localname == NULL)
2962*7c568831SAndroid Build Coastguard Worker return(NULL);
2963*7c568831SAndroid Build Coastguard Worker cur = xmlHashLookup2(table, localname, prefix);
2964*7c568831SAndroid Build Coastguard Worker if (prefix != NULL)
2965*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
2966*7c568831SAndroid Build Coastguard Worker return(cur);
2967*7c568831SAndroid Build Coastguard Worker }
2968*7c568831SAndroid Build Coastguard Worker
2969*7c568831SAndroid Build Coastguard Worker /**
2970*7c568831SAndroid Build Coastguard Worker * xmlGetDtdElementDesc2:
2971*7c568831SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
2972*7c568831SAndroid Build Coastguard Worker * @name: the element name
2973*7c568831SAndroid Build Coastguard Worker * @create: create an empty description if not found
2974*7c568831SAndroid Build Coastguard Worker *
2975*7c568831SAndroid Build Coastguard Worker * Search the DTD for the description of this element
2976*7c568831SAndroid Build Coastguard Worker *
2977*7c568831SAndroid Build Coastguard Worker * returns the xmlElementPtr if found or NULL
2978*7c568831SAndroid Build Coastguard Worker */
2979*7c568831SAndroid Build Coastguard Worker
2980*7c568831SAndroid Build Coastguard Worker static xmlElementPtr
xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt,xmlDtdPtr dtd,const xmlChar * name)2981*7c568831SAndroid Build Coastguard Worker xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name) {
2982*7c568831SAndroid Build Coastguard Worker xmlElementTablePtr table;
2983*7c568831SAndroid Build Coastguard Worker xmlElementPtr cur = NULL;
2984*7c568831SAndroid Build Coastguard Worker const xmlChar *localName;
2985*7c568831SAndroid Build Coastguard Worker xmlChar *prefix = NULL;
2986*7c568831SAndroid Build Coastguard Worker
2987*7c568831SAndroid Build Coastguard Worker if (dtd == NULL) return(NULL);
2988*7c568831SAndroid Build Coastguard Worker
2989*7c568831SAndroid Build Coastguard Worker /*
2990*7c568831SAndroid Build Coastguard Worker * Create the Element table if needed.
2991*7c568831SAndroid Build Coastguard Worker */
2992*7c568831SAndroid Build Coastguard Worker if (dtd->elements == NULL) {
2993*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
2994*7c568831SAndroid Build Coastguard Worker
2995*7c568831SAndroid Build Coastguard Worker if (dtd->doc != NULL)
2996*7c568831SAndroid Build Coastguard Worker dict = dtd->doc->dict;
2997*7c568831SAndroid Build Coastguard Worker
2998*7c568831SAndroid Build Coastguard Worker dtd->elements = xmlHashCreateDict(0, dict);
2999*7c568831SAndroid Build Coastguard Worker if (dtd->elements == NULL)
3000*7c568831SAndroid Build Coastguard Worker goto mem_error;
3001*7c568831SAndroid Build Coastguard Worker }
3002*7c568831SAndroid Build Coastguard Worker table = (xmlElementTablePtr) dtd->elements;
3003*7c568831SAndroid Build Coastguard Worker
3004*7c568831SAndroid Build Coastguard Worker localName = xmlSplitQName4(name, &prefix);
3005*7c568831SAndroid Build Coastguard Worker if (localName == NULL)
3006*7c568831SAndroid Build Coastguard Worker goto mem_error;
3007*7c568831SAndroid Build Coastguard Worker cur = xmlHashLookup2(table, localName, prefix);
3008*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
3009*7c568831SAndroid Build Coastguard Worker cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
3010*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
3011*7c568831SAndroid Build Coastguard Worker goto mem_error;
3012*7c568831SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlElement));
3013*7c568831SAndroid Build Coastguard Worker cur->type = XML_ELEMENT_DECL;
3014*7c568831SAndroid Build Coastguard Worker cur->doc = dtd->doc;
3015*7c568831SAndroid Build Coastguard Worker
3016*7c568831SAndroid Build Coastguard Worker /*
3017*7c568831SAndroid Build Coastguard Worker * fill the structure.
3018*7c568831SAndroid Build Coastguard Worker */
3019*7c568831SAndroid Build Coastguard Worker cur->name = xmlStrdup(localName);
3020*7c568831SAndroid Build Coastguard Worker if (cur->name == NULL)
3021*7c568831SAndroid Build Coastguard Worker goto mem_error;
3022*7c568831SAndroid Build Coastguard Worker cur->prefix = prefix;
3023*7c568831SAndroid Build Coastguard Worker prefix = NULL;
3024*7c568831SAndroid Build Coastguard Worker cur->etype = XML_ELEMENT_TYPE_UNDEFINED;
3025*7c568831SAndroid Build Coastguard Worker
3026*7c568831SAndroid Build Coastguard Worker if (xmlHashAdd2(table, localName, cur->prefix, cur) <= 0)
3027*7c568831SAndroid Build Coastguard Worker goto mem_error;
3028*7c568831SAndroid Build Coastguard Worker }
3029*7c568831SAndroid Build Coastguard Worker
3030*7c568831SAndroid Build Coastguard Worker if (prefix != NULL)
3031*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
3032*7c568831SAndroid Build Coastguard Worker return(cur);
3033*7c568831SAndroid Build Coastguard Worker
3034*7c568831SAndroid Build Coastguard Worker mem_error:
3035*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
3036*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
3037*7c568831SAndroid Build Coastguard Worker xmlFreeElement(cur);
3038*7c568831SAndroid Build Coastguard Worker return(NULL);
3039*7c568831SAndroid Build Coastguard Worker }
3040*7c568831SAndroid Build Coastguard Worker
3041*7c568831SAndroid Build Coastguard Worker /**
3042*7c568831SAndroid Build Coastguard Worker * xmlGetDtdQElementDesc:
3043*7c568831SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
3044*7c568831SAndroid Build Coastguard Worker * @name: the element name
3045*7c568831SAndroid Build Coastguard Worker * @prefix: the element namespace prefix
3046*7c568831SAndroid Build Coastguard Worker *
3047*7c568831SAndroid Build Coastguard Worker * Search the DTD for the description of this element
3048*7c568831SAndroid Build Coastguard Worker *
3049*7c568831SAndroid Build Coastguard Worker * returns the xmlElementPtr if found or NULL
3050*7c568831SAndroid Build Coastguard Worker */
3051*7c568831SAndroid Build Coastguard Worker
3052*7c568831SAndroid Build Coastguard Worker xmlElementPtr
xmlGetDtdQElementDesc(xmlDtdPtr dtd,const xmlChar * name,const xmlChar * prefix)3053*7c568831SAndroid Build Coastguard Worker xmlGetDtdQElementDesc(xmlDtdPtr dtd, const xmlChar *name,
3054*7c568831SAndroid Build Coastguard Worker const xmlChar *prefix) {
3055*7c568831SAndroid Build Coastguard Worker xmlElementTablePtr table;
3056*7c568831SAndroid Build Coastguard Worker
3057*7c568831SAndroid Build Coastguard Worker if (dtd == NULL) return(NULL);
3058*7c568831SAndroid Build Coastguard Worker if (dtd->elements == NULL) return(NULL);
3059*7c568831SAndroid Build Coastguard Worker table = (xmlElementTablePtr) dtd->elements;
3060*7c568831SAndroid Build Coastguard Worker
3061*7c568831SAndroid Build Coastguard Worker return(xmlHashLookup2(table, name, prefix));
3062*7c568831SAndroid Build Coastguard Worker }
3063*7c568831SAndroid Build Coastguard Worker
3064*7c568831SAndroid Build Coastguard Worker /**
3065*7c568831SAndroid Build Coastguard Worker * xmlGetDtdAttrDesc:
3066*7c568831SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
3067*7c568831SAndroid Build Coastguard Worker * @elem: the element name
3068*7c568831SAndroid Build Coastguard Worker * @name: the attribute name
3069*7c568831SAndroid Build Coastguard Worker *
3070*7c568831SAndroid Build Coastguard Worker * Search the DTD for the description of this attribute on
3071*7c568831SAndroid Build Coastguard Worker * this element.
3072*7c568831SAndroid Build Coastguard Worker *
3073*7c568831SAndroid Build Coastguard Worker * returns the xmlAttributePtr if found or NULL
3074*7c568831SAndroid Build Coastguard Worker */
3075*7c568831SAndroid Build Coastguard Worker
3076*7c568831SAndroid Build Coastguard Worker xmlAttributePtr
xmlGetDtdAttrDesc(xmlDtdPtr dtd,const xmlChar * elem,const xmlChar * name)3077*7c568831SAndroid Build Coastguard Worker xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name) {
3078*7c568831SAndroid Build Coastguard Worker xmlAttributeTablePtr table;
3079*7c568831SAndroid Build Coastguard Worker xmlAttributePtr cur;
3080*7c568831SAndroid Build Coastguard Worker const xmlChar *localname;
3081*7c568831SAndroid Build Coastguard Worker xmlChar *prefix = NULL;
3082*7c568831SAndroid Build Coastguard Worker
3083*7c568831SAndroid Build Coastguard Worker if ((dtd == NULL) || (dtd->attributes == NULL) ||
3084*7c568831SAndroid Build Coastguard Worker (elem == NULL) || (name == NULL))
3085*7c568831SAndroid Build Coastguard Worker return(NULL);
3086*7c568831SAndroid Build Coastguard Worker
3087*7c568831SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) dtd->attributes;
3088*7c568831SAndroid Build Coastguard Worker if (table == NULL)
3089*7c568831SAndroid Build Coastguard Worker return(NULL);
3090*7c568831SAndroid Build Coastguard Worker
3091*7c568831SAndroid Build Coastguard Worker localname = xmlSplitQName4(name, &prefix);
3092*7c568831SAndroid Build Coastguard Worker if (localname == NULL)
3093*7c568831SAndroid Build Coastguard Worker return(NULL);
3094*7c568831SAndroid Build Coastguard Worker cur = xmlHashLookup3(table, localname, prefix, elem);
3095*7c568831SAndroid Build Coastguard Worker if (prefix != NULL)
3096*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
3097*7c568831SAndroid Build Coastguard Worker return(cur);
3098*7c568831SAndroid Build Coastguard Worker }
3099*7c568831SAndroid Build Coastguard Worker
3100*7c568831SAndroid Build Coastguard Worker /**
3101*7c568831SAndroid Build Coastguard Worker * xmlGetDtdQAttrDesc:
3102*7c568831SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
3103*7c568831SAndroid Build Coastguard Worker * @elem: the element name
3104*7c568831SAndroid Build Coastguard Worker * @name: the attribute name
3105*7c568831SAndroid Build Coastguard Worker * @prefix: the attribute namespace prefix
3106*7c568831SAndroid Build Coastguard Worker *
3107*7c568831SAndroid Build Coastguard Worker * Search the DTD for the description of this qualified attribute on
3108*7c568831SAndroid Build Coastguard Worker * this element.
3109*7c568831SAndroid Build Coastguard Worker *
3110*7c568831SAndroid Build Coastguard Worker * returns the xmlAttributePtr if found or NULL
3111*7c568831SAndroid Build Coastguard Worker */
3112*7c568831SAndroid Build Coastguard Worker
3113*7c568831SAndroid Build Coastguard Worker xmlAttributePtr
xmlGetDtdQAttrDesc(xmlDtdPtr dtd,const xmlChar * elem,const xmlChar * name,const xmlChar * prefix)3114*7c568831SAndroid Build Coastguard Worker xmlGetDtdQAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name,
3115*7c568831SAndroid Build Coastguard Worker const xmlChar *prefix) {
3116*7c568831SAndroid Build Coastguard Worker xmlAttributeTablePtr table;
3117*7c568831SAndroid Build Coastguard Worker
3118*7c568831SAndroid Build Coastguard Worker if (dtd == NULL) return(NULL);
3119*7c568831SAndroid Build Coastguard Worker if (dtd->attributes == NULL) return(NULL);
3120*7c568831SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) dtd->attributes;
3121*7c568831SAndroid Build Coastguard Worker
3122*7c568831SAndroid Build Coastguard Worker return(xmlHashLookup3(table, name, prefix, elem));
3123*7c568831SAndroid Build Coastguard Worker }
3124*7c568831SAndroid Build Coastguard Worker
3125*7c568831SAndroid Build Coastguard Worker /**
3126*7c568831SAndroid Build Coastguard Worker * xmlGetDtdNotationDesc:
3127*7c568831SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
3128*7c568831SAndroid Build Coastguard Worker * @name: the notation name
3129*7c568831SAndroid Build Coastguard Worker *
3130*7c568831SAndroid Build Coastguard Worker * Search the DTD for the description of this notation
3131*7c568831SAndroid Build Coastguard Worker *
3132*7c568831SAndroid Build Coastguard Worker * returns the xmlNotationPtr if found or NULL
3133*7c568831SAndroid Build Coastguard Worker */
3134*7c568831SAndroid Build Coastguard Worker
3135*7c568831SAndroid Build Coastguard Worker xmlNotationPtr
xmlGetDtdNotationDesc(xmlDtdPtr dtd,const xmlChar * name)3136*7c568831SAndroid Build Coastguard Worker xmlGetDtdNotationDesc(xmlDtdPtr dtd, const xmlChar *name) {
3137*7c568831SAndroid Build Coastguard Worker xmlNotationTablePtr table;
3138*7c568831SAndroid Build Coastguard Worker
3139*7c568831SAndroid Build Coastguard Worker if (dtd == NULL) return(NULL);
3140*7c568831SAndroid Build Coastguard Worker if (dtd->notations == NULL) return(NULL);
3141*7c568831SAndroid Build Coastguard Worker table = (xmlNotationTablePtr) dtd->notations;
3142*7c568831SAndroid Build Coastguard Worker
3143*7c568831SAndroid Build Coastguard Worker return(xmlHashLookup(table, name));
3144*7c568831SAndroid Build Coastguard Worker }
3145*7c568831SAndroid Build Coastguard Worker
3146*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
3147*7c568831SAndroid Build Coastguard Worker /**
3148*7c568831SAndroid Build Coastguard Worker * xmlValidateNotationUse:
3149*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
3150*7c568831SAndroid Build Coastguard Worker * @doc: the document
3151*7c568831SAndroid Build Coastguard Worker * @notationName: the notation name to check
3152*7c568831SAndroid Build Coastguard Worker *
3153*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
3154*7c568831SAndroid Build Coastguard Worker *
3155*7c568831SAndroid Build Coastguard Worker * Validate that the given name match a notation declaration.
3156*7c568831SAndroid Build Coastguard Worker * - [ VC: Notation Declared ]
3157*7c568831SAndroid Build Coastguard Worker *
3158*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3159*7c568831SAndroid Build Coastguard Worker */
3160*7c568831SAndroid Build Coastguard Worker
3161*7c568831SAndroid Build Coastguard Worker int
xmlValidateNotationUse(xmlValidCtxtPtr ctxt,xmlDocPtr doc,const xmlChar * notationName)3162*7c568831SAndroid Build Coastguard Worker xmlValidateNotationUse(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3163*7c568831SAndroid Build Coastguard Worker const xmlChar *notationName) {
3164*7c568831SAndroid Build Coastguard Worker xmlNotationPtr notaDecl;
3165*7c568831SAndroid Build Coastguard Worker if ((doc == NULL) || (doc->intSubset == NULL) ||
3166*7c568831SAndroid Build Coastguard Worker (notationName == NULL)) return(-1);
3167*7c568831SAndroid Build Coastguard Worker
3168*7c568831SAndroid Build Coastguard Worker notaDecl = xmlGetDtdNotationDesc(doc->intSubset, notationName);
3169*7c568831SAndroid Build Coastguard Worker if ((notaDecl == NULL) && (doc->extSubset != NULL))
3170*7c568831SAndroid Build Coastguard Worker notaDecl = xmlGetDtdNotationDesc(doc->extSubset, notationName);
3171*7c568831SAndroid Build Coastguard Worker
3172*7c568831SAndroid Build Coastguard Worker if (notaDecl == NULL) {
3173*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc, XML_DTD_UNKNOWN_NOTATION,
3174*7c568831SAndroid Build Coastguard Worker "NOTATION %s is not declared\n",
3175*7c568831SAndroid Build Coastguard Worker notationName, NULL, NULL);
3176*7c568831SAndroid Build Coastguard Worker return(0);
3177*7c568831SAndroid Build Coastguard Worker }
3178*7c568831SAndroid Build Coastguard Worker return(1);
3179*7c568831SAndroid Build Coastguard Worker }
3180*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
3181*7c568831SAndroid Build Coastguard Worker
3182*7c568831SAndroid Build Coastguard Worker /**
3183*7c568831SAndroid Build Coastguard Worker * xmlIsMixedElement:
3184*7c568831SAndroid Build Coastguard Worker * @doc: the document
3185*7c568831SAndroid Build Coastguard Worker * @name: the element name
3186*7c568831SAndroid Build Coastguard Worker *
3187*7c568831SAndroid Build Coastguard Worker * Search in the DtDs whether an element accept Mixed content (or ANY)
3188*7c568831SAndroid Build Coastguard Worker * basically if it is supposed to accept text childs
3189*7c568831SAndroid Build Coastguard Worker *
3190*7c568831SAndroid Build Coastguard Worker * returns 0 if no, 1 if yes, and -1 if no element description is available
3191*7c568831SAndroid Build Coastguard Worker */
3192*7c568831SAndroid Build Coastguard Worker
3193*7c568831SAndroid Build Coastguard Worker int
xmlIsMixedElement(xmlDocPtr doc,const xmlChar * name)3194*7c568831SAndroid Build Coastguard Worker xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name) {
3195*7c568831SAndroid Build Coastguard Worker xmlElementPtr elemDecl;
3196*7c568831SAndroid Build Coastguard Worker
3197*7c568831SAndroid Build Coastguard Worker if ((doc == NULL) || (doc->intSubset == NULL)) return(-1);
3198*7c568831SAndroid Build Coastguard Worker
3199*7c568831SAndroid Build Coastguard Worker elemDecl = xmlGetDtdElementDesc(doc->intSubset, name);
3200*7c568831SAndroid Build Coastguard Worker if ((elemDecl == NULL) && (doc->extSubset != NULL))
3201*7c568831SAndroid Build Coastguard Worker elemDecl = xmlGetDtdElementDesc(doc->extSubset, name);
3202*7c568831SAndroid Build Coastguard Worker if (elemDecl == NULL) return(-1);
3203*7c568831SAndroid Build Coastguard Worker switch (elemDecl->etype) {
3204*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_UNDEFINED:
3205*7c568831SAndroid Build Coastguard Worker return(-1);
3206*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ELEMENT:
3207*7c568831SAndroid Build Coastguard Worker return(0);
3208*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_EMPTY:
3209*7c568831SAndroid Build Coastguard Worker /*
3210*7c568831SAndroid Build Coastguard Worker * return 1 for EMPTY since we want VC error to pop up
3211*7c568831SAndroid Build Coastguard Worker * on <empty> </empty> for example
3212*7c568831SAndroid Build Coastguard Worker */
3213*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ANY:
3214*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_MIXED:
3215*7c568831SAndroid Build Coastguard Worker return(1);
3216*7c568831SAndroid Build Coastguard Worker }
3217*7c568831SAndroid Build Coastguard Worker return(1);
3218*7c568831SAndroid Build Coastguard Worker }
3219*7c568831SAndroid Build Coastguard Worker
3220*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
3221*7c568831SAndroid Build Coastguard Worker
3222*7c568831SAndroid Build Coastguard Worker /**
3223*7c568831SAndroid Build Coastguard Worker * xmlValidNormalizeString:
3224*7c568831SAndroid Build Coastguard Worker * @str: a string
3225*7c568831SAndroid Build Coastguard Worker *
3226*7c568831SAndroid Build Coastguard Worker * Normalize a string in-place.
3227*7c568831SAndroid Build Coastguard Worker */
3228*7c568831SAndroid Build Coastguard Worker static void
xmlValidNormalizeString(xmlChar * str)3229*7c568831SAndroid Build Coastguard Worker xmlValidNormalizeString(xmlChar *str) {
3230*7c568831SAndroid Build Coastguard Worker xmlChar *dst;
3231*7c568831SAndroid Build Coastguard Worker const xmlChar *src;
3232*7c568831SAndroid Build Coastguard Worker
3233*7c568831SAndroid Build Coastguard Worker if (str == NULL)
3234*7c568831SAndroid Build Coastguard Worker return;
3235*7c568831SAndroid Build Coastguard Worker src = str;
3236*7c568831SAndroid Build Coastguard Worker dst = str;
3237*7c568831SAndroid Build Coastguard Worker
3238*7c568831SAndroid Build Coastguard Worker while (*src == 0x20) src++;
3239*7c568831SAndroid Build Coastguard Worker while (*src != 0) {
3240*7c568831SAndroid Build Coastguard Worker if (*src == 0x20) {
3241*7c568831SAndroid Build Coastguard Worker while (*src == 0x20) src++;
3242*7c568831SAndroid Build Coastguard Worker if (*src != 0)
3243*7c568831SAndroid Build Coastguard Worker *dst++ = 0x20;
3244*7c568831SAndroid Build Coastguard Worker } else {
3245*7c568831SAndroid Build Coastguard Worker *dst++ = *src++;
3246*7c568831SAndroid Build Coastguard Worker }
3247*7c568831SAndroid Build Coastguard Worker }
3248*7c568831SAndroid Build Coastguard Worker *dst = 0;
3249*7c568831SAndroid Build Coastguard Worker }
3250*7c568831SAndroid Build Coastguard Worker
3251*7c568831SAndroid Build Coastguard Worker static int
xmlIsDocNameStartChar(xmlDocPtr doc,int c)3252*7c568831SAndroid Build Coastguard Worker xmlIsDocNameStartChar(xmlDocPtr doc, int c) {
3253*7c568831SAndroid Build Coastguard Worker if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
3254*7c568831SAndroid Build Coastguard Worker /*
3255*7c568831SAndroid Build Coastguard Worker * Use the new checks of production [4] [4a] amd [5] of the
3256*7c568831SAndroid Build Coastguard Worker * Update 5 of XML-1.0
3257*7c568831SAndroid Build Coastguard Worker */
3258*7c568831SAndroid Build Coastguard Worker if (((c >= 'a') && (c <= 'z')) ||
3259*7c568831SAndroid Build Coastguard Worker ((c >= 'A') && (c <= 'Z')) ||
3260*7c568831SAndroid Build Coastguard Worker (c == '_') || (c == ':') ||
3261*7c568831SAndroid Build Coastguard Worker ((c >= 0xC0) && (c <= 0xD6)) ||
3262*7c568831SAndroid Build Coastguard Worker ((c >= 0xD8) && (c <= 0xF6)) ||
3263*7c568831SAndroid Build Coastguard Worker ((c >= 0xF8) && (c <= 0x2FF)) ||
3264*7c568831SAndroid Build Coastguard Worker ((c >= 0x370) && (c <= 0x37D)) ||
3265*7c568831SAndroid Build Coastguard Worker ((c >= 0x37F) && (c <= 0x1FFF)) ||
3266*7c568831SAndroid Build Coastguard Worker ((c >= 0x200C) && (c <= 0x200D)) ||
3267*7c568831SAndroid Build Coastguard Worker ((c >= 0x2070) && (c <= 0x218F)) ||
3268*7c568831SAndroid Build Coastguard Worker ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3269*7c568831SAndroid Build Coastguard Worker ((c >= 0x3001) && (c <= 0xD7FF)) ||
3270*7c568831SAndroid Build Coastguard Worker ((c >= 0xF900) && (c <= 0xFDCF)) ||
3271*7c568831SAndroid Build Coastguard Worker ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3272*7c568831SAndroid Build Coastguard Worker ((c >= 0x10000) && (c <= 0xEFFFF)))
3273*7c568831SAndroid Build Coastguard Worker return(1);
3274*7c568831SAndroid Build Coastguard Worker } else {
3275*7c568831SAndroid Build Coastguard Worker if (IS_LETTER(c) || (c == '_') || (c == ':'))
3276*7c568831SAndroid Build Coastguard Worker return(1);
3277*7c568831SAndroid Build Coastguard Worker }
3278*7c568831SAndroid Build Coastguard Worker return(0);
3279*7c568831SAndroid Build Coastguard Worker }
3280*7c568831SAndroid Build Coastguard Worker
3281*7c568831SAndroid Build Coastguard Worker static int
xmlIsDocNameChar(xmlDocPtr doc,int c)3282*7c568831SAndroid Build Coastguard Worker xmlIsDocNameChar(xmlDocPtr doc, int c) {
3283*7c568831SAndroid Build Coastguard Worker if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
3284*7c568831SAndroid Build Coastguard Worker /*
3285*7c568831SAndroid Build Coastguard Worker * Use the new checks of production [4] [4a] amd [5] of the
3286*7c568831SAndroid Build Coastguard Worker * Update 5 of XML-1.0
3287*7c568831SAndroid Build Coastguard Worker */
3288*7c568831SAndroid Build Coastguard Worker if (((c >= 'a') && (c <= 'z')) ||
3289*7c568831SAndroid Build Coastguard Worker ((c >= 'A') && (c <= 'Z')) ||
3290*7c568831SAndroid Build Coastguard Worker ((c >= '0') && (c <= '9')) || /* !start */
3291*7c568831SAndroid Build Coastguard Worker (c == '_') || (c == ':') ||
3292*7c568831SAndroid Build Coastguard Worker (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3293*7c568831SAndroid Build Coastguard Worker ((c >= 0xC0) && (c <= 0xD6)) ||
3294*7c568831SAndroid Build Coastguard Worker ((c >= 0xD8) && (c <= 0xF6)) ||
3295*7c568831SAndroid Build Coastguard Worker ((c >= 0xF8) && (c <= 0x2FF)) ||
3296*7c568831SAndroid Build Coastguard Worker ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3297*7c568831SAndroid Build Coastguard Worker ((c >= 0x370) && (c <= 0x37D)) ||
3298*7c568831SAndroid Build Coastguard Worker ((c >= 0x37F) && (c <= 0x1FFF)) ||
3299*7c568831SAndroid Build Coastguard Worker ((c >= 0x200C) && (c <= 0x200D)) ||
3300*7c568831SAndroid Build Coastguard Worker ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3301*7c568831SAndroid Build Coastguard Worker ((c >= 0x2070) && (c <= 0x218F)) ||
3302*7c568831SAndroid Build Coastguard Worker ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3303*7c568831SAndroid Build Coastguard Worker ((c >= 0x3001) && (c <= 0xD7FF)) ||
3304*7c568831SAndroid Build Coastguard Worker ((c >= 0xF900) && (c <= 0xFDCF)) ||
3305*7c568831SAndroid Build Coastguard Worker ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3306*7c568831SAndroid Build Coastguard Worker ((c >= 0x10000) && (c <= 0xEFFFF)))
3307*7c568831SAndroid Build Coastguard Worker return(1);
3308*7c568831SAndroid Build Coastguard Worker } else {
3309*7c568831SAndroid Build Coastguard Worker if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3310*7c568831SAndroid Build Coastguard Worker (c == '.') || (c == '-') ||
3311*7c568831SAndroid Build Coastguard Worker (c == '_') || (c == ':') ||
3312*7c568831SAndroid Build Coastguard Worker (IS_COMBINING(c)) ||
3313*7c568831SAndroid Build Coastguard Worker (IS_EXTENDER(c)))
3314*7c568831SAndroid Build Coastguard Worker return(1);
3315*7c568831SAndroid Build Coastguard Worker }
3316*7c568831SAndroid Build Coastguard Worker return(0);
3317*7c568831SAndroid Build Coastguard Worker }
3318*7c568831SAndroid Build Coastguard Worker
3319*7c568831SAndroid Build Coastguard Worker /**
3320*7c568831SAndroid Build Coastguard Worker * xmlValidateNameValue:
3321*7c568831SAndroid Build Coastguard Worker * @doc: pointer to the document or NULL
3322*7c568831SAndroid Build Coastguard Worker * @value: an Name value
3323*7c568831SAndroid Build Coastguard Worker *
3324*7c568831SAndroid Build Coastguard Worker * Validate that the given value match Name production
3325*7c568831SAndroid Build Coastguard Worker *
3326*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3327*7c568831SAndroid Build Coastguard Worker */
3328*7c568831SAndroid Build Coastguard Worker
3329*7c568831SAndroid Build Coastguard Worker static int
xmlValidateNameValueInternal(xmlDocPtr doc,const xmlChar * value)3330*7c568831SAndroid Build Coastguard Worker xmlValidateNameValueInternal(xmlDocPtr doc, const xmlChar *value) {
3331*7c568831SAndroid Build Coastguard Worker const xmlChar *cur;
3332*7c568831SAndroid Build Coastguard Worker int val, len;
3333*7c568831SAndroid Build Coastguard Worker
3334*7c568831SAndroid Build Coastguard Worker if (value == NULL) return(0);
3335*7c568831SAndroid Build Coastguard Worker cur = value;
3336*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3337*7c568831SAndroid Build Coastguard Worker cur += len;
3338*7c568831SAndroid Build Coastguard Worker if (!xmlIsDocNameStartChar(doc, val))
3339*7c568831SAndroid Build Coastguard Worker return(0);
3340*7c568831SAndroid Build Coastguard Worker
3341*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3342*7c568831SAndroid Build Coastguard Worker cur += len;
3343*7c568831SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3344*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3345*7c568831SAndroid Build Coastguard Worker cur += len;
3346*7c568831SAndroid Build Coastguard Worker }
3347*7c568831SAndroid Build Coastguard Worker
3348*7c568831SAndroid Build Coastguard Worker if (val != 0) return(0);
3349*7c568831SAndroid Build Coastguard Worker
3350*7c568831SAndroid Build Coastguard Worker return(1);
3351*7c568831SAndroid Build Coastguard Worker }
3352*7c568831SAndroid Build Coastguard Worker
3353*7c568831SAndroid Build Coastguard Worker /**
3354*7c568831SAndroid Build Coastguard Worker * xmlValidateNameValue:
3355*7c568831SAndroid Build Coastguard Worker * @value: an Name value
3356*7c568831SAndroid Build Coastguard Worker *
3357*7c568831SAndroid Build Coastguard Worker * Validate that the given value match Name production
3358*7c568831SAndroid Build Coastguard Worker *
3359*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3360*7c568831SAndroid Build Coastguard Worker */
3361*7c568831SAndroid Build Coastguard Worker
3362*7c568831SAndroid Build Coastguard Worker int
xmlValidateNameValue(const xmlChar * value)3363*7c568831SAndroid Build Coastguard Worker xmlValidateNameValue(const xmlChar *value) {
3364*7c568831SAndroid Build Coastguard Worker return(xmlValidateNameValueInternal(NULL, value));
3365*7c568831SAndroid Build Coastguard Worker }
3366*7c568831SAndroid Build Coastguard Worker
3367*7c568831SAndroid Build Coastguard Worker /**
3368*7c568831SAndroid Build Coastguard Worker * xmlValidateNamesValueInternal:
3369*7c568831SAndroid Build Coastguard Worker * @doc: pointer to the document or NULL
3370*7c568831SAndroid Build Coastguard Worker * @value: an Names value
3371*7c568831SAndroid Build Coastguard Worker *
3372*7c568831SAndroid Build Coastguard Worker * Validate that the given value match Names production
3373*7c568831SAndroid Build Coastguard Worker *
3374*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3375*7c568831SAndroid Build Coastguard Worker */
3376*7c568831SAndroid Build Coastguard Worker
3377*7c568831SAndroid Build Coastguard Worker static int
xmlValidateNamesValueInternal(xmlDocPtr doc,const xmlChar * value)3378*7c568831SAndroid Build Coastguard Worker xmlValidateNamesValueInternal(xmlDocPtr doc, const xmlChar *value) {
3379*7c568831SAndroid Build Coastguard Worker const xmlChar *cur;
3380*7c568831SAndroid Build Coastguard Worker int val, len;
3381*7c568831SAndroid Build Coastguard Worker
3382*7c568831SAndroid Build Coastguard Worker if (value == NULL) return(0);
3383*7c568831SAndroid Build Coastguard Worker cur = value;
3384*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3385*7c568831SAndroid Build Coastguard Worker cur += len;
3386*7c568831SAndroid Build Coastguard Worker
3387*7c568831SAndroid Build Coastguard Worker if (!xmlIsDocNameStartChar(doc, val))
3388*7c568831SAndroid Build Coastguard Worker return(0);
3389*7c568831SAndroid Build Coastguard Worker
3390*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3391*7c568831SAndroid Build Coastguard Worker cur += len;
3392*7c568831SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3393*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3394*7c568831SAndroid Build Coastguard Worker cur += len;
3395*7c568831SAndroid Build Coastguard Worker }
3396*7c568831SAndroid Build Coastguard Worker
3397*7c568831SAndroid Build Coastguard Worker /* Should not test IS_BLANK(val) here -- see erratum E20*/
3398*7c568831SAndroid Build Coastguard Worker while (val == 0x20) {
3399*7c568831SAndroid Build Coastguard Worker while (val == 0x20) {
3400*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3401*7c568831SAndroid Build Coastguard Worker cur += len;
3402*7c568831SAndroid Build Coastguard Worker }
3403*7c568831SAndroid Build Coastguard Worker
3404*7c568831SAndroid Build Coastguard Worker if (!xmlIsDocNameStartChar(doc, val))
3405*7c568831SAndroid Build Coastguard Worker return(0);
3406*7c568831SAndroid Build Coastguard Worker
3407*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3408*7c568831SAndroid Build Coastguard Worker cur += len;
3409*7c568831SAndroid Build Coastguard Worker
3410*7c568831SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3411*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3412*7c568831SAndroid Build Coastguard Worker cur += len;
3413*7c568831SAndroid Build Coastguard Worker }
3414*7c568831SAndroid Build Coastguard Worker }
3415*7c568831SAndroid Build Coastguard Worker
3416*7c568831SAndroid Build Coastguard Worker if (val != 0) return(0);
3417*7c568831SAndroid Build Coastguard Worker
3418*7c568831SAndroid Build Coastguard Worker return(1);
3419*7c568831SAndroid Build Coastguard Worker }
3420*7c568831SAndroid Build Coastguard Worker
3421*7c568831SAndroid Build Coastguard Worker /**
3422*7c568831SAndroid Build Coastguard Worker * xmlValidateNamesValue:
3423*7c568831SAndroid Build Coastguard Worker * @value: an Names value
3424*7c568831SAndroid Build Coastguard Worker *
3425*7c568831SAndroid Build Coastguard Worker * Validate that the given value match Names production
3426*7c568831SAndroid Build Coastguard Worker *
3427*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3428*7c568831SAndroid Build Coastguard Worker */
3429*7c568831SAndroid Build Coastguard Worker
3430*7c568831SAndroid Build Coastguard Worker int
xmlValidateNamesValue(const xmlChar * value)3431*7c568831SAndroid Build Coastguard Worker xmlValidateNamesValue(const xmlChar *value) {
3432*7c568831SAndroid Build Coastguard Worker return(xmlValidateNamesValueInternal(NULL, value));
3433*7c568831SAndroid Build Coastguard Worker }
3434*7c568831SAndroid Build Coastguard Worker
3435*7c568831SAndroid Build Coastguard Worker /**
3436*7c568831SAndroid Build Coastguard Worker * xmlValidateNmtokenValueInternal:
3437*7c568831SAndroid Build Coastguard Worker * @doc: pointer to the document or NULL
3438*7c568831SAndroid Build Coastguard Worker * @value: an Nmtoken value
3439*7c568831SAndroid Build Coastguard Worker *
3440*7c568831SAndroid Build Coastguard Worker * Validate that the given value match Nmtoken production
3441*7c568831SAndroid Build Coastguard Worker *
3442*7c568831SAndroid Build Coastguard Worker * [ VC: Name Token ]
3443*7c568831SAndroid Build Coastguard Worker *
3444*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3445*7c568831SAndroid Build Coastguard Worker */
3446*7c568831SAndroid Build Coastguard Worker
3447*7c568831SAndroid Build Coastguard Worker static int
xmlValidateNmtokenValueInternal(xmlDocPtr doc,const xmlChar * value)3448*7c568831SAndroid Build Coastguard Worker xmlValidateNmtokenValueInternal(xmlDocPtr doc, const xmlChar *value) {
3449*7c568831SAndroid Build Coastguard Worker const xmlChar *cur;
3450*7c568831SAndroid Build Coastguard Worker int val, len;
3451*7c568831SAndroid Build Coastguard Worker
3452*7c568831SAndroid Build Coastguard Worker if (value == NULL) return(0);
3453*7c568831SAndroid Build Coastguard Worker cur = value;
3454*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3455*7c568831SAndroid Build Coastguard Worker cur += len;
3456*7c568831SAndroid Build Coastguard Worker
3457*7c568831SAndroid Build Coastguard Worker if (!xmlIsDocNameChar(doc, val))
3458*7c568831SAndroid Build Coastguard Worker return(0);
3459*7c568831SAndroid Build Coastguard Worker
3460*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3461*7c568831SAndroid Build Coastguard Worker cur += len;
3462*7c568831SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3463*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3464*7c568831SAndroid Build Coastguard Worker cur += len;
3465*7c568831SAndroid Build Coastguard Worker }
3466*7c568831SAndroid Build Coastguard Worker
3467*7c568831SAndroid Build Coastguard Worker if (val != 0) return(0);
3468*7c568831SAndroid Build Coastguard Worker
3469*7c568831SAndroid Build Coastguard Worker return(1);
3470*7c568831SAndroid Build Coastguard Worker }
3471*7c568831SAndroid Build Coastguard Worker
3472*7c568831SAndroid Build Coastguard Worker /**
3473*7c568831SAndroid Build Coastguard Worker * xmlValidateNmtokenValue:
3474*7c568831SAndroid Build Coastguard Worker * @value: an Nmtoken value
3475*7c568831SAndroid Build Coastguard Worker *
3476*7c568831SAndroid Build Coastguard Worker * Validate that the given value match Nmtoken production
3477*7c568831SAndroid Build Coastguard Worker *
3478*7c568831SAndroid Build Coastguard Worker * [ VC: Name Token ]
3479*7c568831SAndroid Build Coastguard Worker *
3480*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3481*7c568831SAndroid Build Coastguard Worker */
3482*7c568831SAndroid Build Coastguard Worker
3483*7c568831SAndroid Build Coastguard Worker int
xmlValidateNmtokenValue(const xmlChar * value)3484*7c568831SAndroid Build Coastguard Worker xmlValidateNmtokenValue(const xmlChar *value) {
3485*7c568831SAndroid Build Coastguard Worker return(xmlValidateNmtokenValueInternal(NULL, value));
3486*7c568831SAndroid Build Coastguard Worker }
3487*7c568831SAndroid Build Coastguard Worker
3488*7c568831SAndroid Build Coastguard Worker /**
3489*7c568831SAndroid Build Coastguard Worker * xmlValidateNmtokensValueInternal:
3490*7c568831SAndroid Build Coastguard Worker * @doc: pointer to the document or NULL
3491*7c568831SAndroid Build Coastguard Worker * @value: an Nmtokens value
3492*7c568831SAndroid Build Coastguard Worker *
3493*7c568831SAndroid Build Coastguard Worker * Validate that the given value match Nmtokens production
3494*7c568831SAndroid Build Coastguard Worker *
3495*7c568831SAndroid Build Coastguard Worker * [ VC: Name Token ]
3496*7c568831SAndroid Build Coastguard Worker *
3497*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3498*7c568831SAndroid Build Coastguard Worker */
3499*7c568831SAndroid Build Coastguard Worker
3500*7c568831SAndroid Build Coastguard Worker static int
xmlValidateNmtokensValueInternal(xmlDocPtr doc,const xmlChar * value)3501*7c568831SAndroid Build Coastguard Worker xmlValidateNmtokensValueInternal(xmlDocPtr doc, const xmlChar *value) {
3502*7c568831SAndroid Build Coastguard Worker const xmlChar *cur;
3503*7c568831SAndroid Build Coastguard Worker int val, len;
3504*7c568831SAndroid Build Coastguard Worker
3505*7c568831SAndroid Build Coastguard Worker if (value == NULL) return(0);
3506*7c568831SAndroid Build Coastguard Worker cur = value;
3507*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3508*7c568831SAndroid Build Coastguard Worker cur += len;
3509*7c568831SAndroid Build Coastguard Worker
3510*7c568831SAndroid Build Coastguard Worker while (IS_BLANK(val)) {
3511*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3512*7c568831SAndroid Build Coastguard Worker cur += len;
3513*7c568831SAndroid Build Coastguard Worker }
3514*7c568831SAndroid Build Coastguard Worker
3515*7c568831SAndroid Build Coastguard Worker if (!xmlIsDocNameChar(doc, val))
3516*7c568831SAndroid Build Coastguard Worker return(0);
3517*7c568831SAndroid Build Coastguard Worker
3518*7c568831SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3519*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3520*7c568831SAndroid Build Coastguard Worker cur += len;
3521*7c568831SAndroid Build Coastguard Worker }
3522*7c568831SAndroid Build Coastguard Worker
3523*7c568831SAndroid Build Coastguard Worker /* Should not test IS_BLANK(val) here -- see erratum E20*/
3524*7c568831SAndroid Build Coastguard Worker while (val == 0x20) {
3525*7c568831SAndroid Build Coastguard Worker while (val == 0x20) {
3526*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3527*7c568831SAndroid Build Coastguard Worker cur += len;
3528*7c568831SAndroid Build Coastguard Worker }
3529*7c568831SAndroid Build Coastguard Worker if (val == 0) return(1);
3530*7c568831SAndroid Build Coastguard Worker
3531*7c568831SAndroid Build Coastguard Worker if (!xmlIsDocNameChar(doc, val))
3532*7c568831SAndroid Build Coastguard Worker return(0);
3533*7c568831SAndroid Build Coastguard Worker
3534*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3535*7c568831SAndroid Build Coastguard Worker cur += len;
3536*7c568831SAndroid Build Coastguard Worker
3537*7c568831SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3538*7c568831SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3539*7c568831SAndroid Build Coastguard Worker cur += len;
3540*7c568831SAndroid Build Coastguard Worker }
3541*7c568831SAndroid Build Coastguard Worker }
3542*7c568831SAndroid Build Coastguard Worker
3543*7c568831SAndroid Build Coastguard Worker if (val != 0) return(0);
3544*7c568831SAndroid Build Coastguard Worker
3545*7c568831SAndroid Build Coastguard Worker return(1);
3546*7c568831SAndroid Build Coastguard Worker }
3547*7c568831SAndroid Build Coastguard Worker
3548*7c568831SAndroid Build Coastguard Worker /**
3549*7c568831SAndroid Build Coastguard Worker * xmlValidateNmtokensValue:
3550*7c568831SAndroid Build Coastguard Worker * @value: an Nmtokens value
3551*7c568831SAndroid Build Coastguard Worker *
3552*7c568831SAndroid Build Coastguard Worker * Validate that the given value match Nmtokens production
3553*7c568831SAndroid Build Coastguard Worker *
3554*7c568831SAndroid Build Coastguard Worker * [ VC: Name Token ]
3555*7c568831SAndroid Build Coastguard Worker *
3556*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3557*7c568831SAndroid Build Coastguard Worker */
3558*7c568831SAndroid Build Coastguard Worker
3559*7c568831SAndroid Build Coastguard Worker int
xmlValidateNmtokensValue(const xmlChar * value)3560*7c568831SAndroid Build Coastguard Worker xmlValidateNmtokensValue(const xmlChar *value) {
3561*7c568831SAndroid Build Coastguard Worker return(xmlValidateNmtokensValueInternal(NULL, value));
3562*7c568831SAndroid Build Coastguard Worker }
3563*7c568831SAndroid Build Coastguard Worker
3564*7c568831SAndroid Build Coastguard Worker /**
3565*7c568831SAndroid Build Coastguard Worker * xmlValidateNotationDecl:
3566*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
3567*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
3568*7c568831SAndroid Build Coastguard Worker * @nota: a notation definition
3569*7c568831SAndroid Build Coastguard Worker *
3570*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
3571*7c568831SAndroid Build Coastguard Worker *
3572*7c568831SAndroid Build Coastguard Worker * Try to validate a single notation definition
3573*7c568831SAndroid Build Coastguard Worker * basically it does the following checks as described by the
3574*7c568831SAndroid Build Coastguard Worker * XML-1.0 recommendation:
3575*7c568831SAndroid Build Coastguard Worker * - it seems that no validity constraint exists on notation declarations
3576*7c568831SAndroid Build Coastguard Worker * But this function get called anyway ...
3577*7c568831SAndroid Build Coastguard Worker *
3578*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3579*7c568831SAndroid Build Coastguard Worker */
3580*7c568831SAndroid Build Coastguard Worker
3581*7c568831SAndroid Build Coastguard Worker int
xmlValidateNotationDecl(xmlValidCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlDocPtr doc ATTRIBUTE_UNUSED,xmlNotationPtr nota ATTRIBUTE_UNUSED)3582*7c568831SAndroid Build Coastguard Worker xmlValidateNotationDecl(xmlValidCtxtPtr ctxt ATTRIBUTE_UNUSED, xmlDocPtr doc ATTRIBUTE_UNUSED,
3583*7c568831SAndroid Build Coastguard Worker xmlNotationPtr nota ATTRIBUTE_UNUSED) {
3584*7c568831SAndroid Build Coastguard Worker int ret = 1;
3585*7c568831SAndroid Build Coastguard Worker
3586*7c568831SAndroid Build Coastguard Worker return(ret);
3587*7c568831SAndroid Build Coastguard Worker }
3588*7c568831SAndroid Build Coastguard Worker
3589*7c568831SAndroid Build Coastguard Worker /**
3590*7c568831SAndroid Build Coastguard Worker * xmlValidateAttributeValueInternal:
3591*7c568831SAndroid Build Coastguard Worker * @doc: the document
3592*7c568831SAndroid Build Coastguard Worker * @type: an attribute type
3593*7c568831SAndroid Build Coastguard Worker * @value: an attribute value
3594*7c568831SAndroid Build Coastguard Worker *
3595*7c568831SAndroid Build Coastguard Worker * Validate that the given attribute value match the proper production
3596*7c568831SAndroid Build Coastguard Worker *
3597*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3598*7c568831SAndroid Build Coastguard Worker */
3599*7c568831SAndroid Build Coastguard Worker
3600*7c568831SAndroid Build Coastguard Worker static int
xmlValidateAttributeValueInternal(xmlDocPtr doc,xmlAttributeType type,const xmlChar * value)3601*7c568831SAndroid Build Coastguard Worker xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
3602*7c568831SAndroid Build Coastguard Worker const xmlChar *value) {
3603*7c568831SAndroid Build Coastguard Worker switch (type) {
3604*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITIES:
3605*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREFS:
3606*7c568831SAndroid Build Coastguard Worker return(xmlValidateNamesValueInternal(doc, value));
3607*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITY:
3608*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREF:
3609*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ID:
3610*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NOTATION:
3611*7c568831SAndroid Build Coastguard Worker return(xmlValidateNameValueInternal(doc, value));
3612*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKENS:
3613*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENUMERATION:
3614*7c568831SAndroid Build Coastguard Worker return(xmlValidateNmtokensValueInternal(doc, value));
3615*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKEN:
3616*7c568831SAndroid Build Coastguard Worker return(xmlValidateNmtokenValueInternal(doc, value));
3617*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_CDATA:
3618*7c568831SAndroid Build Coastguard Worker break;
3619*7c568831SAndroid Build Coastguard Worker }
3620*7c568831SAndroid Build Coastguard Worker return(1);
3621*7c568831SAndroid Build Coastguard Worker }
3622*7c568831SAndroid Build Coastguard Worker
3623*7c568831SAndroid Build Coastguard Worker /**
3624*7c568831SAndroid Build Coastguard Worker * xmlValidateAttributeValue:
3625*7c568831SAndroid Build Coastguard Worker * @type: an attribute type
3626*7c568831SAndroid Build Coastguard Worker * @value: an attribute value
3627*7c568831SAndroid Build Coastguard Worker *
3628*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
3629*7c568831SAndroid Build Coastguard Worker *
3630*7c568831SAndroid Build Coastguard Worker * Validate that the given attribute value match the proper production
3631*7c568831SAndroid Build Coastguard Worker *
3632*7c568831SAndroid Build Coastguard Worker * [ VC: ID ]
3633*7c568831SAndroid Build Coastguard Worker * Values of type ID must match the Name production....
3634*7c568831SAndroid Build Coastguard Worker *
3635*7c568831SAndroid Build Coastguard Worker * [ VC: IDREF ]
3636*7c568831SAndroid Build Coastguard Worker * Values of type IDREF must match the Name production, and values
3637*7c568831SAndroid Build Coastguard Worker * of type IDREFS must match Names ...
3638*7c568831SAndroid Build Coastguard Worker *
3639*7c568831SAndroid Build Coastguard Worker * [ VC: Entity Name ]
3640*7c568831SAndroid Build Coastguard Worker * Values of type ENTITY must match the Name production, values
3641*7c568831SAndroid Build Coastguard Worker * of type ENTITIES must match Names ...
3642*7c568831SAndroid Build Coastguard Worker *
3643*7c568831SAndroid Build Coastguard Worker * [ VC: Name Token ]
3644*7c568831SAndroid Build Coastguard Worker * Values of type NMTOKEN must match the Nmtoken production; values
3645*7c568831SAndroid Build Coastguard Worker * of type NMTOKENS must match Nmtokens.
3646*7c568831SAndroid Build Coastguard Worker *
3647*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3648*7c568831SAndroid Build Coastguard Worker */
3649*7c568831SAndroid Build Coastguard Worker int
xmlValidateAttributeValue(xmlAttributeType type,const xmlChar * value)3650*7c568831SAndroid Build Coastguard Worker xmlValidateAttributeValue(xmlAttributeType type, const xmlChar *value) {
3651*7c568831SAndroid Build Coastguard Worker return(xmlValidateAttributeValueInternal(NULL, type, value));
3652*7c568831SAndroid Build Coastguard Worker }
3653*7c568831SAndroid Build Coastguard Worker
3654*7c568831SAndroid Build Coastguard Worker /**
3655*7c568831SAndroid Build Coastguard Worker * xmlValidateAttributeValue2:
3656*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
3657*7c568831SAndroid Build Coastguard Worker * @doc: the document
3658*7c568831SAndroid Build Coastguard Worker * @name: the attribute name (used for error reporting only)
3659*7c568831SAndroid Build Coastguard Worker * @type: the attribute type
3660*7c568831SAndroid Build Coastguard Worker * @value: the attribute value
3661*7c568831SAndroid Build Coastguard Worker *
3662*7c568831SAndroid Build Coastguard Worker * Validate that the given attribute value match a given type.
3663*7c568831SAndroid Build Coastguard Worker * This typically cannot be done before having finished parsing
3664*7c568831SAndroid Build Coastguard Worker * the subsets.
3665*7c568831SAndroid Build Coastguard Worker *
3666*7c568831SAndroid Build Coastguard Worker * [ VC: IDREF ]
3667*7c568831SAndroid Build Coastguard Worker * Values of type IDREF must match one of the declared IDs
3668*7c568831SAndroid Build Coastguard Worker * Values of type IDREFS must match a sequence of the declared IDs
3669*7c568831SAndroid Build Coastguard Worker * each Name must match the value of an ID attribute on some element
3670*7c568831SAndroid Build Coastguard Worker * in the XML document; i.e. IDREF values must match the value of
3671*7c568831SAndroid Build Coastguard Worker * some ID attribute
3672*7c568831SAndroid Build Coastguard Worker *
3673*7c568831SAndroid Build Coastguard Worker * [ VC: Entity Name ]
3674*7c568831SAndroid Build Coastguard Worker * Values of type ENTITY must match one declared entity
3675*7c568831SAndroid Build Coastguard Worker * Values of type ENTITIES must match a sequence of declared entities
3676*7c568831SAndroid Build Coastguard Worker *
3677*7c568831SAndroid Build Coastguard Worker * [ VC: Notation Attributes ]
3678*7c568831SAndroid Build Coastguard Worker * all notation names in the declaration must be declared.
3679*7c568831SAndroid Build Coastguard Worker *
3680*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3681*7c568831SAndroid Build Coastguard Worker */
3682*7c568831SAndroid Build Coastguard Worker
3683*7c568831SAndroid Build Coastguard Worker static int
xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt,xmlDocPtr doc,const xmlChar * name,xmlAttributeType type,const xmlChar * value)3684*7c568831SAndroid Build Coastguard Worker xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3685*7c568831SAndroid Build Coastguard Worker const xmlChar *name, xmlAttributeType type, const xmlChar *value) {
3686*7c568831SAndroid Build Coastguard Worker int ret = 1;
3687*7c568831SAndroid Build Coastguard Worker switch (type) {
3688*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREFS:
3689*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREF:
3690*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ID:
3691*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKENS:
3692*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENUMERATION:
3693*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKEN:
3694*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_CDATA:
3695*7c568831SAndroid Build Coastguard Worker break;
3696*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITY: {
3697*7c568831SAndroid Build Coastguard Worker xmlEntityPtr ent;
3698*7c568831SAndroid Build Coastguard Worker
3699*7c568831SAndroid Build Coastguard Worker ent = xmlGetDocEntity(doc, value);
3700*7c568831SAndroid Build Coastguard Worker /* yeah it's a bit messy... */
3701*7c568831SAndroid Build Coastguard Worker if ((ent == NULL) && (doc->standalone == 1)) {
3702*7c568831SAndroid Build Coastguard Worker doc->standalone = 0;
3703*7c568831SAndroid Build Coastguard Worker ent = xmlGetDocEntity(doc, value);
3704*7c568831SAndroid Build Coastguard Worker }
3705*7c568831SAndroid Build Coastguard Worker if (ent == NULL) {
3706*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3707*7c568831SAndroid Build Coastguard Worker XML_DTD_UNKNOWN_ENTITY,
3708*7c568831SAndroid Build Coastguard Worker "ENTITY attribute %s reference an unknown entity \"%s\"\n",
3709*7c568831SAndroid Build Coastguard Worker name, value, NULL);
3710*7c568831SAndroid Build Coastguard Worker ret = 0;
3711*7c568831SAndroid Build Coastguard Worker } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
3712*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3713*7c568831SAndroid Build Coastguard Worker XML_DTD_ENTITY_TYPE,
3714*7c568831SAndroid Build Coastguard Worker "ENTITY attribute %s reference an entity \"%s\" of wrong type\n",
3715*7c568831SAndroid Build Coastguard Worker name, value, NULL);
3716*7c568831SAndroid Build Coastguard Worker ret = 0;
3717*7c568831SAndroid Build Coastguard Worker }
3718*7c568831SAndroid Build Coastguard Worker break;
3719*7c568831SAndroid Build Coastguard Worker }
3720*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITIES: {
3721*7c568831SAndroid Build Coastguard Worker xmlChar *dup, *nam = NULL, *cur, save;
3722*7c568831SAndroid Build Coastguard Worker xmlEntityPtr ent;
3723*7c568831SAndroid Build Coastguard Worker
3724*7c568831SAndroid Build Coastguard Worker dup = xmlStrdup(value);
3725*7c568831SAndroid Build Coastguard Worker if (dup == NULL) {
3726*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
3727*7c568831SAndroid Build Coastguard Worker return(0);
3728*7c568831SAndroid Build Coastguard Worker }
3729*7c568831SAndroid Build Coastguard Worker cur = dup;
3730*7c568831SAndroid Build Coastguard Worker while (*cur != 0) {
3731*7c568831SAndroid Build Coastguard Worker nam = cur;
3732*7c568831SAndroid Build Coastguard Worker while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
3733*7c568831SAndroid Build Coastguard Worker save = *cur;
3734*7c568831SAndroid Build Coastguard Worker *cur = 0;
3735*7c568831SAndroid Build Coastguard Worker ent = xmlGetDocEntity(doc, nam);
3736*7c568831SAndroid Build Coastguard Worker if (ent == NULL) {
3737*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3738*7c568831SAndroid Build Coastguard Worker XML_DTD_UNKNOWN_ENTITY,
3739*7c568831SAndroid Build Coastguard Worker "ENTITIES attribute %s reference an unknown entity \"%s\"\n",
3740*7c568831SAndroid Build Coastguard Worker name, nam, NULL);
3741*7c568831SAndroid Build Coastguard Worker ret = 0;
3742*7c568831SAndroid Build Coastguard Worker } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
3743*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3744*7c568831SAndroid Build Coastguard Worker XML_DTD_ENTITY_TYPE,
3745*7c568831SAndroid Build Coastguard Worker "ENTITIES attribute %s reference an entity \"%s\" of wrong type\n",
3746*7c568831SAndroid Build Coastguard Worker name, nam, NULL);
3747*7c568831SAndroid Build Coastguard Worker ret = 0;
3748*7c568831SAndroid Build Coastguard Worker }
3749*7c568831SAndroid Build Coastguard Worker if (save == 0)
3750*7c568831SAndroid Build Coastguard Worker break;
3751*7c568831SAndroid Build Coastguard Worker *cur = save;
3752*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
3753*7c568831SAndroid Build Coastguard Worker }
3754*7c568831SAndroid Build Coastguard Worker xmlFree(dup);
3755*7c568831SAndroid Build Coastguard Worker break;
3756*7c568831SAndroid Build Coastguard Worker }
3757*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NOTATION: {
3758*7c568831SAndroid Build Coastguard Worker xmlNotationPtr nota;
3759*7c568831SAndroid Build Coastguard Worker
3760*7c568831SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->intSubset, value);
3761*7c568831SAndroid Build Coastguard Worker if ((nota == NULL) && (doc->extSubset != NULL))
3762*7c568831SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->extSubset, value);
3763*7c568831SAndroid Build Coastguard Worker
3764*7c568831SAndroid Build Coastguard Worker if (nota == NULL) {
3765*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3766*7c568831SAndroid Build Coastguard Worker XML_DTD_UNKNOWN_NOTATION,
3767*7c568831SAndroid Build Coastguard Worker "NOTATION attribute %s reference an unknown notation \"%s\"\n",
3768*7c568831SAndroid Build Coastguard Worker name, value, NULL);
3769*7c568831SAndroid Build Coastguard Worker ret = 0;
3770*7c568831SAndroid Build Coastguard Worker }
3771*7c568831SAndroid Build Coastguard Worker break;
3772*7c568831SAndroid Build Coastguard Worker }
3773*7c568831SAndroid Build Coastguard Worker }
3774*7c568831SAndroid Build Coastguard Worker return(ret);
3775*7c568831SAndroid Build Coastguard Worker }
3776*7c568831SAndroid Build Coastguard Worker
3777*7c568831SAndroid Build Coastguard Worker /**
3778*7c568831SAndroid Build Coastguard Worker * xmlValidCtxtNormalizeAttributeValue:
3779*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
3780*7c568831SAndroid Build Coastguard Worker * @doc: the document
3781*7c568831SAndroid Build Coastguard Worker * @elem: the parent
3782*7c568831SAndroid Build Coastguard Worker * @name: the attribute name
3783*7c568831SAndroid Build Coastguard Worker * @value: the attribute value
3784*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context or NULL
3785*7c568831SAndroid Build Coastguard Worker *
3786*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
3787*7c568831SAndroid Build Coastguard Worker *
3788*7c568831SAndroid Build Coastguard Worker * Does the validation related extra step of the normalization of attribute
3789*7c568831SAndroid Build Coastguard Worker * values:
3790*7c568831SAndroid Build Coastguard Worker *
3791*7c568831SAndroid Build Coastguard Worker * If the declared value is not CDATA, then the XML processor must further
3792*7c568831SAndroid Build Coastguard Worker * process the normalized attribute value by discarding any leading and
3793*7c568831SAndroid Build Coastguard Worker * trailing space (#x20) characters, and by replacing sequences of space
3794*7c568831SAndroid Build Coastguard Worker * (#x20) characters by single space (#x20) character.
3795*7c568831SAndroid Build Coastguard Worker *
3796*7c568831SAndroid Build Coastguard Worker * Also check VC: Standalone Document Declaration in P32, and update
3797*7c568831SAndroid Build Coastguard Worker * ctxt->valid accordingly
3798*7c568831SAndroid Build Coastguard Worker *
3799*7c568831SAndroid Build Coastguard Worker * returns a new normalized string if normalization is needed, NULL otherwise
3800*7c568831SAndroid Build Coastguard Worker * the caller must free the returned value.
3801*7c568831SAndroid Build Coastguard Worker */
3802*7c568831SAndroid Build Coastguard Worker
3803*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem,const xmlChar * name,const xmlChar * value)3804*7c568831SAndroid Build Coastguard Worker xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3805*7c568831SAndroid Build Coastguard Worker xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
3806*7c568831SAndroid Build Coastguard Worker xmlChar *ret;
3807*7c568831SAndroid Build Coastguard Worker xmlAttributePtr attrDecl = NULL;
3808*7c568831SAndroid Build Coastguard Worker const xmlChar *localName;
3809*7c568831SAndroid Build Coastguard Worker xmlChar *prefix = NULL;
3810*7c568831SAndroid Build Coastguard Worker int extsubset = 0;
3811*7c568831SAndroid Build Coastguard Worker
3812*7c568831SAndroid Build Coastguard Worker if (doc == NULL) return(NULL);
3813*7c568831SAndroid Build Coastguard Worker if (elem == NULL) return(NULL);
3814*7c568831SAndroid Build Coastguard Worker if (name == NULL) return(NULL);
3815*7c568831SAndroid Build Coastguard Worker if (value == NULL) return(NULL);
3816*7c568831SAndroid Build Coastguard Worker
3817*7c568831SAndroid Build Coastguard Worker localName = xmlSplitQName4(name, &prefix);
3818*7c568831SAndroid Build Coastguard Worker if (localName == NULL)
3819*7c568831SAndroid Build Coastguard Worker goto mem_error;
3820*7c568831SAndroid Build Coastguard Worker
3821*7c568831SAndroid Build Coastguard Worker if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
3822*7c568831SAndroid Build Coastguard Worker xmlChar buf[50];
3823*7c568831SAndroid Build Coastguard Worker xmlChar *elemname;
3824*7c568831SAndroid Build Coastguard Worker
3825*7c568831SAndroid Build Coastguard Worker elemname = xmlBuildQName(elem->name, elem->ns->prefix, buf, 50);
3826*7c568831SAndroid Build Coastguard Worker if (elemname == NULL)
3827*7c568831SAndroid Build Coastguard Worker goto mem_error;
3828*7c568831SAndroid Build Coastguard Worker if (doc->intSubset != NULL)
3829*7c568831SAndroid Build Coastguard Worker attrDecl = xmlHashLookup3(doc->intSubset->attributes, localName,
3830*7c568831SAndroid Build Coastguard Worker prefix, elemname);
3831*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
3832*7c568831SAndroid Build Coastguard Worker attrDecl = xmlHashLookup3(doc->extSubset->attributes, localName,
3833*7c568831SAndroid Build Coastguard Worker prefix, elemname);
3834*7c568831SAndroid Build Coastguard Worker if (attrDecl != NULL)
3835*7c568831SAndroid Build Coastguard Worker extsubset = 1;
3836*7c568831SAndroid Build Coastguard Worker }
3837*7c568831SAndroid Build Coastguard Worker if ((elemname != buf) && (elemname != elem->name))
3838*7c568831SAndroid Build Coastguard Worker xmlFree(elemname);
3839*7c568831SAndroid Build Coastguard Worker }
3840*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->intSubset != NULL))
3841*7c568831SAndroid Build Coastguard Worker attrDecl = xmlHashLookup3(doc->intSubset->attributes, localName,
3842*7c568831SAndroid Build Coastguard Worker prefix, elem->name);
3843*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
3844*7c568831SAndroid Build Coastguard Worker attrDecl = xmlHashLookup3(doc->extSubset->attributes, localName,
3845*7c568831SAndroid Build Coastguard Worker prefix, elem->name);
3846*7c568831SAndroid Build Coastguard Worker if (attrDecl != NULL)
3847*7c568831SAndroid Build Coastguard Worker extsubset = 1;
3848*7c568831SAndroid Build Coastguard Worker }
3849*7c568831SAndroid Build Coastguard Worker
3850*7c568831SAndroid Build Coastguard Worker if (attrDecl == NULL)
3851*7c568831SAndroid Build Coastguard Worker goto done;
3852*7c568831SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
3853*7c568831SAndroid Build Coastguard Worker goto done;
3854*7c568831SAndroid Build Coastguard Worker
3855*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup(value);
3856*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
3857*7c568831SAndroid Build Coastguard Worker goto mem_error;
3858*7c568831SAndroid Build Coastguard Worker xmlValidNormalizeString(ret);
3859*7c568831SAndroid Build Coastguard Worker if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
3860*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
3861*7c568831SAndroid Build Coastguard Worker "standalone: %s on %s value had to be normalized based on external subset declaration\n",
3862*7c568831SAndroid Build Coastguard Worker name, elem->name, NULL);
3863*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
3864*7c568831SAndroid Build Coastguard Worker }
3865*7c568831SAndroid Build Coastguard Worker
3866*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
3867*7c568831SAndroid Build Coastguard Worker return(ret);
3868*7c568831SAndroid Build Coastguard Worker
3869*7c568831SAndroid Build Coastguard Worker mem_error:
3870*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
3871*7c568831SAndroid Build Coastguard Worker
3872*7c568831SAndroid Build Coastguard Worker done:
3873*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
3874*7c568831SAndroid Build Coastguard Worker return(NULL);
3875*7c568831SAndroid Build Coastguard Worker }
3876*7c568831SAndroid Build Coastguard Worker
3877*7c568831SAndroid Build Coastguard Worker /**
3878*7c568831SAndroid Build Coastguard Worker * xmlValidNormalizeAttributeValue:
3879*7c568831SAndroid Build Coastguard Worker * @doc: the document
3880*7c568831SAndroid Build Coastguard Worker * @elem: the parent
3881*7c568831SAndroid Build Coastguard Worker * @name: the attribute name
3882*7c568831SAndroid Build Coastguard Worker * @value: the attribute value
3883*7c568831SAndroid Build Coastguard Worker *
3884*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
3885*7c568831SAndroid Build Coastguard Worker *
3886*7c568831SAndroid Build Coastguard Worker * Does the validation related extra step of the normalization of attribute
3887*7c568831SAndroid Build Coastguard Worker * values:
3888*7c568831SAndroid Build Coastguard Worker *
3889*7c568831SAndroid Build Coastguard Worker * If the declared value is not CDATA, then the XML processor must further
3890*7c568831SAndroid Build Coastguard Worker * process the normalized attribute value by discarding any leading and
3891*7c568831SAndroid Build Coastguard Worker * trailing space (#x20) characters, and by replacing sequences of space
3892*7c568831SAndroid Build Coastguard Worker * (#x20) characters by single space (#x20) character.
3893*7c568831SAndroid Build Coastguard Worker *
3894*7c568831SAndroid Build Coastguard Worker * Returns a new normalized string if normalization is needed, NULL otherwise
3895*7c568831SAndroid Build Coastguard Worker * the caller must free the returned value.
3896*7c568831SAndroid Build Coastguard Worker */
3897*7c568831SAndroid Build Coastguard Worker
3898*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlValidNormalizeAttributeValue(xmlDocPtr doc,xmlNodePtr elem,const xmlChar * name,const xmlChar * value)3899*7c568831SAndroid Build Coastguard Worker xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
3900*7c568831SAndroid Build Coastguard Worker const xmlChar *name, const xmlChar *value) {
3901*7c568831SAndroid Build Coastguard Worker xmlChar *ret;
3902*7c568831SAndroid Build Coastguard Worker xmlAttributePtr attrDecl = NULL;
3903*7c568831SAndroid Build Coastguard Worker
3904*7c568831SAndroid Build Coastguard Worker if (doc == NULL) return(NULL);
3905*7c568831SAndroid Build Coastguard Worker if (elem == NULL) return(NULL);
3906*7c568831SAndroid Build Coastguard Worker if (name == NULL) return(NULL);
3907*7c568831SAndroid Build Coastguard Worker if (value == NULL) return(NULL);
3908*7c568831SAndroid Build Coastguard Worker
3909*7c568831SAndroid Build Coastguard Worker if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
3910*7c568831SAndroid Build Coastguard Worker xmlChar fn[50];
3911*7c568831SAndroid Build Coastguard Worker xmlChar *fullname;
3912*7c568831SAndroid Build Coastguard Worker
3913*7c568831SAndroid Build Coastguard Worker fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
3914*7c568831SAndroid Build Coastguard Worker if (fullname == NULL)
3915*7c568831SAndroid Build Coastguard Worker return(NULL);
3916*7c568831SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != elem->name))
3917*7c568831SAndroid Build Coastguard Worker xmlFree(fullname);
3918*7c568831SAndroid Build Coastguard Worker }
3919*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
3920*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
3921*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
3922*7c568831SAndroid Build Coastguard Worker
3923*7c568831SAndroid Build Coastguard Worker if (attrDecl == NULL)
3924*7c568831SAndroid Build Coastguard Worker return(NULL);
3925*7c568831SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
3926*7c568831SAndroid Build Coastguard Worker return(NULL);
3927*7c568831SAndroid Build Coastguard Worker
3928*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup(value);
3929*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
3930*7c568831SAndroid Build Coastguard Worker return(NULL);
3931*7c568831SAndroid Build Coastguard Worker xmlValidNormalizeString(ret);
3932*7c568831SAndroid Build Coastguard Worker return(ret);
3933*7c568831SAndroid Build Coastguard Worker }
3934*7c568831SAndroid Build Coastguard Worker
3935*7c568831SAndroid Build Coastguard Worker static void
xmlValidateAttributeIdCallback(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)3936*7c568831SAndroid Build Coastguard Worker xmlValidateAttributeIdCallback(void *payload, void *data,
3937*7c568831SAndroid Build Coastguard Worker const xmlChar *name ATTRIBUTE_UNUSED) {
3938*7c568831SAndroid Build Coastguard Worker xmlAttributePtr attr = (xmlAttributePtr) payload;
3939*7c568831SAndroid Build Coastguard Worker int *count = (int *) data;
3940*7c568831SAndroid Build Coastguard Worker if (attr->atype == XML_ATTRIBUTE_ID) (*count)++;
3941*7c568831SAndroid Build Coastguard Worker }
3942*7c568831SAndroid Build Coastguard Worker
3943*7c568831SAndroid Build Coastguard Worker /**
3944*7c568831SAndroid Build Coastguard Worker * xmlValidateAttributeDecl:
3945*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
3946*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
3947*7c568831SAndroid Build Coastguard Worker * @attr: an attribute definition
3948*7c568831SAndroid Build Coastguard Worker *
3949*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
3950*7c568831SAndroid Build Coastguard Worker *
3951*7c568831SAndroid Build Coastguard Worker * Try to validate a single attribute definition
3952*7c568831SAndroid Build Coastguard Worker * basically it does the following checks as described by the
3953*7c568831SAndroid Build Coastguard Worker * XML-1.0 recommendation:
3954*7c568831SAndroid Build Coastguard Worker * - [ VC: Attribute Default Legal ]
3955*7c568831SAndroid Build Coastguard Worker * - [ VC: Enumeration ]
3956*7c568831SAndroid Build Coastguard Worker * - [ VC: ID Attribute Default ]
3957*7c568831SAndroid Build Coastguard Worker *
3958*7c568831SAndroid Build Coastguard Worker * The ID/IDREF uniqueness and matching are done separately
3959*7c568831SAndroid Build Coastguard Worker *
3960*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3961*7c568831SAndroid Build Coastguard Worker */
3962*7c568831SAndroid Build Coastguard Worker
3963*7c568831SAndroid Build Coastguard Worker int
xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlAttributePtr attr)3964*7c568831SAndroid Build Coastguard Worker xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3965*7c568831SAndroid Build Coastguard Worker xmlAttributePtr attr) {
3966*7c568831SAndroid Build Coastguard Worker int ret = 1;
3967*7c568831SAndroid Build Coastguard Worker int val;
3968*7c568831SAndroid Build Coastguard Worker CHECK_DTD;
3969*7c568831SAndroid Build Coastguard Worker if(attr == NULL) return(1);
3970*7c568831SAndroid Build Coastguard Worker
3971*7c568831SAndroid Build Coastguard Worker /* Attribute Default Legal */
3972*7c568831SAndroid Build Coastguard Worker /* Enumeration */
3973*7c568831SAndroid Build Coastguard Worker if (attr->defaultValue != NULL) {
3974*7c568831SAndroid Build Coastguard Worker val = xmlValidateAttributeValueInternal(doc, attr->atype,
3975*7c568831SAndroid Build Coastguard Worker attr->defaultValue);
3976*7c568831SAndroid Build Coastguard Worker if (val == 0) {
3977*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_DEFAULT,
3978*7c568831SAndroid Build Coastguard Worker "Syntax of default value for attribute %s of %s is not valid\n",
3979*7c568831SAndroid Build Coastguard Worker attr->name, attr->elem, NULL);
3980*7c568831SAndroid Build Coastguard Worker }
3981*7c568831SAndroid Build Coastguard Worker ret &= val;
3982*7c568831SAndroid Build Coastguard Worker }
3983*7c568831SAndroid Build Coastguard Worker
3984*7c568831SAndroid Build Coastguard Worker /* ID Attribute Default */
3985*7c568831SAndroid Build Coastguard Worker if ((attr->atype == XML_ATTRIBUTE_ID)&&
3986*7c568831SAndroid Build Coastguard Worker (attr->def != XML_ATTRIBUTE_IMPLIED) &&
3987*7c568831SAndroid Build Coastguard Worker (attr->def != XML_ATTRIBUTE_REQUIRED)) {
3988*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_FIXED,
3989*7c568831SAndroid Build Coastguard Worker "ID attribute %s of %s is not valid must be #IMPLIED or #REQUIRED\n",
3990*7c568831SAndroid Build Coastguard Worker attr->name, attr->elem, NULL);
3991*7c568831SAndroid Build Coastguard Worker ret = 0;
3992*7c568831SAndroid Build Coastguard Worker }
3993*7c568831SAndroid Build Coastguard Worker
3994*7c568831SAndroid Build Coastguard Worker /* One ID per Element Type */
3995*7c568831SAndroid Build Coastguard Worker if (attr->atype == XML_ATTRIBUTE_ID) {
3996*7c568831SAndroid Build Coastguard Worker xmlElementPtr elem = NULL;
3997*7c568831SAndroid Build Coastguard Worker const xmlChar *elemLocalName;
3998*7c568831SAndroid Build Coastguard Worker xmlChar *elemPrefix;
3999*7c568831SAndroid Build Coastguard Worker int nbId;
4000*7c568831SAndroid Build Coastguard Worker
4001*7c568831SAndroid Build Coastguard Worker elemLocalName = xmlSplitQName4(attr->elem, &elemPrefix);
4002*7c568831SAndroid Build Coastguard Worker if (elemLocalName == NULL) {
4003*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
4004*7c568831SAndroid Build Coastguard Worker return(0);
4005*7c568831SAndroid Build Coastguard Worker }
4006*7c568831SAndroid Build Coastguard Worker
4007*7c568831SAndroid Build Coastguard Worker /* the trick is that we parse DtD as their own internal subset */
4008*7c568831SAndroid Build Coastguard Worker if (doc->intSubset != NULL)
4009*7c568831SAndroid Build Coastguard Worker elem = xmlHashLookup2(doc->intSubset->elements,
4010*7c568831SAndroid Build Coastguard Worker elemLocalName, elemPrefix);
4011*7c568831SAndroid Build Coastguard Worker if (elem != NULL) {
4012*7c568831SAndroid Build Coastguard Worker nbId = xmlScanIDAttributeDecl(ctxt, elem, 0);
4013*7c568831SAndroid Build Coastguard Worker } else {
4014*7c568831SAndroid Build Coastguard Worker xmlAttributeTablePtr table;
4015*7c568831SAndroid Build Coastguard Worker
4016*7c568831SAndroid Build Coastguard Worker /*
4017*7c568831SAndroid Build Coastguard Worker * The attribute may be declared in the internal subset and the
4018*7c568831SAndroid Build Coastguard Worker * element in the external subset.
4019*7c568831SAndroid Build Coastguard Worker */
4020*7c568831SAndroid Build Coastguard Worker nbId = 0;
4021*7c568831SAndroid Build Coastguard Worker if (doc->intSubset != NULL) {
4022*7c568831SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) doc->intSubset->attributes;
4023*7c568831SAndroid Build Coastguard Worker xmlHashScan3(table, NULL, NULL, attr->elem,
4024*7c568831SAndroid Build Coastguard Worker xmlValidateAttributeIdCallback, &nbId);
4025*7c568831SAndroid Build Coastguard Worker }
4026*7c568831SAndroid Build Coastguard Worker }
4027*7c568831SAndroid Build Coastguard Worker if (nbId > 1) {
4028*7c568831SAndroid Build Coastguard Worker
4029*7c568831SAndroid Build Coastguard Worker xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4030*7c568831SAndroid Build Coastguard Worker "Element %s has %d ID attribute defined in the internal subset : %s\n",
4031*7c568831SAndroid Build Coastguard Worker attr->elem, nbId, attr->name);
4032*7c568831SAndroid Build Coastguard Worker ret = 0;
4033*7c568831SAndroid Build Coastguard Worker } else if (doc->extSubset != NULL) {
4034*7c568831SAndroid Build Coastguard Worker int extId = 0;
4035*7c568831SAndroid Build Coastguard Worker elem = xmlHashLookup2(doc->extSubset->elements,
4036*7c568831SAndroid Build Coastguard Worker elemLocalName, elemPrefix);
4037*7c568831SAndroid Build Coastguard Worker if (elem != NULL) {
4038*7c568831SAndroid Build Coastguard Worker extId = xmlScanIDAttributeDecl(ctxt, elem, 0);
4039*7c568831SAndroid Build Coastguard Worker }
4040*7c568831SAndroid Build Coastguard Worker if (extId > 1) {
4041*7c568831SAndroid Build Coastguard Worker xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4042*7c568831SAndroid Build Coastguard Worker "Element %s has %d ID attribute defined in the external subset : %s\n",
4043*7c568831SAndroid Build Coastguard Worker attr->elem, extId, attr->name);
4044*7c568831SAndroid Build Coastguard Worker ret = 0;
4045*7c568831SAndroid Build Coastguard Worker } else if (extId + nbId > 1) {
4046*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4047*7c568831SAndroid Build Coastguard Worker "Element %s has ID attributes defined in the internal and external subset : %s\n",
4048*7c568831SAndroid Build Coastguard Worker attr->elem, attr->name, NULL);
4049*7c568831SAndroid Build Coastguard Worker ret = 0;
4050*7c568831SAndroid Build Coastguard Worker }
4051*7c568831SAndroid Build Coastguard Worker }
4052*7c568831SAndroid Build Coastguard Worker
4053*7c568831SAndroid Build Coastguard Worker xmlFree(elemPrefix);
4054*7c568831SAndroid Build Coastguard Worker }
4055*7c568831SAndroid Build Coastguard Worker
4056*7c568831SAndroid Build Coastguard Worker /* Validity Constraint: Enumeration */
4057*7c568831SAndroid Build Coastguard Worker if ((attr->defaultValue != NULL) && (attr->tree != NULL)) {
4058*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr tree = attr->tree;
4059*7c568831SAndroid Build Coastguard Worker while (tree != NULL) {
4060*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(tree->name, attr->defaultValue)) break;
4061*7c568831SAndroid Build Coastguard Worker tree = tree->next;
4062*7c568831SAndroid Build Coastguard Worker }
4063*7c568831SAndroid Build Coastguard Worker if (tree == NULL) {
4064*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_VALUE,
4065*7c568831SAndroid Build Coastguard Worker "Default value \"%s\" for attribute %s of %s is not among the enumerated set\n",
4066*7c568831SAndroid Build Coastguard Worker attr->defaultValue, attr->name, attr->elem);
4067*7c568831SAndroid Build Coastguard Worker ret = 0;
4068*7c568831SAndroid Build Coastguard Worker }
4069*7c568831SAndroid Build Coastguard Worker }
4070*7c568831SAndroid Build Coastguard Worker
4071*7c568831SAndroid Build Coastguard Worker return(ret);
4072*7c568831SAndroid Build Coastguard Worker }
4073*7c568831SAndroid Build Coastguard Worker
4074*7c568831SAndroid Build Coastguard Worker /**
4075*7c568831SAndroid Build Coastguard Worker * xmlValidateElementDecl:
4076*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
4077*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
4078*7c568831SAndroid Build Coastguard Worker * @elem: an element definition
4079*7c568831SAndroid Build Coastguard Worker *
4080*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
4081*7c568831SAndroid Build Coastguard Worker *
4082*7c568831SAndroid Build Coastguard Worker * Try to validate a single element definition
4083*7c568831SAndroid Build Coastguard Worker * basically it does the following checks as described by the
4084*7c568831SAndroid Build Coastguard Worker * XML-1.0 recommendation:
4085*7c568831SAndroid Build Coastguard Worker * - [ VC: One ID per Element Type ]
4086*7c568831SAndroid Build Coastguard Worker * - [ VC: No Duplicate Types ]
4087*7c568831SAndroid Build Coastguard Worker * - [ VC: Unique Element Type Declaration ]
4088*7c568831SAndroid Build Coastguard Worker *
4089*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
4090*7c568831SAndroid Build Coastguard Worker */
4091*7c568831SAndroid Build Coastguard Worker
4092*7c568831SAndroid Build Coastguard Worker int
xmlValidateElementDecl(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlElementPtr elem)4093*7c568831SAndroid Build Coastguard Worker xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4094*7c568831SAndroid Build Coastguard Worker xmlElementPtr elem) {
4095*7c568831SAndroid Build Coastguard Worker int ret = 1;
4096*7c568831SAndroid Build Coastguard Worker xmlElementPtr tst;
4097*7c568831SAndroid Build Coastguard Worker const xmlChar *localName;
4098*7c568831SAndroid Build Coastguard Worker xmlChar *prefix;
4099*7c568831SAndroid Build Coastguard Worker
4100*7c568831SAndroid Build Coastguard Worker CHECK_DTD;
4101*7c568831SAndroid Build Coastguard Worker
4102*7c568831SAndroid Build Coastguard Worker if (elem == NULL) return(1);
4103*7c568831SAndroid Build Coastguard Worker
4104*7c568831SAndroid Build Coastguard Worker /* No Duplicate Types */
4105*7c568831SAndroid Build Coastguard Worker if (elem->etype == XML_ELEMENT_TYPE_MIXED) {
4106*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr cur, next;
4107*7c568831SAndroid Build Coastguard Worker const xmlChar *name;
4108*7c568831SAndroid Build Coastguard Worker
4109*7c568831SAndroid Build Coastguard Worker cur = elem->content;
4110*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
4111*7c568831SAndroid Build Coastguard Worker if (cur->type != XML_ELEMENT_CONTENT_OR) break;
4112*7c568831SAndroid Build Coastguard Worker if (cur->c1 == NULL) break;
4113*7c568831SAndroid Build Coastguard Worker if (cur->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
4114*7c568831SAndroid Build Coastguard Worker name = cur->c1->name;
4115*7c568831SAndroid Build Coastguard Worker next = cur->c2;
4116*7c568831SAndroid Build Coastguard Worker while (next != NULL) {
4117*7c568831SAndroid Build Coastguard Worker if (next->type == XML_ELEMENT_CONTENT_ELEMENT) {
4118*7c568831SAndroid Build Coastguard Worker if ((xmlStrEqual(next->name, name)) &&
4119*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(next->prefix, cur->c1->prefix))) {
4120*7c568831SAndroid Build Coastguard Worker if (cur->c1->prefix == NULL) {
4121*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4122*7c568831SAndroid Build Coastguard Worker "Definition of %s has duplicate references of %s\n",
4123*7c568831SAndroid Build Coastguard Worker elem->name, name, NULL);
4124*7c568831SAndroid Build Coastguard Worker } else {
4125*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4126*7c568831SAndroid Build Coastguard Worker "Definition of %s has duplicate references of %s:%s\n",
4127*7c568831SAndroid Build Coastguard Worker elem->name, cur->c1->prefix, name);
4128*7c568831SAndroid Build Coastguard Worker }
4129*7c568831SAndroid Build Coastguard Worker ret = 0;
4130*7c568831SAndroid Build Coastguard Worker }
4131*7c568831SAndroid Build Coastguard Worker break;
4132*7c568831SAndroid Build Coastguard Worker }
4133*7c568831SAndroid Build Coastguard Worker if (next->c1 == NULL) break;
4134*7c568831SAndroid Build Coastguard Worker if (next->c1->type != XML_ELEMENT_CONTENT_ELEMENT) break;
4135*7c568831SAndroid Build Coastguard Worker if ((xmlStrEqual(next->c1->name, name)) &&
4136*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(next->c1->prefix, cur->c1->prefix))) {
4137*7c568831SAndroid Build Coastguard Worker if (cur->c1->prefix == NULL) {
4138*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4139*7c568831SAndroid Build Coastguard Worker "Definition of %s has duplicate references to %s\n",
4140*7c568831SAndroid Build Coastguard Worker elem->name, name, NULL);
4141*7c568831SAndroid Build Coastguard Worker } else {
4142*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4143*7c568831SAndroid Build Coastguard Worker "Definition of %s has duplicate references to %s:%s\n",
4144*7c568831SAndroid Build Coastguard Worker elem->name, cur->c1->prefix, name);
4145*7c568831SAndroid Build Coastguard Worker }
4146*7c568831SAndroid Build Coastguard Worker ret = 0;
4147*7c568831SAndroid Build Coastguard Worker }
4148*7c568831SAndroid Build Coastguard Worker next = next->c2;
4149*7c568831SAndroid Build Coastguard Worker }
4150*7c568831SAndroid Build Coastguard Worker }
4151*7c568831SAndroid Build Coastguard Worker cur = cur->c2;
4152*7c568831SAndroid Build Coastguard Worker }
4153*7c568831SAndroid Build Coastguard Worker }
4154*7c568831SAndroid Build Coastguard Worker
4155*7c568831SAndroid Build Coastguard Worker localName = xmlSplitQName4(elem->name, &prefix);
4156*7c568831SAndroid Build Coastguard Worker if (localName == NULL) {
4157*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
4158*7c568831SAndroid Build Coastguard Worker return(0);
4159*7c568831SAndroid Build Coastguard Worker }
4160*7c568831SAndroid Build Coastguard Worker
4161*7c568831SAndroid Build Coastguard Worker /* VC: Unique Element Type Declaration */
4162*7c568831SAndroid Build Coastguard Worker if (doc->intSubset != NULL) {
4163*7c568831SAndroid Build Coastguard Worker tst = xmlHashLookup2(doc->intSubset->elements, localName, prefix);
4164*7c568831SAndroid Build Coastguard Worker
4165*7c568831SAndroid Build Coastguard Worker if ((tst != NULL ) && (tst != elem) &&
4166*7c568831SAndroid Build Coastguard Worker ((tst->prefix == elem->prefix) ||
4167*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(tst->prefix, elem->prefix))) &&
4168*7c568831SAndroid Build Coastguard Worker (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
4169*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
4170*7c568831SAndroid Build Coastguard Worker "Redefinition of element %s\n",
4171*7c568831SAndroid Build Coastguard Worker elem->name, NULL, NULL);
4172*7c568831SAndroid Build Coastguard Worker ret = 0;
4173*7c568831SAndroid Build Coastguard Worker }
4174*7c568831SAndroid Build Coastguard Worker }
4175*7c568831SAndroid Build Coastguard Worker if (doc->extSubset != NULL) {
4176*7c568831SAndroid Build Coastguard Worker tst = xmlHashLookup2(doc->extSubset->elements, localName, prefix);
4177*7c568831SAndroid Build Coastguard Worker
4178*7c568831SAndroid Build Coastguard Worker if ((tst != NULL ) && (tst != elem) &&
4179*7c568831SAndroid Build Coastguard Worker ((tst->prefix == elem->prefix) ||
4180*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(tst->prefix, elem->prefix))) &&
4181*7c568831SAndroid Build Coastguard Worker (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
4182*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
4183*7c568831SAndroid Build Coastguard Worker "Redefinition of element %s\n",
4184*7c568831SAndroid Build Coastguard Worker elem->name, NULL, NULL);
4185*7c568831SAndroid Build Coastguard Worker ret = 0;
4186*7c568831SAndroid Build Coastguard Worker }
4187*7c568831SAndroid Build Coastguard Worker }
4188*7c568831SAndroid Build Coastguard Worker
4189*7c568831SAndroid Build Coastguard Worker /* One ID per Element Type
4190*7c568831SAndroid Build Coastguard Worker * already done when registering the attribute
4191*7c568831SAndroid Build Coastguard Worker if (xmlScanIDAttributeDecl(ctxt, elem) > 1) {
4192*7c568831SAndroid Build Coastguard Worker ret = 0;
4193*7c568831SAndroid Build Coastguard Worker } */
4194*7c568831SAndroid Build Coastguard Worker
4195*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
4196*7c568831SAndroid Build Coastguard Worker return(ret);
4197*7c568831SAndroid Build Coastguard Worker }
4198*7c568831SAndroid Build Coastguard Worker
4199*7c568831SAndroid Build Coastguard Worker /**
4200*7c568831SAndroid Build Coastguard Worker * xmlValidateOneAttribute:
4201*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
4202*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
4203*7c568831SAndroid Build Coastguard Worker * @elem: an element instance
4204*7c568831SAndroid Build Coastguard Worker * @attr: an attribute instance
4205*7c568831SAndroid Build Coastguard Worker * @value: the attribute value (without entities processing)
4206*7c568831SAndroid Build Coastguard Worker *
4207*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
4208*7c568831SAndroid Build Coastguard Worker *
4209*7c568831SAndroid Build Coastguard Worker * Try to validate a single attribute for an element
4210*7c568831SAndroid Build Coastguard Worker * basically it does the following checks as described by the
4211*7c568831SAndroid Build Coastguard Worker * XML-1.0 recommendation:
4212*7c568831SAndroid Build Coastguard Worker * - [ VC: Attribute Value Type ]
4213*7c568831SAndroid Build Coastguard Worker * - [ VC: Fixed Attribute Default ]
4214*7c568831SAndroid Build Coastguard Worker * - [ VC: Entity Name ]
4215*7c568831SAndroid Build Coastguard Worker * - [ VC: Name Token ]
4216*7c568831SAndroid Build Coastguard Worker * - [ VC: ID ]
4217*7c568831SAndroid Build Coastguard Worker * - [ VC: IDREF ]
4218*7c568831SAndroid Build Coastguard Worker * - [ VC: Entity Name ]
4219*7c568831SAndroid Build Coastguard Worker * - [ VC: Notation Attributes ]
4220*7c568831SAndroid Build Coastguard Worker *
4221*7c568831SAndroid Build Coastguard Worker * The ID/IDREF uniqueness and matching are done separately
4222*7c568831SAndroid Build Coastguard Worker *
4223*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
4224*7c568831SAndroid Build Coastguard Worker */
4225*7c568831SAndroid Build Coastguard Worker
4226*7c568831SAndroid Build Coastguard Worker int
xmlValidateOneAttribute(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem,xmlAttrPtr attr,const xmlChar * value)4227*7c568831SAndroid Build Coastguard Worker xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4228*7c568831SAndroid Build Coastguard Worker xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value)
4229*7c568831SAndroid Build Coastguard Worker {
4230*7c568831SAndroid Build Coastguard Worker xmlAttributePtr attrDecl = NULL;
4231*7c568831SAndroid Build Coastguard Worker const xmlChar *aprefix;
4232*7c568831SAndroid Build Coastguard Worker int val;
4233*7c568831SAndroid Build Coastguard Worker int ret = 1;
4234*7c568831SAndroid Build Coastguard Worker
4235*7c568831SAndroid Build Coastguard Worker CHECK_DTD;
4236*7c568831SAndroid Build Coastguard Worker if ((elem == NULL) || (elem->name == NULL)) return(0);
4237*7c568831SAndroid Build Coastguard Worker if ((attr == NULL) || (attr->name == NULL)) return(0);
4238*7c568831SAndroid Build Coastguard Worker
4239*7c568831SAndroid Build Coastguard Worker aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL;
4240*7c568831SAndroid Build Coastguard Worker
4241*7c568831SAndroid Build Coastguard Worker if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
4242*7c568831SAndroid Build Coastguard Worker xmlChar fn[50];
4243*7c568831SAndroid Build Coastguard Worker xmlChar *fullname;
4244*7c568831SAndroid Build Coastguard Worker
4245*7c568831SAndroid Build Coastguard Worker fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
4246*7c568831SAndroid Build Coastguard Worker if (fullname == NULL) {
4247*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
4248*7c568831SAndroid Build Coastguard Worker return(0);
4249*7c568831SAndroid Build Coastguard Worker }
4250*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
4251*7c568831SAndroid Build Coastguard Worker attr->name, aprefix);
4252*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4253*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
4254*7c568831SAndroid Build Coastguard Worker attr->name, aprefix);
4255*7c568831SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != elem->name))
4256*7c568831SAndroid Build Coastguard Worker xmlFree(fullname);
4257*7c568831SAndroid Build Coastguard Worker }
4258*7c568831SAndroid Build Coastguard Worker if (attrDecl == NULL) {
4259*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
4260*7c568831SAndroid Build Coastguard Worker attr->name, aprefix);
4261*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4262*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
4263*7c568831SAndroid Build Coastguard Worker attr->name, aprefix);
4264*7c568831SAndroid Build Coastguard Worker }
4265*7c568831SAndroid Build Coastguard Worker
4266*7c568831SAndroid Build Coastguard Worker
4267*7c568831SAndroid Build Coastguard Worker /* Validity Constraint: Attribute Value Type */
4268*7c568831SAndroid Build Coastguard Worker if (attrDecl == NULL) {
4269*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4270*7c568831SAndroid Build Coastguard Worker "No declaration for attribute %s of element %s\n",
4271*7c568831SAndroid Build Coastguard Worker attr->name, elem->name, NULL);
4272*7c568831SAndroid Build Coastguard Worker return(0);
4273*7c568831SAndroid Build Coastguard Worker }
4274*7c568831SAndroid Build Coastguard Worker if (attr->atype == XML_ATTRIBUTE_ID)
4275*7c568831SAndroid Build Coastguard Worker xmlRemoveID(doc, attr);
4276*7c568831SAndroid Build Coastguard Worker attr->atype = attrDecl->atype;
4277*7c568831SAndroid Build Coastguard Worker
4278*7c568831SAndroid Build Coastguard Worker val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
4279*7c568831SAndroid Build Coastguard Worker if (val == 0) {
4280*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4281*7c568831SAndroid Build Coastguard Worker "Syntax of value for attribute %s of %s is not valid\n",
4282*7c568831SAndroid Build Coastguard Worker attr->name, elem->name, NULL);
4283*7c568831SAndroid Build Coastguard Worker ret = 0;
4284*7c568831SAndroid Build Coastguard Worker }
4285*7c568831SAndroid Build Coastguard Worker
4286*7c568831SAndroid Build Coastguard Worker /* Validity constraint: Fixed Attribute Default */
4287*7c568831SAndroid Build Coastguard Worker if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
4288*7c568831SAndroid Build Coastguard Worker if (!xmlStrEqual(value, attrDecl->defaultValue)) {
4289*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4290*7c568831SAndroid Build Coastguard Worker "Value for attribute %s of %s is different from default \"%s\"\n",
4291*7c568831SAndroid Build Coastguard Worker attr->name, elem->name, attrDecl->defaultValue);
4292*7c568831SAndroid Build Coastguard Worker ret = 0;
4293*7c568831SAndroid Build Coastguard Worker }
4294*7c568831SAndroid Build Coastguard Worker }
4295*7c568831SAndroid Build Coastguard Worker
4296*7c568831SAndroid Build Coastguard Worker /* Validity Constraint: ID uniqueness */
4297*7c568831SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_ID) {
4298*7c568831SAndroid Build Coastguard Worker if (xmlAddID(ctxt, doc, value, attr) == NULL)
4299*7c568831SAndroid Build Coastguard Worker ret = 0;
4300*7c568831SAndroid Build Coastguard Worker }
4301*7c568831SAndroid Build Coastguard Worker
4302*7c568831SAndroid Build Coastguard Worker if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
4303*7c568831SAndroid Build Coastguard Worker (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
4304*7c568831SAndroid Build Coastguard Worker if (xmlAddRef(ctxt, doc, value, attr) == NULL)
4305*7c568831SAndroid Build Coastguard Worker ret = 0;
4306*7c568831SAndroid Build Coastguard Worker }
4307*7c568831SAndroid Build Coastguard Worker
4308*7c568831SAndroid Build Coastguard Worker /* Validity Constraint: Notation Attributes */
4309*7c568831SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
4310*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr tree = attrDecl->tree;
4311*7c568831SAndroid Build Coastguard Worker xmlNotationPtr nota;
4312*7c568831SAndroid Build Coastguard Worker
4313*7c568831SAndroid Build Coastguard Worker /* First check that the given NOTATION was declared */
4314*7c568831SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->intSubset, value);
4315*7c568831SAndroid Build Coastguard Worker if (nota == NULL)
4316*7c568831SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->extSubset, value);
4317*7c568831SAndroid Build Coastguard Worker
4318*7c568831SAndroid Build Coastguard Worker if (nota == NULL) {
4319*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4320*7c568831SAndroid Build Coastguard Worker "Value \"%s\" for attribute %s of %s is not a declared Notation\n",
4321*7c568831SAndroid Build Coastguard Worker value, attr->name, elem->name);
4322*7c568831SAndroid Build Coastguard Worker ret = 0;
4323*7c568831SAndroid Build Coastguard Worker }
4324*7c568831SAndroid Build Coastguard Worker
4325*7c568831SAndroid Build Coastguard Worker /* Second, verify that it's among the list */
4326*7c568831SAndroid Build Coastguard Worker while (tree != NULL) {
4327*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(tree->name, value)) break;
4328*7c568831SAndroid Build Coastguard Worker tree = tree->next;
4329*7c568831SAndroid Build Coastguard Worker }
4330*7c568831SAndroid Build Coastguard Worker if (tree == NULL) {
4331*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4332*7c568831SAndroid Build Coastguard Worker "Value \"%s\" for attribute %s of %s is not among the enumerated notations\n",
4333*7c568831SAndroid Build Coastguard Worker value, attr->name, elem->name);
4334*7c568831SAndroid Build Coastguard Worker ret = 0;
4335*7c568831SAndroid Build Coastguard Worker }
4336*7c568831SAndroid Build Coastguard Worker }
4337*7c568831SAndroid Build Coastguard Worker
4338*7c568831SAndroid Build Coastguard Worker /* Validity Constraint: Enumeration */
4339*7c568831SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
4340*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr tree = attrDecl->tree;
4341*7c568831SAndroid Build Coastguard Worker while (tree != NULL) {
4342*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(tree->name, value)) break;
4343*7c568831SAndroid Build Coastguard Worker tree = tree->next;
4344*7c568831SAndroid Build Coastguard Worker }
4345*7c568831SAndroid Build Coastguard Worker if (tree == NULL) {
4346*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4347*7c568831SAndroid Build Coastguard Worker "Value \"%s\" for attribute %s of %s is not among the enumerated set\n",
4348*7c568831SAndroid Build Coastguard Worker value, attr->name, elem->name);
4349*7c568831SAndroid Build Coastguard Worker ret = 0;
4350*7c568831SAndroid Build Coastguard Worker }
4351*7c568831SAndroid Build Coastguard Worker }
4352*7c568831SAndroid Build Coastguard Worker
4353*7c568831SAndroid Build Coastguard Worker /* Fixed Attribute Default */
4354*7c568831SAndroid Build Coastguard Worker if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
4355*7c568831SAndroid Build Coastguard Worker (!xmlStrEqual(attrDecl->defaultValue, value))) {
4356*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4357*7c568831SAndroid Build Coastguard Worker "Value for attribute %s of %s must be \"%s\"\n",
4358*7c568831SAndroid Build Coastguard Worker attr->name, elem->name, attrDecl->defaultValue);
4359*7c568831SAndroid Build Coastguard Worker ret = 0;
4360*7c568831SAndroid Build Coastguard Worker }
4361*7c568831SAndroid Build Coastguard Worker
4362*7c568831SAndroid Build Coastguard Worker /* Extra check for the attribute value */
4363*7c568831SAndroid Build Coastguard Worker ret &= xmlValidateAttributeValue2(ctxt, doc, attr->name,
4364*7c568831SAndroid Build Coastguard Worker attrDecl->atype, value);
4365*7c568831SAndroid Build Coastguard Worker
4366*7c568831SAndroid Build Coastguard Worker return(ret);
4367*7c568831SAndroid Build Coastguard Worker }
4368*7c568831SAndroid Build Coastguard Worker
4369*7c568831SAndroid Build Coastguard Worker /**
4370*7c568831SAndroid Build Coastguard Worker * xmlValidateOneNamespace:
4371*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
4372*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
4373*7c568831SAndroid Build Coastguard Worker * @elem: an element instance
4374*7c568831SAndroid Build Coastguard Worker * @prefix: the namespace prefix
4375*7c568831SAndroid Build Coastguard Worker * @ns: an namespace declaration instance
4376*7c568831SAndroid Build Coastguard Worker * @value: the attribute value (without entities processing)
4377*7c568831SAndroid Build Coastguard Worker *
4378*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
4379*7c568831SAndroid Build Coastguard Worker *
4380*7c568831SAndroid Build Coastguard Worker * Try to validate a single namespace declaration for an element
4381*7c568831SAndroid Build Coastguard Worker * basically it does the following checks as described by the
4382*7c568831SAndroid Build Coastguard Worker * XML-1.0 recommendation:
4383*7c568831SAndroid Build Coastguard Worker * - [ VC: Attribute Value Type ]
4384*7c568831SAndroid Build Coastguard Worker * - [ VC: Fixed Attribute Default ]
4385*7c568831SAndroid Build Coastguard Worker * - [ VC: Entity Name ]
4386*7c568831SAndroid Build Coastguard Worker * - [ VC: Name Token ]
4387*7c568831SAndroid Build Coastguard Worker * - [ VC: ID ]
4388*7c568831SAndroid Build Coastguard Worker * - [ VC: IDREF ]
4389*7c568831SAndroid Build Coastguard Worker * - [ VC: Entity Name ]
4390*7c568831SAndroid Build Coastguard Worker * - [ VC: Notation Attributes ]
4391*7c568831SAndroid Build Coastguard Worker *
4392*7c568831SAndroid Build Coastguard Worker * The ID/IDREF uniqueness and matching are done separately
4393*7c568831SAndroid Build Coastguard Worker *
4394*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
4395*7c568831SAndroid Build Coastguard Worker */
4396*7c568831SAndroid Build Coastguard Worker
4397*7c568831SAndroid Build Coastguard Worker int
xmlValidateOneNamespace(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem,const xmlChar * prefix,xmlNsPtr ns,const xmlChar * value)4398*7c568831SAndroid Build Coastguard Worker xmlValidateOneNamespace(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4399*7c568831SAndroid Build Coastguard Worker xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
4400*7c568831SAndroid Build Coastguard Worker /* xmlElementPtr elemDecl; */
4401*7c568831SAndroid Build Coastguard Worker xmlAttributePtr attrDecl = NULL;
4402*7c568831SAndroid Build Coastguard Worker int val;
4403*7c568831SAndroid Build Coastguard Worker int ret = 1;
4404*7c568831SAndroid Build Coastguard Worker
4405*7c568831SAndroid Build Coastguard Worker CHECK_DTD;
4406*7c568831SAndroid Build Coastguard Worker if ((elem == NULL) || (elem->name == NULL)) return(0);
4407*7c568831SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->href == NULL)) return(0);
4408*7c568831SAndroid Build Coastguard Worker
4409*7c568831SAndroid Build Coastguard Worker if (prefix != NULL) {
4410*7c568831SAndroid Build Coastguard Worker xmlChar fn[50];
4411*7c568831SAndroid Build Coastguard Worker xmlChar *fullname;
4412*7c568831SAndroid Build Coastguard Worker
4413*7c568831SAndroid Build Coastguard Worker fullname = xmlBuildQName(elem->name, prefix, fn, 50);
4414*7c568831SAndroid Build Coastguard Worker if (fullname == NULL) {
4415*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
4416*7c568831SAndroid Build Coastguard Worker return(0);
4417*7c568831SAndroid Build Coastguard Worker }
4418*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4419*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
4420*7c568831SAndroid Build Coastguard Worker ns->prefix, BAD_CAST "xmlns");
4421*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4422*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
4423*7c568831SAndroid Build Coastguard Worker ns->prefix, BAD_CAST "xmlns");
4424*7c568831SAndroid Build Coastguard Worker } else {
4425*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
4426*7c568831SAndroid Build Coastguard Worker BAD_CAST "xmlns", NULL);
4427*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4428*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
4429*7c568831SAndroid Build Coastguard Worker BAD_CAST "xmlns", NULL);
4430*7c568831SAndroid Build Coastguard Worker }
4431*7c568831SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != elem->name))
4432*7c568831SAndroid Build Coastguard Worker xmlFree(fullname);
4433*7c568831SAndroid Build Coastguard Worker }
4434*7c568831SAndroid Build Coastguard Worker if (attrDecl == NULL) {
4435*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4436*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
4437*7c568831SAndroid Build Coastguard Worker ns->prefix, BAD_CAST "xmlns");
4438*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4439*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
4440*7c568831SAndroid Build Coastguard Worker ns->prefix, BAD_CAST "xmlns");
4441*7c568831SAndroid Build Coastguard Worker } else {
4442*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
4443*7c568831SAndroid Build Coastguard Worker BAD_CAST "xmlns", NULL);
4444*7c568831SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4445*7c568831SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
4446*7c568831SAndroid Build Coastguard Worker BAD_CAST "xmlns", NULL);
4447*7c568831SAndroid Build Coastguard Worker }
4448*7c568831SAndroid Build Coastguard Worker }
4449*7c568831SAndroid Build Coastguard Worker
4450*7c568831SAndroid Build Coastguard Worker
4451*7c568831SAndroid Build Coastguard Worker /* Validity Constraint: Attribute Value Type */
4452*7c568831SAndroid Build Coastguard Worker if (attrDecl == NULL) {
4453*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4454*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4455*7c568831SAndroid Build Coastguard Worker "No declaration for attribute xmlns:%s of element %s\n",
4456*7c568831SAndroid Build Coastguard Worker ns->prefix, elem->name, NULL);
4457*7c568831SAndroid Build Coastguard Worker } else {
4458*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4459*7c568831SAndroid Build Coastguard Worker "No declaration for attribute xmlns of element %s\n",
4460*7c568831SAndroid Build Coastguard Worker elem->name, NULL, NULL);
4461*7c568831SAndroid Build Coastguard Worker }
4462*7c568831SAndroid Build Coastguard Worker return(0);
4463*7c568831SAndroid Build Coastguard Worker }
4464*7c568831SAndroid Build Coastguard Worker
4465*7c568831SAndroid Build Coastguard Worker val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
4466*7c568831SAndroid Build Coastguard Worker if (val == 0) {
4467*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4468*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
4469*7c568831SAndroid Build Coastguard Worker "Syntax of value for attribute xmlns:%s of %s is not valid\n",
4470*7c568831SAndroid Build Coastguard Worker ns->prefix, elem->name, NULL);
4471*7c568831SAndroid Build Coastguard Worker } else {
4472*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
4473*7c568831SAndroid Build Coastguard Worker "Syntax of value for attribute xmlns of %s is not valid\n",
4474*7c568831SAndroid Build Coastguard Worker elem->name, NULL, NULL);
4475*7c568831SAndroid Build Coastguard Worker }
4476*7c568831SAndroid Build Coastguard Worker ret = 0;
4477*7c568831SAndroid Build Coastguard Worker }
4478*7c568831SAndroid Build Coastguard Worker
4479*7c568831SAndroid Build Coastguard Worker /* Validity constraint: Fixed Attribute Default */
4480*7c568831SAndroid Build Coastguard Worker if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
4481*7c568831SAndroid Build Coastguard Worker if (!xmlStrEqual(value, attrDecl->defaultValue)) {
4482*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4483*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4484*7c568831SAndroid Build Coastguard Worker "Value for attribute xmlns:%s of %s is different from default \"%s\"\n",
4485*7c568831SAndroid Build Coastguard Worker ns->prefix, elem->name, attrDecl->defaultValue);
4486*7c568831SAndroid Build Coastguard Worker } else {
4487*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4488*7c568831SAndroid Build Coastguard Worker "Value for attribute xmlns of %s is different from default \"%s\"\n",
4489*7c568831SAndroid Build Coastguard Worker elem->name, attrDecl->defaultValue, NULL);
4490*7c568831SAndroid Build Coastguard Worker }
4491*7c568831SAndroid Build Coastguard Worker ret = 0;
4492*7c568831SAndroid Build Coastguard Worker }
4493*7c568831SAndroid Build Coastguard Worker }
4494*7c568831SAndroid Build Coastguard Worker
4495*7c568831SAndroid Build Coastguard Worker /* Validity Constraint: Notation Attributes */
4496*7c568831SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
4497*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr tree = attrDecl->tree;
4498*7c568831SAndroid Build Coastguard Worker xmlNotationPtr nota;
4499*7c568831SAndroid Build Coastguard Worker
4500*7c568831SAndroid Build Coastguard Worker /* First check that the given NOTATION was declared */
4501*7c568831SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->intSubset, value);
4502*7c568831SAndroid Build Coastguard Worker if (nota == NULL)
4503*7c568831SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->extSubset, value);
4504*7c568831SAndroid Build Coastguard Worker
4505*7c568831SAndroid Build Coastguard Worker if (nota == NULL) {
4506*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4507*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4508*7c568831SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns:%s of %s is not a declared Notation\n",
4509*7c568831SAndroid Build Coastguard Worker value, ns->prefix, elem->name);
4510*7c568831SAndroid Build Coastguard Worker } else {
4511*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4512*7c568831SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns of %s is not a declared Notation\n",
4513*7c568831SAndroid Build Coastguard Worker value, elem->name, NULL);
4514*7c568831SAndroid Build Coastguard Worker }
4515*7c568831SAndroid Build Coastguard Worker ret = 0;
4516*7c568831SAndroid Build Coastguard Worker }
4517*7c568831SAndroid Build Coastguard Worker
4518*7c568831SAndroid Build Coastguard Worker /* Second, verify that it's among the list */
4519*7c568831SAndroid Build Coastguard Worker while (tree != NULL) {
4520*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(tree->name, value)) break;
4521*7c568831SAndroid Build Coastguard Worker tree = tree->next;
4522*7c568831SAndroid Build Coastguard Worker }
4523*7c568831SAndroid Build Coastguard Worker if (tree == NULL) {
4524*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4525*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4526*7c568831SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated notations\n",
4527*7c568831SAndroid Build Coastguard Worker value, ns->prefix, elem->name);
4528*7c568831SAndroid Build Coastguard Worker } else {
4529*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4530*7c568831SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns of %s is not among the enumerated notations\n",
4531*7c568831SAndroid Build Coastguard Worker value, elem->name, NULL);
4532*7c568831SAndroid Build Coastguard Worker }
4533*7c568831SAndroid Build Coastguard Worker ret = 0;
4534*7c568831SAndroid Build Coastguard Worker }
4535*7c568831SAndroid Build Coastguard Worker }
4536*7c568831SAndroid Build Coastguard Worker
4537*7c568831SAndroid Build Coastguard Worker /* Validity Constraint: Enumeration */
4538*7c568831SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
4539*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr tree = attrDecl->tree;
4540*7c568831SAndroid Build Coastguard Worker while (tree != NULL) {
4541*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(tree->name, value)) break;
4542*7c568831SAndroid Build Coastguard Worker tree = tree->next;
4543*7c568831SAndroid Build Coastguard Worker }
4544*7c568831SAndroid Build Coastguard Worker if (tree == NULL) {
4545*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4546*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4547*7c568831SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated set\n",
4548*7c568831SAndroid Build Coastguard Worker value, ns->prefix, elem->name);
4549*7c568831SAndroid Build Coastguard Worker } else {
4550*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4551*7c568831SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns of %s is not among the enumerated set\n",
4552*7c568831SAndroid Build Coastguard Worker value, elem->name, NULL);
4553*7c568831SAndroid Build Coastguard Worker }
4554*7c568831SAndroid Build Coastguard Worker ret = 0;
4555*7c568831SAndroid Build Coastguard Worker }
4556*7c568831SAndroid Build Coastguard Worker }
4557*7c568831SAndroid Build Coastguard Worker
4558*7c568831SAndroid Build Coastguard Worker /* Fixed Attribute Default */
4559*7c568831SAndroid Build Coastguard Worker if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
4560*7c568831SAndroid Build Coastguard Worker (!xmlStrEqual(attrDecl->defaultValue, value))) {
4561*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4562*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
4563*7c568831SAndroid Build Coastguard Worker "Value for attribute xmlns:%s of %s must be \"%s\"\n",
4564*7c568831SAndroid Build Coastguard Worker ns->prefix, elem->name, attrDecl->defaultValue);
4565*7c568831SAndroid Build Coastguard Worker } else {
4566*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
4567*7c568831SAndroid Build Coastguard Worker "Value for attribute xmlns of %s must be \"%s\"\n",
4568*7c568831SAndroid Build Coastguard Worker elem->name, attrDecl->defaultValue, NULL);
4569*7c568831SAndroid Build Coastguard Worker }
4570*7c568831SAndroid Build Coastguard Worker ret = 0;
4571*7c568831SAndroid Build Coastguard Worker }
4572*7c568831SAndroid Build Coastguard Worker
4573*7c568831SAndroid Build Coastguard Worker /* Extra check for the attribute value */
4574*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4575*7c568831SAndroid Build Coastguard Worker ret &= xmlValidateAttributeValue2(ctxt, doc, ns->prefix,
4576*7c568831SAndroid Build Coastguard Worker attrDecl->atype, value);
4577*7c568831SAndroid Build Coastguard Worker } else {
4578*7c568831SAndroid Build Coastguard Worker ret &= xmlValidateAttributeValue2(ctxt, doc, BAD_CAST "xmlns",
4579*7c568831SAndroid Build Coastguard Worker attrDecl->atype, value);
4580*7c568831SAndroid Build Coastguard Worker }
4581*7c568831SAndroid Build Coastguard Worker
4582*7c568831SAndroid Build Coastguard Worker return(ret);
4583*7c568831SAndroid Build Coastguard Worker }
4584*7c568831SAndroid Build Coastguard Worker
4585*7c568831SAndroid Build Coastguard Worker #ifndef LIBXML_REGEXP_ENABLED
4586*7c568831SAndroid Build Coastguard Worker /**
4587*7c568831SAndroid Build Coastguard Worker * xmlValidateSkipIgnorable:
4588*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
4589*7c568831SAndroid Build Coastguard Worker * @child: the child list
4590*7c568831SAndroid Build Coastguard Worker *
4591*7c568831SAndroid Build Coastguard Worker * Skip ignorable elements w.r.t. the validation process
4592*7c568831SAndroid Build Coastguard Worker *
4593*7c568831SAndroid Build Coastguard Worker * returns the first element to consider for validation of the content model
4594*7c568831SAndroid Build Coastguard Worker */
4595*7c568831SAndroid Build Coastguard Worker
4596*7c568831SAndroid Build Coastguard Worker static xmlNodePtr
xmlValidateSkipIgnorable(xmlNodePtr child)4597*7c568831SAndroid Build Coastguard Worker xmlValidateSkipIgnorable(xmlNodePtr child) {
4598*7c568831SAndroid Build Coastguard Worker while (child != NULL) {
4599*7c568831SAndroid Build Coastguard Worker switch (child->type) {
4600*7c568831SAndroid Build Coastguard Worker /* These things are ignored (skipped) during validation. */
4601*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
4602*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
4603*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
4604*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
4605*7c568831SAndroid Build Coastguard Worker child = child->next;
4606*7c568831SAndroid Build Coastguard Worker break;
4607*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
4608*7c568831SAndroid Build Coastguard Worker if (xmlIsBlankNode(child))
4609*7c568831SAndroid Build Coastguard Worker child = child->next;
4610*7c568831SAndroid Build Coastguard Worker else
4611*7c568831SAndroid Build Coastguard Worker return(child);
4612*7c568831SAndroid Build Coastguard Worker break;
4613*7c568831SAndroid Build Coastguard Worker /* keep current node */
4614*7c568831SAndroid Build Coastguard Worker default:
4615*7c568831SAndroid Build Coastguard Worker return(child);
4616*7c568831SAndroid Build Coastguard Worker }
4617*7c568831SAndroid Build Coastguard Worker }
4618*7c568831SAndroid Build Coastguard Worker return(child);
4619*7c568831SAndroid Build Coastguard Worker }
4620*7c568831SAndroid Build Coastguard Worker
4621*7c568831SAndroid Build Coastguard Worker /**
4622*7c568831SAndroid Build Coastguard Worker * xmlValidateElementType:
4623*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
4624*7c568831SAndroid Build Coastguard Worker *
4625*7c568831SAndroid Build Coastguard Worker * Try to validate the content model of an element internal function
4626*7c568831SAndroid Build Coastguard Worker *
4627*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 ,-1 in case of error, -2 if an entity
4628*7c568831SAndroid Build Coastguard Worker * reference is found and -3 if the validation succeeded but
4629*7c568831SAndroid Build Coastguard Worker * the content model is not determinist.
4630*7c568831SAndroid Build Coastguard Worker */
4631*7c568831SAndroid Build Coastguard Worker
4632*7c568831SAndroid Build Coastguard Worker static int
xmlValidateElementType(xmlValidCtxtPtr ctxt)4633*7c568831SAndroid Build Coastguard Worker xmlValidateElementType(xmlValidCtxtPtr ctxt) {
4634*7c568831SAndroid Build Coastguard Worker int ret = -1;
4635*7c568831SAndroid Build Coastguard Worker int determinist = 1;
4636*7c568831SAndroid Build Coastguard Worker
4637*7c568831SAndroid Build Coastguard Worker NODE = xmlValidateSkipIgnorable(NODE);
4638*7c568831SAndroid Build Coastguard Worker if ((NODE == NULL) && (CONT == NULL))
4639*7c568831SAndroid Build Coastguard Worker return(1);
4640*7c568831SAndroid Build Coastguard Worker if ((NODE == NULL) &&
4641*7c568831SAndroid Build Coastguard Worker ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
4642*7c568831SAndroid Build Coastguard Worker (CONT->ocur == XML_ELEMENT_CONTENT_OPT))) {
4643*7c568831SAndroid Build Coastguard Worker return(1);
4644*7c568831SAndroid Build Coastguard Worker }
4645*7c568831SAndroid Build Coastguard Worker if (CONT == NULL) return(-1);
4646*7c568831SAndroid Build Coastguard Worker if ((NODE != NULL) && (NODE->type == XML_ENTITY_REF_NODE))
4647*7c568831SAndroid Build Coastguard Worker return(-2);
4648*7c568831SAndroid Build Coastguard Worker
4649*7c568831SAndroid Build Coastguard Worker /*
4650*7c568831SAndroid Build Coastguard Worker * We arrive here when more states need to be examined
4651*7c568831SAndroid Build Coastguard Worker */
4652*7c568831SAndroid Build Coastguard Worker cont:
4653*7c568831SAndroid Build Coastguard Worker
4654*7c568831SAndroid Build Coastguard Worker /*
4655*7c568831SAndroid Build Coastguard Worker * We just recovered from a rollback generated by a possible
4656*7c568831SAndroid Build Coastguard Worker * epsilon transition, go directly to the analysis phase
4657*7c568831SAndroid Build Coastguard Worker */
4658*7c568831SAndroid Build Coastguard Worker if (STATE == ROLLBACK_PARENT) {
4659*7c568831SAndroid Build Coastguard Worker ret = 1;
4660*7c568831SAndroid Build Coastguard Worker goto analyze;
4661*7c568831SAndroid Build Coastguard Worker }
4662*7c568831SAndroid Build Coastguard Worker
4663*7c568831SAndroid Build Coastguard Worker /*
4664*7c568831SAndroid Build Coastguard Worker * we may have to save a backup state here. This is the equivalent
4665*7c568831SAndroid Build Coastguard Worker * of handling epsilon transition in NFAs.
4666*7c568831SAndroid Build Coastguard Worker */
4667*7c568831SAndroid Build Coastguard Worker if ((CONT != NULL) &&
4668*7c568831SAndroid Build Coastguard Worker ((CONT->parent == NULL) ||
4669*7c568831SAndroid Build Coastguard Worker (CONT->parent == (xmlElementContentPtr) 1) ||
4670*7c568831SAndroid Build Coastguard Worker (CONT->parent->type != XML_ELEMENT_CONTENT_OR)) &&
4671*7c568831SAndroid Build Coastguard Worker ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
4672*7c568831SAndroid Build Coastguard Worker (CONT->ocur == XML_ELEMENT_CONTENT_OPT) ||
4673*7c568831SAndroid Build Coastguard Worker ((CONT->ocur == XML_ELEMENT_CONTENT_PLUS) && (OCCURRENCE)))) {
4674*7c568831SAndroid Build Coastguard Worker if (vstateVPush(ctxt, CONT, NODE, DEPTH, OCCURS, ROLLBACK_PARENT) < 0)
4675*7c568831SAndroid Build Coastguard Worker return(0);
4676*7c568831SAndroid Build Coastguard Worker }
4677*7c568831SAndroid Build Coastguard Worker
4678*7c568831SAndroid Build Coastguard Worker
4679*7c568831SAndroid Build Coastguard Worker /*
4680*7c568831SAndroid Build Coastguard Worker * Check first if the content matches
4681*7c568831SAndroid Build Coastguard Worker */
4682*7c568831SAndroid Build Coastguard Worker switch (CONT->type) {
4683*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
4684*7c568831SAndroid Build Coastguard Worker if (NODE == NULL) {
4685*7c568831SAndroid Build Coastguard Worker ret = 0;
4686*7c568831SAndroid Build Coastguard Worker break;
4687*7c568831SAndroid Build Coastguard Worker }
4688*7c568831SAndroid Build Coastguard Worker if (NODE->type == XML_TEXT_NODE) {
4689*7c568831SAndroid Build Coastguard Worker /*
4690*7c568831SAndroid Build Coastguard Worker * go to next element in the content model
4691*7c568831SAndroid Build Coastguard Worker * skipping ignorable elems
4692*7c568831SAndroid Build Coastguard Worker */
4693*7c568831SAndroid Build Coastguard Worker do {
4694*7c568831SAndroid Build Coastguard Worker NODE = NODE->next;
4695*7c568831SAndroid Build Coastguard Worker NODE = xmlValidateSkipIgnorable(NODE);
4696*7c568831SAndroid Build Coastguard Worker if ((NODE != NULL) &&
4697*7c568831SAndroid Build Coastguard Worker (NODE->type == XML_ENTITY_REF_NODE))
4698*7c568831SAndroid Build Coastguard Worker return(-2);
4699*7c568831SAndroid Build Coastguard Worker } while ((NODE != NULL) &&
4700*7c568831SAndroid Build Coastguard Worker ((NODE->type != XML_ELEMENT_NODE) &&
4701*7c568831SAndroid Build Coastguard Worker (NODE->type != XML_TEXT_NODE) &&
4702*7c568831SAndroid Build Coastguard Worker (NODE->type != XML_CDATA_SECTION_NODE)));
4703*7c568831SAndroid Build Coastguard Worker ret = 1;
4704*7c568831SAndroid Build Coastguard Worker break;
4705*7c568831SAndroid Build Coastguard Worker } else {
4706*7c568831SAndroid Build Coastguard Worker ret = 0;
4707*7c568831SAndroid Build Coastguard Worker break;
4708*7c568831SAndroid Build Coastguard Worker }
4709*7c568831SAndroid Build Coastguard Worker break;
4710*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT:
4711*7c568831SAndroid Build Coastguard Worker if (NODE == NULL) {
4712*7c568831SAndroid Build Coastguard Worker ret = 0;
4713*7c568831SAndroid Build Coastguard Worker break;
4714*7c568831SAndroid Build Coastguard Worker }
4715*7c568831SAndroid Build Coastguard Worker ret = ((NODE->type == XML_ELEMENT_NODE) &&
4716*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(NODE->name, CONT->name)));
4717*7c568831SAndroid Build Coastguard Worker if (ret == 1) {
4718*7c568831SAndroid Build Coastguard Worker if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
4719*7c568831SAndroid Build Coastguard Worker ret = (CONT->prefix == NULL);
4720*7c568831SAndroid Build Coastguard Worker } else if (CONT->prefix == NULL) {
4721*7c568831SAndroid Build Coastguard Worker ret = 0;
4722*7c568831SAndroid Build Coastguard Worker } else {
4723*7c568831SAndroid Build Coastguard Worker ret = xmlStrEqual(NODE->ns->prefix, CONT->prefix);
4724*7c568831SAndroid Build Coastguard Worker }
4725*7c568831SAndroid Build Coastguard Worker }
4726*7c568831SAndroid Build Coastguard Worker if (ret == 1) {
4727*7c568831SAndroid Build Coastguard Worker /*
4728*7c568831SAndroid Build Coastguard Worker * go to next element in the content model
4729*7c568831SAndroid Build Coastguard Worker * skipping ignorable elems
4730*7c568831SAndroid Build Coastguard Worker */
4731*7c568831SAndroid Build Coastguard Worker do {
4732*7c568831SAndroid Build Coastguard Worker NODE = NODE->next;
4733*7c568831SAndroid Build Coastguard Worker NODE = xmlValidateSkipIgnorable(NODE);
4734*7c568831SAndroid Build Coastguard Worker if ((NODE != NULL) &&
4735*7c568831SAndroid Build Coastguard Worker (NODE->type == XML_ENTITY_REF_NODE))
4736*7c568831SAndroid Build Coastguard Worker return(-2);
4737*7c568831SAndroid Build Coastguard Worker } while ((NODE != NULL) &&
4738*7c568831SAndroid Build Coastguard Worker ((NODE->type != XML_ELEMENT_NODE) &&
4739*7c568831SAndroid Build Coastguard Worker (NODE->type != XML_TEXT_NODE) &&
4740*7c568831SAndroid Build Coastguard Worker (NODE->type != XML_CDATA_SECTION_NODE)));
4741*7c568831SAndroid Build Coastguard Worker } else {
4742*7c568831SAndroid Build Coastguard Worker ret = 0;
4743*7c568831SAndroid Build Coastguard Worker break;
4744*7c568831SAndroid Build Coastguard Worker }
4745*7c568831SAndroid Build Coastguard Worker break;
4746*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
4747*7c568831SAndroid Build Coastguard Worker /*
4748*7c568831SAndroid Build Coastguard Worker * Small optimization.
4749*7c568831SAndroid Build Coastguard Worker */
4750*7c568831SAndroid Build Coastguard Worker if (CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
4751*7c568831SAndroid Build Coastguard Worker if ((NODE == NULL) ||
4752*7c568831SAndroid Build Coastguard Worker (!xmlStrEqual(NODE->name, CONT->c1->name))) {
4753*7c568831SAndroid Build Coastguard Worker DEPTH++;
4754*7c568831SAndroid Build Coastguard Worker CONT = CONT->c2;
4755*7c568831SAndroid Build Coastguard Worker goto cont;
4756*7c568831SAndroid Build Coastguard Worker }
4757*7c568831SAndroid Build Coastguard Worker if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
4758*7c568831SAndroid Build Coastguard Worker ret = (CONT->c1->prefix == NULL);
4759*7c568831SAndroid Build Coastguard Worker } else if (CONT->c1->prefix == NULL) {
4760*7c568831SAndroid Build Coastguard Worker ret = 0;
4761*7c568831SAndroid Build Coastguard Worker } else {
4762*7c568831SAndroid Build Coastguard Worker ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix);
4763*7c568831SAndroid Build Coastguard Worker }
4764*7c568831SAndroid Build Coastguard Worker if (ret == 0) {
4765*7c568831SAndroid Build Coastguard Worker DEPTH++;
4766*7c568831SAndroid Build Coastguard Worker CONT = CONT->c2;
4767*7c568831SAndroid Build Coastguard Worker goto cont;
4768*7c568831SAndroid Build Coastguard Worker }
4769*7c568831SAndroid Build Coastguard Worker }
4770*7c568831SAndroid Build Coastguard Worker
4771*7c568831SAndroid Build Coastguard Worker /*
4772*7c568831SAndroid Build Coastguard Worker * save the second branch 'or' branch
4773*7c568831SAndroid Build Coastguard Worker */
4774*7c568831SAndroid Build Coastguard Worker if (vstateVPush(ctxt, CONT->c2, NODE, DEPTH + 1,
4775*7c568831SAndroid Build Coastguard Worker OCCURS, ROLLBACK_OR) < 0)
4776*7c568831SAndroid Build Coastguard Worker return(-1);
4777*7c568831SAndroid Build Coastguard Worker DEPTH++;
4778*7c568831SAndroid Build Coastguard Worker CONT = CONT->c1;
4779*7c568831SAndroid Build Coastguard Worker goto cont;
4780*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
4781*7c568831SAndroid Build Coastguard Worker /*
4782*7c568831SAndroid Build Coastguard Worker * Small optimization.
4783*7c568831SAndroid Build Coastguard Worker */
4784*7c568831SAndroid Build Coastguard Worker if ((CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) &&
4785*7c568831SAndroid Build Coastguard Worker ((CONT->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
4786*7c568831SAndroid Build Coastguard Worker (CONT->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
4787*7c568831SAndroid Build Coastguard Worker if ((NODE == NULL) ||
4788*7c568831SAndroid Build Coastguard Worker (!xmlStrEqual(NODE->name, CONT->c1->name))) {
4789*7c568831SAndroid Build Coastguard Worker DEPTH++;
4790*7c568831SAndroid Build Coastguard Worker CONT = CONT->c2;
4791*7c568831SAndroid Build Coastguard Worker goto cont;
4792*7c568831SAndroid Build Coastguard Worker }
4793*7c568831SAndroid Build Coastguard Worker if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
4794*7c568831SAndroid Build Coastguard Worker ret = (CONT->c1->prefix == NULL);
4795*7c568831SAndroid Build Coastguard Worker } else if (CONT->c1->prefix == NULL) {
4796*7c568831SAndroid Build Coastguard Worker ret = 0;
4797*7c568831SAndroid Build Coastguard Worker } else {
4798*7c568831SAndroid Build Coastguard Worker ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix);
4799*7c568831SAndroid Build Coastguard Worker }
4800*7c568831SAndroid Build Coastguard Worker if (ret == 0) {
4801*7c568831SAndroid Build Coastguard Worker DEPTH++;
4802*7c568831SAndroid Build Coastguard Worker CONT = CONT->c2;
4803*7c568831SAndroid Build Coastguard Worker goto cont;
4804*7c568831SAndroid Build Coastguard Worker }
4805*7c568831SAndroid Build Coastguard Worker }
4806*7c568831SAndroid Build Coastguard Worker DEPTH++;
4807*7c568831SAndroid Build Coastguard Worker CONT = CONT->c1;
4808*7c568831SAndroid Build Coastguard Worker goto cont;
4809*7c568831SAndroid Build Coastguard Worker }
4810*7c568831SAndroid Build Coastguard Worker
4811*7c568831SAndroid Build Coastguard Worker /*
4812*7c568831SAndroid Build Coastguard Worker * At this point handle going up in the tree
4813*7c568831SAndroid Build Coastguard Worker */
4814*7c568831SAndroid Build Coastguard Worker if (ret == -1) {
4815*7c568831SAndroid Build Coastguard Worker return(ret);
4816*7c568831SAndroid Build Coastguard Worker }
4817*7c568831SAndroid Build Coastguard Worker analyze:
4818*7c568831SAndroid Build Coastguard Worker while (CONT != NULL) {
4819*7c568831SAndroid Build Coastguard Worker /*
4820*7c568831SAndroid Build Coastguard Worker * First do the analysis depending on the occurrence model at
4821*7c568831SAndroid Build Coastguard Worker * this level.
4822*7c568831SAndroid Build Coastguard Worker */
4823*7c568831SAndroid Build Coastguard Worker if (ret == 0) {
4824*7c568831SAndroid Build Coastguard Worker switch (CONT->ocur) {
4825*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
4826*7c568831SAndroid Build Coastguard Worker
4827*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
4828*7c568831SAndroid Build Coastguard Worker cur = ctxt->vstate->node;
4829*7c568831SAndroid Build Coastguard Worker if (vstateVPop(ctxt) < 0 ) {
4830*7c568831SAndroid Build Coastguard Worker return(0);
4831*7c568831SAndroid Build Coastguard Worker }
4832*7c568831SAndroid Build Coastguard Worker if (cur != ctxt->vstate->node)
4833*7c568831SAndroid Build Coastguard Worker determinist = -3;
4834*7c568831SAndroid Build Coastguard Worker goto cont;
4835*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
4836*7c568831SAndroid Build Coastguard Worker if (OCCURRENCE == 0) {
4837*7c568831SAndroid Build Coastguard Worker cur = ctxt->vstate->node;
4838*7c568831SAndroid Build Coastguard Worker if (vstateVPop(ctxt) < 0 ) {
4839*7c568831SAndroid Build Coastguard Worker return(0);
4840*7c568831SAndroid Build Coastguard Worker }
4841*7c568831SAndroid Build Coastguard Worker if (cur != ctxt->vstate->node)
4842*7c568831SAndroid Build Coastguard Worker determinist = -3;
4843*7c568831SAndroid Build Coastguard Worker goto cont;
4844*7c568831SAndroid Build Coastguard Worker }
4845*7c568831SAndroid Build Coastguard Worker ret = 1;
4846*7c568831SAndroid Build Coastguard Worker break;
4847*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
4848*7c568831SAndroid Build Coastguard Worker ret = 1;
4849*7c568831SAndroid Build Coastguard Worker break;
4850*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
4851*7c568831SAndroid Build Coastguard Worker ret = 1;
4852*7c568831SAndroid Build Coastguard Worker break;
4853*7c568831SAndroid Build Coastguard Worker }
4854*7c568831SAndroid Build Coastguard Worker } else {
4855*7c568831SAndroid Build Coastguard Worker switch (CONT->ocur) {
4856*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
4857*7c568831SAndroid Build Coastguard Worker ret = 1;
4858*7c568831SAndroid Build Coastguard Worker break;
4859*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
4860*7c568831SAndroid Build Coastguard Worker ret = 1;
4861*7c568831SAndroid Build Coastguard Worker break;
4862*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
4863*7c568831SAndroid Build Coastguard Worker if (STATE == ROLLBACK_PARENT) {
4864*7c568831SAndroid Build Coastguard Worker ret = 1;
4865*7c568831SAndroid Build Coastguard Worker break;
4866*7c568831SAndroid Build Coastguard Worker }
4867*7c568831SAndroid Build Coastguard Worker if (NODE == NULL) {
4868*7c568831SAndroid Build Coastguard Worker ret = 1;
4869*7c568831SAndroid Build Coastguard Worker break;
4870*7c568831SAndroid Build Coastguard Worker }
4871*7c568831SAndroid Build Coastguard Worker SET_OCCURRENCE;
4872*7c568831SAndroid Build Coastguard Worker goto cont;
4873*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
4874*7c568831SAndroid Build Coastguard Worker if (STATE == ROLLBACK_PARENT) {
4875*7c568831SAndroid Build Coastguard Worker ret = 1;
4876*7c568831SAndroid Build Coastguard Worker break;
4877*7c568831SAndroid Build Coastguard Worker }
4878*7c568831SAndroid Build Coastguard Worker if (NODE == NULL) {
4879*7c568831SAndroid Build Coastguard Worker ret = 1;
4880*7c568831SAndroid Build Coastguard Worker break;
4881*7c568831SAndroid Build Coastguard Worker }
4882*7c568831SAndroid Build Coastguard Worker /* SET_OCCURRENCE; */
4883*7c568831SAndroid Build Coastguard Worker goto cont;
4884*7c568831SAndroid Build Coastguard Worker }
4885*7c568831SAndroid Build Coastguard Worker }
4886*7c568831SAndroid Build Coastguard Worker STATE = 0;
4887*7c568831SAndroid Build Coastguard Worker
4888*7c568831SAndroid Build Coastguard Worker /*
4889*7c568831SAndroid Build Coastguard Worker * Then act accordingly at the parent level
4890*7c568831SAndroid Build Coastguard Worker */
4891*7c568831SAndroid Build Coastguard Worker RESET_OCCURRENCE;
4892*7c568831SAndroid Build Coastguard Worker if ((CONT->parent == NULL) ||
4893*7c568831SAndroid Build Coastguard Worker (CONT->parent == (xmlElementContentPtr) 1))
4894*7c568831SAndroid Build Coastguard Worker break;
4895*7c568831SAndroid Build Coastguard Worker
4896*7c568831SAndroid Build Coastguard Worker switch (CONT->parent->type) {
4897*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
4898*7c568831SAndroid Build Coastguard Worker return(-1);
4899*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT:
4900*7c568831SAndroid Build Coastguard Worker return(-1);
4901*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
4902*7c568831SAndroid Build Coastguard Worker if (ret == 1) {
4903*7c568831SAndroid Build Coastguard Worker CONT = CONT->parent;
4904*7c568831SAndroid Build Coastguard Worker DEPTH--;
4905*7c568831SAndroid Build Coastguard Worker } else {
4906*7c568831SAndroid Build Coastguard Worker CONT = CONT->parent;
4907*7c568831SAndroid Build Coastguard Worker DEPTH--;
4908*7c568831SAndroid Build Coastguard Worker }
4909*7c568831SAndroid Build Coastguard Worker break;
4910*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
4911*7c568831SAndroid Build Coastguard Worker if (ret == 0) {
4912*7c568831SAndroid Build Coastguard Worker CONT = CONT->parent;
4913*7c568831SAndroid Build Coastguard Worker DEPTH--;
4914*7c568831SAndroid Build Coastguard Worker } else if (CONT == CONT->parent->c1) {
4915*7c568831SAndroid Build Coastguard Worker CONT = CONT->parent->c2;
4916*7c568831SAndroid Build Coastguard Worker goto cont;
4917*7c568831SAndroid Build Coastguard Worker } else {
4918*7c568831SAndroid Build Coastguard Worker CONT = CONT->parent;
4919*7c568831SAndroid Build Coastguard Worker DEPTH--;
4920*7c568831SAndroid Build Coastguard Worker }
4921*7c568831SAndroid Build Coastguard Worker }
4922*7c568831SAndroid Build Coastguard Worker }
4923*7c568831SAndroid Build Coastguard Worker if (NODE != NULL) {
4924*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
4925*7c568831SAndroid Build Coastguard Worker
4926*7c568831SAndroid Build Coastguard Worker cur = ctxt->vstate->node;
4927*7c568831SAndroid Build Coastguard Worker if (vstateVPop(ctxt) < 0 ) {
4928*7c568831SAndroid Build Coastguard Worker return(0);
4929*7c568831SAndroid Build Coastguard Worker }
4930*7c568831SAndroid Build Coastguard Worker if (cur != ctxt->vstate->node)
4931*7c568831SAndroid Build Coastguard Worker determinist = -3;
4932*7c568831SAndroid Build Coastguard Worker goto cont;
4933*7c568831SAndroid Build Coastguard Worker }
4934*7c568831SAndroid Build Coastguard Worker if (ret == 0) {
4935*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
4936*7c568831SAndroid Build Coastguard Worker
4937*7c568831SAndroid Build Coastguard Worker cur = ctxt->vstate->node;
4938*7c568831SAndroid Build Coastguard Worker if (vstateVPop(ctxt) < 0 ) {
4939*7c568831SAndroid Build Coastguard Worker return(0);
4940*7c568831SAndroid Build Coastguard Worker }
4941*7c568831SAndroid Build Coastguard Worker if (cur != ctxt->vstate->node)
4942*7c568831SAndroid Build Coastguard Worker determinist = -3;
4943*7c568831SAndroid Build Coastguard Worker goto cont;
4944*7c568831SAndroid Build Coastguard Worker }
4945*7c568831SAndroid Build Coastguard Worker return(determinist);
4946*7c568831SAndroid Build Coastguard Worker }
4947*7c568831SAndroid Build Coastguard Worker #endif
4948*7c568831SAndroid Build Coastguard Worker
4949*7c568831SAndroid Build Coastguard Worker /**
4950*7c568831SAndroid Build Coastguard Worker * xmlSnprintfElements:
4951*7c568831SAndroid Build Coastguard Worker * @buf: an output buffer
4952*7c568831SAndroid Build Coastguard Worker * @size: the size of the buffer
4953*7c568831SAndroid Build Coastguard Worker * @content: An element
4954*7c568831SAndroid Build Coastguard Worker * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
4955*7c568831SAndroid Build Coastguard Worker *
4956*7c568831SAndroid Build Coastguard Worker * This will dump the list of elements to the buffer
4957*7c568831SAndroid Build Coastguard Worker * Intended just for the debug routine
4958*7c568831SAndroid Build Coastguard Worker */
4959*7c568831SAndroid Build Coastguard Worker static void
xmlSnprintfElements(char * buf,int size,xmlNodePtr node,int glob)4960*7c568831SAndroid Build Coastguard Worker xmlSnprintfElements(char *buf, int size, xmlNodePtr node, int glob) {
4961*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
4962*7c568831SAndroid Build Coastguard Worker int len;
4963*7c568831SAndroid Build Coastguard Worker
4964*7c568831SAndroid Build Coastguard Worker if (node == NULL) return;
4965*7c568831SAndroid Build Coastguard Worker if (glob) strcat(buf, "(");
4966*7c568831SAndroid Build Coastguard Worker cur = node;
4967*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
4968*7c568831SAndroid Build Coastguard Worker len = strlen(buf);
4969*7c568831SAndroid Build Coastguard Worker if (size - len < 50) {
4970*7c568831SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
4971*7c568831SAndroid Build Coastguard Worker strcat(buf, " ...");
4972*7c568831SAndroid Build Coastguard Worker return;
4973*7c568831SAndroid Build Coastguard Worker }
4974*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
4975*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
4976*7c568831SAndroid Build Coastguard Worker if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
4977*7c568831SAndroid Build Coastguard Worker if (size - len < xmlStrlen(cur->ns->prefix) + 10) {
4978*7c568831SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
4979*7c568831SAndroid Build Coastguard Worker strcat(buf, " ...");
4980*7c568831SAndroid Build Coastguard Worker return;
4981*7c568831SAndroid Build Coastguard Worker }
4982*7c568831SAndroid Build Coastguard Worker strcat(buf, (char *) cur->ns->prefix);
4983*7c568831SAndroid Build Coastguard Worker strcat(buf, ":");
4984*7c568831SAndroid Build Coastguard Worker }
4985*7c568831SAndroid Build Coastguard Worker if (size - len < xmlStrlen(cur->name) + 10) {
4986*7c568831SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
4987*7c568831SAndroid Build Coastguard Worker strcat(buf, " ...");
4988*7c568831SAndroid Build Coastguard Worker return;
4989*7c568831SAndroid Build Coastguard Worker }
4990*7c568831SAndroid Build Coastguard Worker if (cur->name != NULL)
4991*7c568831SAndroid Build Coastguard Worker strcat(buf, (char *) cur->name);
4992*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL)
4993*7c568831SAndroid Build Coastguard Worker strcat(buf, " ");
4994*7c568831SAndroid Build Coastguard Worker break;
4995*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
4996*7c568831SAndroid Build Coastguard Worker if (xmlIsBlankNode(cur))
4997*7c568831SAndroid Build Coastguard Worker break;
4998*7c568831SAndroid Build Coastguard Worker /* Falls through. */
4999*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5000*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
5001*7c568831SAndroid Build Coastguard Worker strcat(buf, "CDATA");
5002*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL)
5003*7c568831SAndroid Build Coastguard Worker strcat(buf, " ");
5004*7c568831SAndroid Build Coastguard Worker break;
5005*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
5006*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
5007*7c568831SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
5008*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
5009*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
5010*7c568831SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
5011*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
5012*7c568831SAndroid Build Coastguard Worker strcat(buf, "???");
5013*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL)
5014*7c568831SAndroid Build Coastguard Worker strcat(buf, " ");
5015*7c568831SAndroid Build Coastguard Worker break;
5016*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
5017*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
5018*7c568831SAndroid Build Coastguard Worker case XML_DTD_NODE:
5019*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
5020*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
5021*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
5022*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
5023*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
5024*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
5025*7c568831SAndroid Build Coastguard Worker break;
5026*7c568831SAndroid Build Coastguard Worker }
5027*7c568831SAndroid Build Coastguard Worker cur = cur->next;
5028*7c568831SAndroid Build Coastguard Worker }
5029*7c568831SAndroid Build Coastguard Worker if (glob) strcat(buf, ")");
5030*7c568831SAndroid Build Coastguard Worker }
5031*7c568831SAndroid Build Coastguard Worker
5032*7c568831SAndroid Build Coastguard Worker /**
5033*7c568831SAndroid Build Coastguard Worker * xmlValidateElementContent:
5034*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
5035*7c568831SAndroid Build Coastguard Worker * @child: the child list
5036*7c568831SAndroid Build Coastguard Worker * @elemDecl: pointer to the element declaration
5037*7c568831SAndroid Build Coastguard Worker * @warn: emit the error message
5038*7c568831SAndroid Build Coastguard Worker * @parent: the parent element (for error reporting)
5039*7c568831SAndroid Build Coastguard Worker *
5040*7c568831SAndroid Build Coastguard Worker * Try to validate the content model of an element
5041*7c568831SAndroid Build Coastguard Worker *
5042*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 if not and -1 in case of error
5043*7c568831SAndroid Build Coastguard Worker */
5044*7c568831SAndroid Build Coastguard Worker
5045*7c568831SAndroid Build Coastguard Worker static int
xmlValidateElementContent(xmlValidCtxtPtr ctxt,xmlNodePtr child,xmlElementPtr elemDecl,int warn,xmlNodePtr parent)5046*7c568831SAndroid Build Coastguard Worker xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
5047*7c568831SAndroid Build Coastguard Worker xmlElementPtr elemDecl, int warn, xmlNodePtr parent) {
5048*7c568831SAndroid Build Coastguard Worker int ret = 1;
5049*7c568831SAndroid Build Coastguard Worker #ifndef LIBXML_REGEXP_ENABLED
5050*7c568831SAndroid Build Coastguard Worker xmlNodePtr repl = NULL, last = NULL, tmp;
5051*7c568831SAndroid Build Coastguard Worker #endif
5052*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
5053*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr cont;
5054*7c568831SAndroid Build Coastguard Worker const xmlChar *name;
5055*7c568831SAndroid Build Coastguard Worker
5056*7c568831SAndroid Build Coastguard Worker if ((elemDecl == NULL) || (parent == NULL) || (ctxt == NULL))
5057*7c568831SAndroid Build Coastguard Worker return(-1);
5058*7c568831SAndroid Build Coastguard Worker cont = elemDecl->content;
5059*7c568831SAndroid Build Coastguard Worker name = elemDecl->name;
5060*7c568831SAndroid Build Coastguard Worker
5061*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
5062*7c568831SAndroid Build Coastguard Worker /* Build the regexp associated to the content model */
5063*7c568831SAndroid Build Coastguard Worker if (elemDecl->contModel == NULL)
5064*7c568831SAndroid Build Coastguard Worker ret = xmlValidBuildContentModel(ctxt, elemDecl);
5065*7c568831SAndroid Build Coastguard Worker if (elemDecl->contModel == NULL) {
5066*7c568831SAndroid Build Coastguard Worker return(-1);
5067*7c568831SAndroid Build Coastguard Worker } else {
5068*7c568831SAndroid Build Coastguard Worker xmlRegExecCtxtPtr exec;
5069*7c568831SAndroid Build Coastguard Worker
5070*7c568831SAndroid Build Coastguard Worker if (!xmlRegexpIsDeterminist(elemDecl->contModel)) {
5071*7c568831SAndroid Build Coastguard Worker return(-1);
5072*7c568831SAndroid Build Coastguard Worker }
5073*7c568831SAndroid Build Coastguard Worker ctxt->nodeMax = 0;
5074*7c568831SAndroid Build Coastguard Worker ctxt->nodeNr = 0;
5075*7c568831SAndroid Build Coastguard Worker ctxt->nodeTab = NULL;
5076*7c568831SAndroid Build Coastguard Worker exec = xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
5077*7c568831SAndroid Build Coastguard Worker if (exec == NULL) {
5078*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5079*7c568831SAndroid Build Coastguard Worker return(-1);
5080*7c568831SAndroid Build Coastguard Worker }
5081*7c568831SAndroid Build Coastguard Worker cur = child;
5082*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
5083*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
5084*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
5085*7c568831SAndroid Build Coastguard Worker /*
5086*7c568831SAndroid Build Coastguard Worker * Push the current node to be able to roll back
5087*7c568831SAndroid Build Coastguard Worker * and process within the entity
5088*7c568831SAndroid Build Coastguard Worker */
5089*7c568831SAndroid Build Coastguard Worker if ((cur->children != NULL) &&
5090*7c568831SAndroid Build Coastguard Worker (cur->children->children != NULL)) {
5091*7c568831SAndroid Build Coastguard Worker nodeVPush(ctxt, cur);
5092*7c568831SAndroid Build Coastguard Worker cur = cur->children->children;
5093*7c568831SAndroid Build Coastguard Worker continue;
5094*7c568831SAndroid Build Coastguard Worker }
5095*7c568831SAndroid Build Coastguard Worker break;
5096*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5097*7c568831SAndroid Build Coastguard Worker if (xmlIsBlankNode(cur))
5098*7c568831SAndroid Build Coastguard Worker break;
5099*7c568831SAndroid Build Coastguard Worker ret = 0;
5100*7c568831SAndroid Build Coastguard Worker goto fail;
5101*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5102*7c568831SAndroid Build Coastguard Worker /* TODO */
5103*7c568831SAndroid Build Coastguard Worker ret = 0;
5104*7c568831SAndroid Build Coastguard Worker goto fail;
5105*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
5106*7c568831SAndroid Build Coastguard Worker if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5107*7c568831SAndroid Build Coastguard Worker xmlChar fn[50];
5108*7c568831SAndroid Build Coastguard Worker xmlChar *fullname;
5109*7c568831SAndroid Build Coastguard Worker
5110*7c568831SAndroid Build Coastguard Worker fullname = xmlBuildQName(cur->name,
5111*7c568831SAndroid Build Coastguard Worker cur->ns->prefix, fn, 50);
5112*7c568831SAndroid Build Coastguard Worker if (fullname == NULL) {
5113*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5114*7c568831SAndroid Build Coastguard Worker ret = -1;
5115*7c568831SAndroid Build Coastguard Worker goto fail;
5116*7c568831SAndroid Build Coastguard Worker }
5117*7c568831SAndroid Build Coastguard Worker ret = xmlRegExecPushString(exec, fullname, NULL);
5118*7c568831SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != cur->name))
5119*7c568831SAndroid Build Coastguard Worker xmlFree(fullname);
5120*7c568831SAndroid Build Coastguard Worker } else {
5121*7c568831SAndroid Build Coastguard Worker ret = xmlRegExecPushString(exec, cur->name, NULL);
5122*7c568831SAndroid Build Coastguard Worker }
5123*7c568831SAndroid Build Coastguard Worker break;
5124*7c568831SAndroid Build Coastguard Worker default:
5125*7c568831SAndroid Build Coastguard Worker break;
5126*7c568831SAndroid Build Coastguard Worker }
5127*7c568831SAndroid Build Coastguard Worker if (ret == XML_REGEXP_OUT_OF_MEMORY)
5128*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5129*7c568831SAndroid Build Coastguard Worker /*
5130*7c568831SAndroid Build Coastguard Worker * Switch to next element
5131*7c568831SAndroid Build Coastguard Worker */
5132*7c568831SAndroid Build Coastguard Worker cur = cur->next;
5133*7c568831SAndroid Build Coastguard Worker while (cur == NULL) {
5134*7c568831SAndroid Build Coastguard Worker cur = nodeVPop(ctxt);
5135*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
5136*7c568831SAndroid Build Coastguard Worker break;
5137*7c568831SAndroid Build Coastguard Worker cur = cur->next;
5138*7c568831SAndroid Build Coastguard Worker }
5139*7c568831SAndroid Build Coastguard Worker }
5140*7c568831SAndroid Build Coastguard Worker ret = xmlRegExecPushString(exec, NULL, NULL);
5141*7c568831SAndroid Build Coastguard Worker if (ret == XML_REGEXP_OUT_OF_MEMORY)
5142*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5143*7c568831SAndroid Build Coastguard Worker fail:
5144*7c568831SAndroid Build Coastguard Worker xmlRegFreeExecCtxt(exec);
5145*7c568831SAndroid Build Coastguard Worker }
5146*7c568831SAndroid Build Coastguard Worker #else /* LIBXML_REGEXP_ENABLED */
5147*7c568831SAndroid Build Coastguard Worker /*
5148*7c568831SAndroid Build Coastguard Worker * Allocate the stack
5149*7c568831SAndroid Build Coastguard Worker */
5150*7c568831SAndroid Build Coastguard Worker ctxt->vstateMax = 8;
5151*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab = (xmlValidState *) xmlMalloc(
5152*7c568831SAndroid Build Coastguard Worker ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
5153*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateTab == NULL) {
5154*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5155*7c568831SAndroid Build Coastguard Worker return(-1);
5156*7c568831SAndroid Build Coastguard Worker }
5157*7c568831SAndroid Build Coastguard Worker /*
5158*7c568831SAndroid Build Coastguard Worker * The first entry in the stack is reserved to the current state
5159*7c568831SAndroid Build Coastguard Worker */
5160*7c568831SAndroid Build Coastguard Worker ctxt->nodeMax = 0;
5161*7c568831SAndroid Build Coastguard Worker ctxt->nodeNr = 0;
5162*7c568831SAndroid Build Coastguard Worker ctxt->nodeTab = NULL;
5163*7c568831SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[0];
5164*7c568831SAndroid Build Coastguard Worker ctxt->vstateNr = 1;
5165*7c568831SAndroid Build Coastguard Worker CONT = cont;
5166*7c568831SAndroid Build Coastguard Worker NODE = child;
5167*7c568831SAndroid Build Coastguard Worker DEPTH = 0;
5168*7c568831SAndroid Build Coastguard Worker OCCURS = 0;
5169*7c568831SAndroid Build Coastguard Worker STATE = 0;
5170*7c568831SAndroid Build Coastguard Worker ret = xmlValidateElementType(ctxt);
5171*7c568831SAndroid Build Coastguard Worker if ((ret == -3) && (warn)) {
5172*7c568831SAndroid Build Coastguard Worker char expr[5000];
5173*7c568831SAndroid Build Coastguard Worker expr[0] = 0;
5174*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(expr, 5000, elemDecl->content, 1);
5175*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
5176*7c568831SAndroid Build Coastguard Worker XML_DTD_CONTENT_NOT_DETERMINIST,
5177*7c568831SAndroid Build Coastguard Worker "Content model of %s is not deterministic: %s\n",
5178*7c568831SAndroid Build Coastguard Worker name, BAD_CAST expr, NULL);
5179*7c568831SAndroid Build Coastguard Worker } else if (ret == -2) {
5180*7c568831SAndroid Build Coastguard Worker /*
5181*7c568831SAndroid Build Coastguard Worker * An entities reference appeared at this level.
5182*7c568831SAndroid Build Coastguard Worker * Build a minimal representation of this node content
5183*7c568831SAndroid Build Coastguard Worker * sufficient to run the validation process on it
5184*7c568831SAndroid Build Coastguard Worker */
5185*7c568831SAndroid Build Coastguard Worker cur = child;
5186*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
5187*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
5188*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
5189*7c568831SAndroid Build Coastguard Worker /*
5190*7c568831SAndroid Build Coastguard Worker * Push the current node to be able to roll back
5191*7c568831SAndroid Build Coastguard Worker * and process within the entity
5192*7c568831SAndroid Build Coastguard Worker */
5193*7c568831SAndroid Build Coastguard Worker if ((cur->children != NULL) &&
5194*7c568831SAndroid Build Coastguard Worker (cur->children->children != NULL)) {
5195*7c568831SAndroid Build Coastguard Worker nodeVPush(ctxt, cur);
5196*7c568831SAndroid Build Coastguard Worker cur = cur->children->children;
5197*7c568831SAndroid Build Coastguard Worker continue;
5198*7c568831SAndroid Build Coastguard Worker }
5199*7c568831SAndroid Build Coastguard Worker break;
5200*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5201*7c568831SAndroid Build Coastguard Worker if (xmlIsBlankNode(cur))
5202*7c568831SAndroid Build Coastguard Worker break;
5203*7c568831SAndroid Build Coastguard Worker /* no break on purpose */
5204*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5205*7c568831SAndroid Build Coastguard Worker /* no break on purpose */
5206*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
5207*7c568831SAndroid Build Coastguard Worker /*
5208*7c568831SAndroid Build Coastguard Worker * Allocate a new node and minimally fills in
5209*7c568831SAndroid Build Coastguard Worker * what's required
5210*7c568831SAndroid Build Coastguard Worker */
5211*7c568831SAndroid Build Coastguard Worker tmp = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
5212*7c568831SAndroid Build Coastguard Worker if (tmp == NULL) {
5213*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5214*7c568831SAndroid Build Coastguard Worker xmlFreeNodeList(repl);
5215*7c568831SAndroid Build Coastguard Worker ret = -1;
5216*7c568831SAndroid Build Coastguard Worker goto done;
5217*7c568831SAndroid Build Coastguard Worker }
5218*7c568831SAndroid Build Coastguard Worker tmp->type = cur->type;
5219*7c568831SAndroid Build Coastguard Worker tmp->name = cur->name;
5220*7c568831SAndroid Build Coastguard Worker tmp->ns = cur->ns;
5221*7c568831SAndroid Build Coastguard Worker tmp->next = NULL;
5222*7c568831SAndroid Build Coastguard Worker tmp->content = NULL;
5223*7c568831SAndroid Build Coastguard Worker if (repl == NULL)
5224*7c568831SAndroid Build Coastguard Worker repl = last = tmp;
5225*7c568831SAndroid Build Coastguard Worker else {
5226*7c568831SAndroid Build Coastguard Worker last->next = tmp;
5227*7c568831SAndroid Build Coastguard Worker last = tmp;
5228*7c568831SAndroid Build Coastguard Worker }
5229*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_CDATA_SECTION_NODE) {
5230*7c568831SAndroid Build Coastguard Worker /*
5231*7c568831SAndroid Build Coastguard Worker * E59 spaces in CDATA does not match the
5232*7c568831SAndroid Build Coastguard Worker * nonterminal S
5233*7c568831SAndroid Build Coastguard Worker */
5234*7c568831SAndroid Build Coastguard Worker tmp->content = xmlStrdup(BAD_CAST "CDATA");
5235*7c568831SAndroid Build Coastguard Worker }
5236*7c568831SAndroid Build Coastguard Worker break;
5237*7c568831SAndroid Build Coastguard Worker default:
5238*7c568831SAndroid Build Coastguard Worker break;
5239*7c568831SAndroid Build Coastguard Worker }
5240*7c568831SAndroid Build Coastguard Worker /*
5241*7c568831SAndroid Build Coastguard Worker * Switch to next element
5242*7c568831SAndroid Build Coastguard Worker */
5243*7c568831SAndroid Build Coastguard Worker cur = cur->next;
5244*7c568831SAndroid Build Coastguard Worker while (cur == NULL) {
5245*7c568831SAndroid Build Coastguard Worker cur = nodeVPop(ctxt);
5246*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
5247*7c568831SAndroid Build Coastguard Worker break;
5248*7c568831SAndroid Build Coastguard Worker cur = cur->next;
5249*7c568831SAndroid Build Coastguard Worker }
5250*7c568831SAndroid Build Coastguard Worker }
5251*7c568831SAndroid Build Coastguard Worker
5252*7c568831SAndroid Build Coastguard Worker /*
5253*7c568831SAndroid Build Coastguard Worker * Relaunch the validation
5254*7c568831SAndroid Build Coastguard Worker */
5255*7c568831SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[0];
5256*7c568831SAndroid Build Coastguard Worker ctxt->vstateNr = 1;
5257*7c568831SAndroid Build Coastguard Worker CONT = cont;
5258*7c568831SAndroid Build Coastguard Worker NODE = repl;
5259*7c568831SAndroid Build Coastguard Worker DEPTH = 0;
5260*7c568831SAndroid Build Coastguard Worker OCCURS = 0;
5261*7c568831SAndroid Build Coastguard Worker STATE = 0;
5262*7c568831SAndroid Build Coastguard Worker ret = xmlValidateElementType(ctxt);
5263*7c568831SAndroid Build Coastguard Worker }
5264*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
5265*7c568831SAndroid Build Coastguard Worker if ((warn) && ((ret != 1) && (ret != -3))) {
5266*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL) {
5267*7c568831SAndroid Build Coastguard Worker char expr[5000];
5268*7c568831SAndroid Build Coastguard Worker char list[5000];
5269*7c568831SAndroid Build Coastguard Worker
5270*7c568831SAndroid Build Coastguard Worker expr[0] = 0;
5271*7c568831SAndroid Build Coastguard Worker xmlSnprintfElementContent(&expr[0], 5000, cont, 1);
5272*7c568831SAndroid Build Coastguard Worker list[0] = 0;
5273*7c568831SAndroid Build Coastguard Worker #ifndef LIBXML_REGEXP_ENABLED
5274*7c568831SAndroid Build Coastguard Worker if (repl != NULL)
5275*7c568831SAndroid Build Coastguard Worker xmlSnprintfElements(&list[0], 5000, repl, 1);
5276*7c568831SAndroid Build Coastguard Worker else
5277*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
5278*7c568831SAndroid Build Coastguard Worker xmlSnprintfElements(&list[0], 5000, child, 1);
5279*7c568831SAndroid Build Coastguard Worker
5280*7c568831SAndroid Build Coastguard Worker if (name != NULL) {
5281*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5282*7c568831SAndroid Build Coastguard Worker "Element %s content does not follow the DTD, expecting %s, got %s\n",
5283*7c568831SAndroid Build Coastguard Worker name, BAD_CAST expr, BAD_CAST list);
5284*7c568831SAndroid Build Coastguard Worker } else {
5285*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5286*7c568831SAndroid Build Coastguard Worker "Element content does not follow the DTD, expecting %s, got %s\n",
5287*7c568831SAndroid Build Coastguard Worker BAD_CAST expr, BAD_CAST list, NULL);
5288*7c568831SAndroid Build Coastguard Worker }
5289*7c568831SAndroid Build Coastguard Worker } else {
5290*7c568831SAndroid Build Coastguard Worker if (name != NULL) {
5291*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5292*7c568831SAndroid Build Coastguard Worker "Element %s content does not follow the DTD\n",
5293*7c568831SAndroid Build Coastguard Worker name, NULL, NULL);
5294*7c568831SAndroid Build Coastguard Worker } else {
5295*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5296*7c568831SAndroid Build Coastguard Worker "Element content does not follow the DTD\n",
5297*7c568831SAndroid Build Coastguard Worker NULL, NULL, NULL);
5298*7c568831SAndroid Build Coastguard Worker }
5299*7c568831SAndroid Build Coastguard Worker }
5300*7c568831SAndroid Build Coastguard Worker ret = 0;
5301*7c568831SAndroid Build Coastguard Worker }
5302*7c568831SAndroid Build Coastguard Worker if (ret == -3)
5303*7c568831SAndroid Build Coastguard Worker ret = 1;
5304*7c568831SAndroid Build Coastguard Worker
5305*7c568831SAndroid Build Coastguard Worker #ifndef LIBXML_REGEXP_ENABLED
5306*7c568831SAndroid Build Coastguard Worker done:
5307*7c568831SAndroid Build Coastguard Worker /*
5308*7c568831SAndroid Build Coastguard Worker * Deallocate the copy if done, and free up the validation stack
5309*7c568831SAndroid Build Coastguard Worker */
5310*7c568831SAndroid Build Coastguard Worker while (repl != NULL) {
5311*7c568831SAndroid Build Coastguard Worker tmp = repl->next;
5312*7c568831SAndroid Build Coastguard Worker xmlFree(repl);
5313*7c568831SAndroid Build Coastguard Worker repl = tmp;
5314*7c568831SAndroid Build Coastguard Worker }
5315*7c568831SAndroid Build Coastguard Worker ctxt->vstateMax = 0;
5316*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateTab != NULL) {
5317*7c568831SAndroid Build Coastguard Worker xmlFree(ctxt->vstateTab);
5318*7c568831SAndroid Build Coastguard Worker ctxt->vstateTab = NULL;
5319*7c568831SAndroid Build Coastguard Worker }
5320*7c568831SAndroid Build Coastguard Worker #endif
5321*7c568831SAndroid Build Coastguard Worker ctxt->nodeMax = 0;
5322*7c568831SAndroid Build Coastguard Worker ctxt->nodeNr = 0;
5323*7c568831SAndroid Build Coastguard Worker if (ctxt->nodeTab != NULL) {
5324*7c568831SAndroid Build Coastguard Worker xmlFree(ctxt->nodeTab);
5325*7c568831SAndroid Build Coastguard Worker ctxt->nodeTab = NULL;
5326*7c568831SAndroid Build Coastguard Worker }
5327*7c568831SAndroid Build Coastguard Worker return(ret);
5328*7c568831SAndroid Build Coastguard Worker
5329*7c568831SAndroid Build Coastguard Worker }
5330*7c568831SAndroid Build Coastguard Worker
5331*7c568831SAndroid Build Coastguard Worker /**
5332*7c568831SAndroid Build Coastguard Worker * xmlValidateCdataElement:
5333*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
5334*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
5335*7c568831SAndroid Build Coastguard Worker * @elem: an element instance
5336*7c568831SAndroid Build Coastguard Worker *
5337*7c568831SAndroid Build Coastguard Worker * Check that an element follows #CDATA
5338*7c568831SAndroid Build Coastguard Worker *
5339*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
5340*7c568831SAndroid Build Coastguard Worker */
5341*7c568831SAndroid Build Coastguard Worker static int
xmlValidateOneCdataElement(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem)5342*7c568831SAndroid Build Coastguard Worker xmlValidateOneCdataElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5343*7c568831SAndroid Build Coastguard Worker xmlNodePtr elem) {
5344*7c568831SAndroid Build Coastguard Worker int ret = 1;
5345*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur, child;
5346*7c568831SAndroid Build Coastguard Worker
5347*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (doc == NULL) || (elem == NULL) ||
5348*7c568831SAndroid Build Coastguard Worker (elem->type != XML_ELEMENT_NODE))
5349*7c568831SAndroid Build Coastguard Worker return(0);
5350*7c568831SAndroid Build Coastguard Worker
5351*7c568831SAndroid Build Coastguard Worker child = elem->children;
5352*7c568831SAndroid Build Coastguard Worker
5353*7c568831SAndroid Build Coastguard Worker cur = child;
5354*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
5355*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
5356*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
5357*7c568831SAndroid Build Coastguard Worker /*
5358*7c568831SAndroid Build Coastguard Worker * Push the current node to be able to roll back
5359*7c568831SAndroid Build Coastguard Worker * and process within the entity
5360*7c568831SAndroid Build Coastguard Worker */
5361*7c568831SAndroid Build Coastguard Worker if ((cur->children != NULL) &&
5362*7c568831SAndroid Build Coastguard Worker (cur->children->children != NULL)) {
5363*7c568831SAndroid Build Coastguard Worker nodeVPush(ctxt, cur);
5364*7c568831SAndroid Build Coastguard Worker cur = cur->children->children;
5365*7c568831SAndroid Build Coastguard Worker continue;
5366*7c568831SAndroid Build Coastguard Worker }
5367*7c568831SAndroid Build Coastguard Worker break;
5368*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
5369*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
5370*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5371*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5372*7c568831SAndroid Build Coastguard Worker break;
5373*7c568831SAndroid Build Coastguard Worker default:
5374*7c568831SAndroid Build Coastguard Worker ret = 0;
5375*7c568831SAndroid Build Coastguard Worker goto done;
5376*7c568831SAndroid Build Coastguard Worker }
5377*7c568831SAndroid Build Coastguard Worker /*
5378*7c568831SAndroid Build Coastguard Worker * Switch to next element
5379*7c568831SAndroid Build Coastguard Worker */
5380*7c568831SAndroid Build Coastguard Worker cur = cur->next;
5381*7c568831SAndroid Build Coastguard Worker while (cur == NULL) {
5382*7c568831SAndroid Build Coastguard Worker cur = nodeVPop(ctxt);
5383*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
5384*7c568831SAndroid Build Coastguard Worker break;
5385*7c568831SAndroid Build Coastguard Worker cur = cur->next;
5386*7c568831SAndroid Build Coastguard Worker }
5387*7c568831SAndroid Build Coastguard Worker }
5388*7c568831SAndroid Build Coastguard Worker done:
5389*7c568831SAndroid Build Coastguard Worker ctxt->nodeMax = 0;
5390*7c568831SAndroid Build Coastguard Worker ctxt->nodeNr = 0;
5391*7c568831SAndroid Build Coastguard Worker if (ctxt->nodeTab != NULL) {
5392*7c568831SAndroid Build Coastguard Worker xmlFree(ctxt->nodeTab);
5393*7c568831SAndroid Build Coastguard Worker ctxt->nodeTab = NULL;
5394*7c568831SAndroid Build Coastguard Worker }
5395*7c568831SAndroid Build Coastguard Worker return(ret);
5396*7c568831SAndroid Build Coastguard Worker }
5397*7c568831SAndroid Build Coastguard Worker
5398*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
5399*7c568831SAndroid Build Coastguard Worker /**
5400*7c568831SAndroid Build Coastguard Worker * xmlValidateCheckMixed:
5401*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
5402*7c568831SAndroid Build Coastguard Worker * @cont: the mixed content model
5403*7c568831SAndroid Build Coastguard Worker * @qname: the qualified name as appearing in the serialization
5404*7c568831SAndroid Build Coastguard Worker *
5405*7c568831SAndroid Build Coastguard Worker * Check if the given node is part of the content model.
5406*7c568831SAndroid Build Coastguard Worker *
5407*7c568831SAndroid Build Coastguard Worker * Returns 1 if yes, 0 if no, -1 in case of error
5408*7c568831SAndroid Build Coastguard Worker */
5409*7c568831SAndroid Build Coastguard Worker static int
xmlValidateCheckMixed(xmlValidCtxtPtr ctxt,xmlElementContentPtr cont,const xmlChar * qname)5410*7c568831SAndroid Build Coastguard Worker xmlValidateCheckMixed(xmlValidCtxtPtr ctxt,
5411*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr cont, const xmlChar *qname) {
5412*7c568831SAndroid Build Coastguard Worker const xmlChar *name;
5413*7c568831SAndroid Build Coastguard Worker int plen;
5414*7c568831SAndroid Build Coastguard Worker name = xmlSplitQName3(qname, &plen);
5415*7c568831SAndroid Build Coastguard Worker
5416*7c568831SAndroid Build Coastguard Worker if (name == NULL) {
5417*7c568831SAndroid Build Coastguard Worker while (cont != NULL) {
5418*7c568831SAndroid Build Coastguard Worker if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5419*7c568831SAndroid Build Coastguard Worker if ((cont->prefix == NULL) && (xmlStrEqual(cont->name, qname)))
5420*7c568831SAndroid Build Coastguard Worker return(1);
5421*7c568831SAndroid Build Coastguard Worker } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5422*7c568831SAndroid Build Coastguard Worker (cont->c1 != NULL) &&
5423*7c568831SAndroid Build Coastguard Worker (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5424*7c568831SAndroid Build Coastguard Worker if ((cont->c1->prefix == NULL) &&
5425*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(cont->c1->name, qname)))
5426*7c568831SAndroid Build Coastguard Worker return(1);
5427*7c568831SAndroid Build Coastguard Worker } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5428*7c568831SAndroid Build Coastguard Worker (cont->c1 == NULL) ||
5429*7c568831SAndroid Build Coastguard Worker (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5430*7c568831SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT,
5431*7c568831SAndroid Build Coastguard Worker "Internal: MIXED struct corrupted\n",
5432*7c568831SAndroid Build Coastguard Worker NULL);
5433*7c568831SAndroid Build Coastguard Worker break;
5434*7c568831SAndroid Build Coastguard Worker }
5435*7c568831SAndroid Build Coastguard Worker cont = cont->c2;
5436*7c568831SAndroid Build Coastguard Worker }
5437*7c568831SAndroid Build Coastguard Worker } else {
5438*7c568831SAndroid Build Coastguard Worker while (cont != NULL) {
5439*7c568831SAndroid Build Coastguard Worker if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5440*7c568831SAndroid Build Coastguard Worker if ((cont->prefix != NULL) &&
5441*7c568831SAndroid Build Coastguard Worker (xmlStrncmp(cont->prefix, qname, plen) == 0) &&
5442*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(cont->name, name)))
5443*7c568831SAndroid Build Coastguard Worker return(1);
5444*7c568831SAndroid Build Coastguard Worker } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5445*7c568831SAndroid Build Coastguard Worker (cont->c1 != NULL) &&
5446*7c568831SAndroid Build Coastguard Worker (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5447*7c568831SAndroid Build Coastguard Worker if ((cont->c1->prefix != NULL) &&
5448*7c568831SAndroid Build Coastguard Worker (xmlStrncmp(cont->c1->prefix, qname, plen) == 0) &&
5449*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(cont->c1->name, name)))
5450*7c568831SAndroid Build Coastguard Worker return(1);
5451*7c568831SAndroid Build Coastguard Worker } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5452*7c568831SAndroid Build Coastguard Worker (cont->c1 == NULL) ||
5453*7c568831SAndroid Build Coastguard Worker (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5454*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT,
5455*7c568831SAndroid Build Coastguard Worker "Internal: MIXED struct corrupted\n",
5456*7c568831SAndroid Build Coastguard Worker NULL);
5457*7c568831SAndroid Build Coastguard Worker break;
5458*7c568831SAndroid Build Coastguard Worker }
5459*7c568831SAndroid Build Coastguard Worker cont = cont->c2;
5460*7c568831SAndroid Build Coastguard Worker }
5461*7c568831SAndroid Build Coastguard Worker }
5462*7c568831SAndroid Build Coastguard Worker return(0);
5463*7c568831SAndroid Build Coastguard Worker }
5464*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
5465*7c568831SAndroid Build Coastguard Worker
5466*7c568831SAndroid Build Coastguard Worker /**
5467*7c568831SAndroid Build Coastguard Worker * xmlValidGetElemDecl:
5468*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
5469*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
5470*7c568831SAndroid Build Coastguard Worker * @elem: an element instance
5471*7c568831SAndroid Build Coastguard Worker * @extsubset: pointer, (out) indicate if the declaration was found
5472*7c568831SAndroid Build Coastguard Worker * in the external subset.
5473*7c568831SAndroid Build Coastguard Worker *
5474*7c568831SAndroid Build Coastguard Worker * Finds a declaration associated to an element in the document.
5475*7c568831SAndroid Build Coastguard Worker *
5476*7c568831SAndroid Build Coastguard Worker * returns the pointer to the declaration or NULL if not found.
5477*7c568831SAndroid Build Coastguard Worker */
5478*7c568831SAndroid Build Coastguard Worker static xmlElementPtr
xmlValidGetElemDecl(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem,int * extsubset)5479*7c568831SAndroid Build Coastguard Worker xmlValidGetElemDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5480*7c568831SAndroid Build Coastguard Worker xmlNodePtr elem, int *extsubset) {
5481*7c568831SAndroid Build Coastguard Worker xmlElementPtr elemDecl = NULL;
5482*7c568831SAndroid Build Coastguard Worker const xmlChar *prefix = NULL;
5483*7c568831SAndroid Build Coastguard Worker
5484*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (doc == NULL) ||
5485*7c568831SAndroid Build Coastguard Worker (elem == NULL) || (elem->name == NULL))
5486*7c568831SAndroid Build Coastguard Worker return(NULL);
5487*7c568831SAndroid Build Coastguard Worker if (extsubset != NULL)
5488*7c568831SAndroid Build Coastguard Worker *extsubset = 0;
5489*7c568831SAndroid Build Coastguard Worker
5490*7c568831SAndroid Build Coastguard Worker /*
5491*7c568831SAndroid Build Coastguard Worker * Fetch the declaration for the qualified name
5492*7c568831SAndroid Build Coastguard Worker */
5493*7c568831SAndroid Build Coastguard Worker if ((elem->ns != NULL) && (elem->ns->prefix != NULL))
5494*7c568831SAndroid Build Coastguard Worker prefix = elem->ns->prefix;
5495*7c568831SAndroid Build Coastguard Worker
5496*7c568831SAndroid Build Coastguard Worker if (prefix != NULL) {
5497*7c568831SAndroid Build Coastguard Worker elemDecl = xmlGetDtdQElementDesc(doc->intSubset,
5498*7c568831SAndroid Build Coastguard Worker elem->name, prefix);
5499*7c568831SAndroid Build Coastguard Worker if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
5500*7c568831SAndroid Build Coastguard Worker elemDecl = xmlGetDtdQElementDesc(doc->extSubset,
5501*7c568831SAndroid Build Coastguard Worker elem->name, prefix);
5502*7c568831SAndroid Build Coastguard Worker if ((elemDecl != NULL) && (extsubset != NULL))
5503*7c568831SAndroid Build Coastguard Worker *extsubset = 1;
5504*7c568831SAndroid Build Coastguard Worker }
5505*7c568831SAndroid Build Coastguard Worker }
5506*7c568831SAndroid Build Coastguard Worker
5507*7c568831SAndroid Build Coastguard Worker /*
5508*7c568831SAndroid Build Coastguard Worker * Fetch the declaration for the non qualified name
5509*7c568831SAndroid Build Coastguard Worker * This is "non-strict" validation should be done on the
5510*7c568831SAndroid Build Coastguard Worker * full QName but in that case being flexible makes sense.
5511*7c568831SAndroid Build Coastguard Worker */
5512*7c568831SAndroid Build Coastguard Worker if (elemDecl == NULL) {
5513*7c568831SAndroid Build Coastguard Worker elemDecl = xmlGetDtdQElementDesc(doc->intSubset, elem->name, NULL);
5514*7c568831SAndroid Build Coastguard Worker if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
5515*7c568831SAndroid Build Coastguard Worker elemDecl = xmlGetDtdQElementDesc(doc->extSubset, elem->name, NULL);
5516*7c568831SAndroid Build Coastguard Worker if ((elemDecl != NULL) && (extsubset != NULL))
5517*7c568831SAndroid Build Coastguard Worker *extsubset = 1;
5518*7c568831SAndroid Build Coastguard Worker }
5519*7c568831SAndroid Build Coastguard Worker }
5520*7c568831SAndroid Build Coastguard Worker if (elemDecl == NULL) {
5521*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem,
5522*7c568831SAndroid Build Coastguard Worker XML_DTD_UNKNOWN_ELEM,
5523*7c568831SAndroid Build Coastguard Worker "No declaration for element %s\n",
5524*7c568831SAndroid Build Coastguard Worker elem->name, NULL, NULL);
5525*7c568831SAndroid Build Coastguard Worker }
5526*7c568831SAndroid Build Coastguard Worker return(elemDecl);
5527*7c568831SAndroid Build Coastguard Worker }
5528*7c568831SAndroid Build Coastguard Worker
5529*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
5530*7c568831SAndroid Build Coastguard Worker /**
5531*7c568831SAndroid Build Coastguard Worker * xmlValidatePushElement:
5532*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
5533*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
5534*7c568831SAndroid Build Coastguard Worker * @elem: an element instance
5535*7c568831SAndroid Build Coastguard Worker * @qname: the qualified name as appearing in the serialization
5536*7c568831SAndroid Build Coastguard Worker *
5537*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
5538*7c568831SAndroid Build Coastguard Worker *
5539*7c568831SAndroid Build Coastguard Worker * Push a new element start on the validation stack.
5540*7c568831SAndroid Build Coastguard Worker *
5541*7c568831SAndroid Build Coastguard Worker * returns 1 if no validation problem was found or 0 otherwise
5542*7c568831SAndroid Build Coastguard Worker */
5543*7c568831SAndroid Build Coastguard Worker int
xmlValidatePushElement(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem,const xmlChar * qname)5544*7c568831SAndroid Build Coastguard Worker xmlValidatePushElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5545*7c568831SAndroid Build Coastguard Worker xmlNodePtr elem, const xmlChar *qname) {
5546*7c568831SAndroid Build Coastguard Worker int ret = 1;
5547*7c568831SAndroid Build Coastguard Worker xmlElementPtr eDecl;
5548*7c568831SAndroid Build Coastguard Worker int extsubset = 0;
5549*7c568831SAndroid Build Coastguard Worker
5550*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
5551*7c568831SAndroid Build Coastguard Worker return(0);
5552*7c568831SAndroid Build Coastguard Worker
5553*7c568831SAndroid Build Coastguard Worker if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5554*7c568831SAndroid Build Coastguard Worker xmlValidStatePtr state = ctxt->vstate;
5555*7c568831SAndroid Build Coastguard Worker xmlElementPtr elemDecl;
5556*7c568831SAndroid Build Coastguard Worker
5557*7c568831SAndroid Build Coastguard Worker /*
5558*7c568831SAndroid Build Coastguard Worker * Check the new element against the content model of the new elem.
5559*7c568831SAndroid Build Coastguard Worker */
5560*7c568831SAndroid Build Coastguard Worker if (state->elemDecl != NULL) {
5561*7c568831SAndroid Build Coastguard Worker elemDecl = state->elemDecl;
5562*7c568831SAndroid Build Coastguard Worker
5563*7c568831SAndroid Build Coastguard Worker switch(elemDecl->etype) {
5564*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_UNDEFINED:
5565*7c568831SAndroid Build Coastguard Worker ret = 0;
5566*7c568831SAndroid Build Coastguard Worker break;
5567*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_EMPTY:
5568*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5569*7c568831SAndroid Build Coastguard Worker XML_DTD_NOT_EMPTY,
5570*7c568831SAndroid Build Coastguard Worker "Element %s was declared EMPTY this one has content\n",
5571*7c568831SAndroid Build Coastguard Worker state->node->name, NULL, NULL);
5572*7c568831SAndroid Build Coastguard Worker ret = 0;
5573*7c568831SAndroid Build Coastguard Worker break;
5574*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ANY:
5575*7c568831SAndroid Build Coastguard Worker /* I don't think anything is required then */
5576*7c568831SAndroid Build Coastguard Worker break;
5577*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_MIXED:
5578*7c568831SAndroid Build Coastguard Worker /* simple case of declared as #PCDATA */
5579*7c568831SAndroid Build Coastguard Worker if ((elemDecl->content != NULL) &&
5580*7c568831SAndroid Build Coastguard Worker (elemDecl->content->type ==
5581*7c568831SAndroid Build Coastguard Worker XML_ELEMENT_CONTENT_PCDATA)) {
5582*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5583*7c568831SAndroid Build Coastguard Worker XML_DTD_NOT_PCDATA,
5584*7c568831SAndroid Build Coastguard Worker "Element %s was declared #PCDATA but contains non text nodes\n",
5585*7c568831SAndroid Build Coastguard Worker state->node->name, NULL, NULL);
5586*7c568831SAndroid Build Coastguard Worker ret = 0;
5587*7c568831SAndroid Build Coastguard Worker } else {
5588*7c568831SAndroid Build Coastguard Worker ret = xmlValidateCheckMixed(ctxt, elemDecl->content,
5589*7c568831SAndroid Build Coastguard Worker qname);
5590*7c568831SAndroid Build Coastguard Worker if (ret != 1) {
5591*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5592*7c568831SAndroid Build Coastguard Worker XML_DTD_INVALID_CHILD,
5593*7c568831SAndroid Build Coastguard Worker "Element %s is not declared in %s list of possible children\n",
5594*7c568831SAndroid Build Coastguard Worker qname, state->node->name, NULL);
5595*7c568831SAndroid Build Coastguard Worker }
5596*7c568831SAndroid Build Coastguard Worker }
5597*7c568831SAndroid Build Coastguard Worker break;
5598*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ELEMENT:
5599*7c568831SAndroid Build Coastguard Worker /*
5600*7c568831SAndroid Build Coastguard Worker * TODO:
5601*7c568831SAndroid Build Coastguard Worker * VC: Standalone Document Declaration
5602*7c568831SAndroid Build Coastguard Worker * - element types with element content, if white space
5603*7c568831SAndroid Build Coastguard Worker * occurs directly within any instance of those types.
5604*7c568831SAndroid Build Coastguard Worker */
5605*7c568831SAndroid Build Coastguard Worker if (state->exec != NULL) {
5606*7c568831SAndroid Build Coastguard Worker ret = xmlRegExecPushString(state->exec, qname, NULL);
5607*7c568831SAndroid Build Coastguard Worker if (ret == XML_REGEXP_OUT_OF_MEMORY) {
5608*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5609*7c568831SAndroid Build Coastguard Worker return(0);
5610*7c568831SAndroid Build Coastguard Worker }
5611*7c568831SAndroid Build Coastguard Worker if (ret < 0) {
5612*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5613*7c568831SAndroid Build Coastguard Worker XML_DTD_CONTENT_MODEL,
5614*7c568831SAndroid Build Coastguard Worker "Element %s content does not follow the DTD, Misplaced %s\n",
5615*7c568831SAndroid Build Coastguard Worker state->node->name, qname, NULL);
5616*7c568831SAndroid Build Coastguard Worker ret = 0;
5617*7c568831SAndroid Build Coastguard Worker } else {
5618*7c568831SAndroid Build Coastguard Worker ret = 1;
5619*7c568831SAndroid Build Coastguard Worker }
5620*7c568831SAndroid Build Coastguard Worker }
5621*7c568831SAndroid Build Coastguard Worker break;
5622*7c568831SAndroid Build Coastguard Worker }
5623*7c568831SAndroid Build Coastguard Worker }
5624*7c568831SAndroid Build Coastguard Worker }
5625*7c568831SAndroid Build Coastguard Worker eDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset);
5626*7c568831SAndroid Build Coastguard Worker vstateVPush(ctxt, eDecl, elem);
5627*7c568831SAndroid Build Coastguard Worker return(ret);
5628*7c568831SAndroid Build Coastguard Worker }
5629*7c568831SAndroid Build Coastguard Worker
5630*7c568831SAndroid Build Coastguard Worker /**
5631*7c568831SAndroid Build Coastguard Worker * xmlValidatePushCData:
5632*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
5633*7c568831SAndroid Build Coastguard Worker * @data: some character data read
5634*7c568831SAndroid Build Coastguard Worker * @len: the length of the data
5635*7c568831SAndroid Build Coastguard Worker *
5636*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
5637*7c568831SAndroid Build Coastguard Worker *
5638*7c568831SAndroid Build Coastguard Worker * check the CData parsed for validation in the current stack
5639*7c568831SAndroid Build Coastguard Worker *
5640*7c568831SAndroid Build Coastguard Worker * returns 1 if no validation problem was found or 0 otherwise
5641*7c568831SAndroid Build Coastguard Worker */
5642*7c568831SAndroid Build Coastguard Worker int
xmlValidatePushCData(xmlValidCtxtPtr ctxt,const xmlChar * data,int len)5643*7c568831SAndroid Build Coastguard Worker xmlValidatePushCData(xmlValidCtxtPtr ctxt, const xmlChar *data, int len) {
5644*7c568831SAndroid Build Coastguard Worker int ret = 1;
5645*7c568831SAndroid Build Coastguard Worker
5646*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
5647*7c568831SAndroid Build Coastguard Worker return(0);
5648*7c568831SAndroid Build Coastguard Worker if (len <= 0)
5649*7c568831SAndroid Build Coastguard Worker return(ret);
5650*7c568831SAndroid Build Coastguard Worker if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5651*7c568831SAndroid Build Coastguard Worker xmlValidStatePtr state = ctxt->vstate;
5652*7c568831SAndroid Build Coastguard Worker xmlElementPtr elemDecl;
5653*7c568831SAndroid Build Coastguard Worker
5654*7c568831SAndroid Build Coastguard Worker /*
5655*7c568831SAndroid Build Coastguard Worker * Check the new element against the content model of the new elem.
5656*7c568831SAndroid Build Coastguard Worker */
5657*7c568831SAndroid Build Coastguard Worker if (state->elemDecl != NULL) {
5658*7c568831SAndroid Build Coastguard Worker elemDecl = state->elemDecl;
5659*7c568831SAndroid Build Coastguard Worker
5660*7c568831SAndroid Build Coastguard Worker switch(elemDecl->etype) {
5661*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_UNDEFINED:
5662*7c568831SAndroid Build Coastguard Worker ret = 0;
5663*7c568831SAndroid Build Coastguard Worker break;
5664*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_EMPTY:
5665*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5666*7c568831SAndroid Build Coastguard Worker XML_DTD_NOT_EMPTY,
5667*7c568831SAndroid Build Coastguard Worker "Element %s was declared EMPTY this one has content\n",
5668*7c568831SAndroid Build Coastguard Worker state->node->name, NULL, NULL);
5669*7c568831SAndroid Build Coastguard Worker ret = 0;
5670*7c568831SAndroid Build Coastguard Worker break;
5671*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ANY:
5672*7c568831SAndroid Build Coastguard Worker break;
5673*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_MIXED:
5674*7c568831SAndroid Build Coastguard Worker break;
5675*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ELEMENT: {
5676*7c568831SAndroid Build Coastguard Worker int i;
5677*7c568831SAndroid Build Coastguard Worker
5678*7c568831SAndroid Build Coastguard Worker for (i = 0;i < len;i++) {
5679*7c568831SAndroid Build Coastguard Worker if (!IS_BLANK_CH(data[i])) {
5680*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5681*7c568831SAndroid Build Coastguard Worker XML_DTD_CONTENT_MODEL,
5682*7c568831SAndroid Build Coastguard Worker "Element %s content does not follow the DTD, Text not allowed\n",
5683*7c568831SAndroid Build Coastguard Worker state->node->name, NULL, NULL);
5684*7c568831SAndroid Build Coastguard Worker ret = 0;
5685*7c568831SAndroid Build Coastguard Worker goto done;
5686*7c568831SAndroid Build Coastguard Worker }
5687*7c568831SAndroid Build Coastguard Worker }
5688*7c568831SAndroid Build Coastguard Worker /*
5689*7c568831SAndroid Build Coastguard Worker * TODO:
5690*7c568831SAndroid Build Coastguard Worker * VC: Standalone Document Declaration
5691*7c568831SAndroid Build Coastguard Worker * element types with element content, if white space
5692*7c568831SAndroid Build Coastguard Worker * occurs directly within any instance of those types.
5693*7c568831SAndroid Build Coastguard Worker */
5694*7c568831SAndroid Build Coastguard Worker break;
5695*7c568831SAndroid Build Coastguard Worker }
5696*7c568831SAndroid Build Coastguard Worker }
5697*7c568831SAndroid Build Coastguard Worker }
5698*7c568831SAndroid Build Coastguard Worker }
5699*7c568831SAndroid Build Coastguard Worker done:
5700*7c568831SAndroid Build Coastguard Worker return(ret);
5701*7c568831SAndroid Build Coastguard Worker }
5702*7c568831SAndroid Build Coastguard Worker
5703*7c568831SAndroid Build Coastguard Worker /**
5704*7c568831SAndroid Build Coastguard Worker * xmlValidatePopElement:
5705*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
5706*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
5707*7c568831SAndroid Build Coastguard Worker * @elem: an element instance
5708*7c568831SAndroid Build Coastguard Worker * @qname: the qualified name as appearing in the serialization
5709*7c568831SAndroid Build Coastguard Worker *
5710*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
5711*7c568831SAndroid Build Coastguard Worker *
5712*7c568831SAndroid Build Coastguard Worker * Pop the element end from the validation stack.
5713*7c568831SAndroid Build Coastguard Worker *
5714*7c568831SAndroid Build Coastguard Worker * returns 1 if no validation problem was found or 0 otherwise
5715*7c568831SAndroid Build Coastguard Worker */
5716*7c568831SAndroid Build Coastguard Worker int
xmlValidatePopElement(xmlValidCtxtPtr ctxt,xmlDocPtr doc ATTRIBUTE_UNUSED,xmlNodePtr elem ATTRIBUTE_UNUSED,const xmlChar * qname ATTRIBUTE_UNUSED)5717*7c568831SAndroid Build Coastguard Worker xmlValidatePopElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc ATTRIBUTE_UNUSED,
5718*7c568831SAndroid Build Coastguard Worker xmlNodePtr elem ATTRIBUTE_UNUSED,
5719*7c568831SAndroid Build Coastguard Worker const xmlChar *qname ATTRIBUTE_UNUSED) {
5720*7c568831SAndroid Build Coastguard Worker int ret = 1;
5721*7c568831SAndroid Build Coastguard Worker
5722*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
5723*7c568831SAndroid Build Coastguard Worker return(0);
5724*7c568831SAndroid Build Coastguard Worker
5725*7c568831SAndroid Build Coastguard Worker if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5726*7c568831SAndroid Build Coastguard Worker xmlValidStatePtr state = ctxt->vstate;
5727*7c568831SAndroid Build Coastguard Worker xmlElementPtr elemDecl;
5728*7c568831SAndroid Build Coastguard Worker
5729*7c568831SAndroid Build Coastguard Worker /*
5730*7c568831SAndroid Build Coastguard Worker * Check the new element against the content model of the new elem.
5731*7c568831SAndroid Build Coastguard Worker */
5732*7c568831SAndroid Build Coastguard Worker if (state->elemDecl != NULL) {
5733*7c568831SAndroid Build Coastguard Worker elemDecl = state->elemDecl;
5734*7c568831SAndroid Build Coastguard Worker
5735*7c568831SAndroid Build Coastguard Worker if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT) {
5736*7c568831SAndroid Build Coastguard Worker if (state->exec != NULL) {
5737*7c568831SAndroid Build Coastguard Worker ret = xmlRegExecPushString(state->exec, NULL, NULL);
5738*7c568831SAndroid Build Coastguard Worker if (ret <= 0) {
5739*7c568831SAndroid Build Coastguard Worker if (ret == XML_REGEXP_OUT_OF_MEMORY)
5740*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5741*7c568831SAndroid Build Coastguard Worker else
5742*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5743*7c568831SAndroid Build Coastguard Worker XML_DTD_CONTENT_MODEL,
5744*7c568831SAndroid Build Coastguard Worker "Element %s content does not follow the DTD, Expecting more children\n",
5745*7c568831SAndroid Build Coastguard Worker state->node->name, NULL,NULL);
5746*7c568831SAndroid Build Coastguard Worker ret = 0;
5747*7c568831SAndroid Build Coastguard Worker } else {
5748*7c568831SAndroid Build Coastguard Worker /*
5749*7c568831SAndroid Build Coastguard Worker * previous validation errors should not generate
5750*7c568831SAndroid Build Coastguard Worker * a new one here
5751*7c568831SAndroid Build Coastguard Worker */
5752*7c568831SAndroid Build Coastguard Worker ret = 1;
5753*7c568831SAndroid Build Coastguard Worker }
5754*7c568831SAndroid Build Coastguard Worker }
5755*7c568831SAndroid Build Coastguard Worker }
5756*7c568831SAndroid Build Coastguard Worker }
5757*7c568831SAndroid Build Coastguard Worker vstateVPop(ctxt);
5758*7c568831SAndroid Build Coastguard Worker }
5759*7c568831SAndroid Build Coastguard Worker return(ret);
5760*7c568831SAndroid Build Coastguard Worker }
5761*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
5762*7c568831SAndroid Build Coastguard Worker
5763*7c568831SAndroid Build Coastguard Worker /**
5764*7c568831SAndroid Build Coastguard Worker * xmlValidateOneElement:
5765*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
5766*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
5767*7c568831SAndroid Build Coastguard Worker * @elem: an element instance
5768*7c568831SAndroid Build Coastguard Worker *
5769*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
5770*7c568831SAndroid Build Coastguard Worker *
5771*7c568831SAndroid Build Coastguard Worker * Try to validate a single element and it's attributes,
5772*7c568831SAndroid Build Coastguard Worker * basically it does the following checks as described by the
5773*7c568831SAndroid Build Coastguard Worker * XML-1.0 recommendation:
5774*7c568831SAndroid Build Coastguard Worker * - [ VC: Element Valid ]
5775*7c568831SAndroid Build Coastguard Worker * - [ VC: Required Attribute ]
5776*7c568831SAndroid Build Coastguard Worker * Then call xmlValidateOneAttribute() for each attribute present.
5777*7c568831SAndroid Build Coastguard Worker *
5778*7c568831SAndroid Build Coastguard Worker * The ID/IDREF checkings are done separately
5779*7c568831SAndroid Build Coastguard Worker *
5780*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
5781*7c568831SAndroid Build Coastguard Worker */
5782*7c568831SAndroid Build Coastguard Worker
5783*7c568831SAndroid Build Coastguard Worker int
xmlValidateOneElement(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem)5784*7c568831SAndroid Build Coastguard Worker xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5785*7c568831SAndroid Build Coastguard Worker xmlNodePtr elem) {
5786*7c568831SAndroid Build Coastguard Worker xmlElementPtr elemDecl = NULL;
5787*7c568831SAndroid Build Coastguard Worker xmlElementContentPtr cont;
5788*7c568831SAndroid Build Coastguard Worker xmlAttributePtr attr;
5789*7c568831SAndroid Build Coastguard Worker xmlNodePtr child;
5790*7c568831SAndroid Build Coastguard Worker int ret = 1, tmp;
5791*7c568831SAndroid Build Coastguard Worker const xmlChar *name;
5792*7c568831SAndroid Build Coastguard Worker int extsubset = 0;
5793*7c568831SAndroid Build Coastguard Worker
5794*7c568831SAndroid Build Coastguard Worker CHECK_DTD;
5795*7c568831SAndroid Build Coastguard Worker
5796*7c568831SAndroid Build Coastguard Worker if (elem == NULL) return(0);
5797*7c568831SAndroid Build Coastguard Worker switch (elem->type) {
5798*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5799*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5800*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
5801*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
5802*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
5803*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
5804*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
5805*7c568831SAndroid Build Coastguard Worker return(1);
5806*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
5807*7c568831SAndroid Build Coastguard Worker break;
5808*7c568831SAndroid Build Coastguard Worker default:
5809*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5810*7c568831SAndroid Build Coastguard Worker "unexpected element type\n", NULL, NULL ,NULL);
5811*7c568831SAndroid Build Coastguard Worker return(0);
5812*7c568831SAndroid Build Coastguard Worker }
5813*7c568831SAndroid Build Coastguard Worker
5814*7c568831SAndroid Build Coastguard Worker /*
5815*7c568831SAndroid Build Coastguard Worker * Fetch the declaration
5816*7c568831SAndroid Build Coastguard Worker */
5817*7c568831SAndroid Build Coastguard Worker elemDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset);
5818*7c568831SAndroid Build Coastguard Worker if (elemDecl == NULL)
5819*7c568831SAndroid Build Coastguard Worker return(0);
5820*7c568831SAndroid Build Coastguard Worker
5821*7c568831SAndroid Build Coastguard Worker /*
5822*7c568831SAndroid Build Coastguard Worker * If vstateNr is not zero that means continuous validation is
5823*7c568831SAndroid Build Coastguard Worker * activated, do not try to check the content model at that level.
5824*7c568831SAndroid Build Coastguard Worker */
5825*7c568831SAndroid Build Coastguard Worker if (ctxt->vstateNr == 0) {
5826*7c568831SAndroid Build Coastguard Worker /* Check that the element content matches the definition */
5827*7c568831SAndroid Build Coastguard Worker switch (elemDecl->etype) {
5828*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_UNDEFINED:
5829*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ELEM,
5830*7c568831SAndroid Build Coastguard Worker "No declaration for element %s\n",
5831*7c568831SAndroid Build Coastguard Worker elem->name, NULL, NULL);
5832*7c568831SAndroid Build Coastguard Worker return(0);
5833*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_EMPTY:
5834*7c568831SAndroid Build Coastguard Worker if (elem->children != NULL) {
5835*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOT_EMPTY,
5836*7c568831SAndroid Build Coastguard Worker "Element %s was declared EMPTY this one has content\n",
5837*7c568831SAndroid Build Coastguard Worker elem->name, NULL, NULL);
5838*7c568831SAndroid Build Coastguard Worker ret = 0;
5839*7c568831SAndroid Build Coastguard Worker }
5840*7c568831SAndroid Build Coastguard Worker break;
5841*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ANY:
5842*7c568831SAndroid Build Coastguard Worker /* I don't think anything is required then */
5843*7c568831SAndroid Build Coastguard Worker break;
5844*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_MIXED:
5845*7c568831SAndroid Build Coastguard Worker
5846*7c568831SAndroid Build Coastguard Worker /* simple case of declared as #PCDATA */
5847*7c568831SAndroid Build Coastguard Worker if ((elemDecl->content != NULL) &&
5848*7c568831SAndroid Build Coastguard Worker (elemDecl->content->type == XML_ELEMENT_CONTENT_PCDATA)) {
5849*7c568831SAndroid Build Coastguard Worker ret = xmlValidateOneCdataElement(ctxt, doc, elem);
5850*7c568831SAndroid Build Coastguard Worker if (!ret) {
5851*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOT_PCDATA,
5852*7c568831SAndroid Build Coastguard Worker "Element %s was declared #PCDATA but contains non text nodes\n",
5853*7c568831SAndroid Build Coastguard Worker elem->name, NULL, NULL);
5854*7c568831SAndroid Build Coastguard Worker }
5855*7c568831SAndroid Build Coastguard Worker break;
5856*7c568831SAndroid Build Coastguard Worker }
5857*7c568831SAndroid Build Coastguard Worker child = elem->children;
5858*7c568831SAndroid Build Coastguard Worker /* Hum, this start to get messy */
5859*7c568831SAndroid Build Coastguard Worker while (child != NULL) {
5860*7c568831SAndroid Build Coastguard Worker if (child->type == XML_ELEMENT_NODE) {
5861*7c568831SAndroid Build Coastguard Worker name = child->name;
5862*7c568831SAndroid Build Coastguard Worker if ((child->ns != NULL) && (child->ns->prefix != NULL)) {
5863*7c568831SAndroid Build Coastguard Worker xmlChar fn[50];
5864*7c568831SAndroid Build Coastguard Worker xmlChar *fullname;
5865*7c568831SAndroid Build Coastguard Worker
5866*7c568831SAndroid Build Coastguard Worker fullname = xmlBuildQName(child->name, child->ns->prefix,
5867*7c568831SAndroid Build Coastguard Worker fn, 50);
5868*7c568831SAndroid Build Coastguard Worker if (fullname == NULL) {
5869*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5870*7c568831SAndroid Build Coastguard Worker return(0);
5871*7c568831SAndroid Build Coastguard Worker }
5872*7c568831SAndroid Build Coastguard Worker cont = elemDecl->content;
5873*7c568831SAndroid Build Coastguard Worker while (cont != NULL) {
5874*7c568831SAndroid Build Coastguard Worker if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5875*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(cont->name, fullname))
5876*7c568831SAndroid Build Coastguard Worker break;
5877*7c568831SAndroid Build Coastguard Worker } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5878*7c568831SAndroid Build Coastguard Worker (cont->c1 != NULL) &&
5879*7c568831SAndroid Build Coastguard Worker (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5880*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(cont->c1->name, fullname))
5881*7c568831SAndroid Build Coastguard Worker break;
5882*7c568831SAndroid Build Coastguard Worker } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5883*7c568831SAndroid Build Coastguard Worker (cont->c1 == NULL) ||
5884*7c568831SAndroid Build Coastguard Worker (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5885*7c568831SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT,
5886*7c568831SAndroid Build Coastguard Worker "Internal: MIXED struct corrupted\n",
5887*7c568831SAndroid Build Coastguard Worker NULL);
5888*7c568831SAndroid Build Coastguard Worker break;
5889*7c568831SAndroid Build Coastguard Worker }
5890*7c568831SAndroid Build Coastguard Worker cont = cont->c2;
5891*7c568831SAndroid Build Coastguard Worker }
5892*7c568831SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != child->name))
5893*7c568831SAndroid Build Coastguard Worker xmlFree(fullname);
5894*7c568831SAndroid Build Coastguard Worker if (cont != NULL)
5895*7c568831SAndroid Build Coastguard Worker goto child_ok;
5896*7c568831SAndroid Build Coastguard Worker }
5897*7c568831SAndroid Build Coastguard Worker cont = elemDecl->content;
5898*7c568831SAndroid Build Coastguard Worker while (cont != NULL) {
5899*7c568831SAndroid Build Coastguard Worker if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5900*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(cont->name, name)) break;
5901*7c568831SAndroid Build Coastguard Worker } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5902*7c568831SAndroid Build Coastguard Worker (cont->c1 != NULL) &&
5903*7c568831SAndroid Build Coastguard Worker (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)) {
5904*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(cont->c1->name, name)) break;
5905*7c568831SAndroid Build Coastguard Worker } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5906*7c568831SAndroid Build Coastguard Worker (cont->c1 == NULL) ||
5907*7c568831SAndroid Build Coastguard Worker (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)) {
5908*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT,
5909*7c568831SAndroid Build Coastguard Worker "Internal: MIXED struct corrupted\n",
5910*7c568831SAndroid Build Coastguard Worker NULL);
5911*7c568831SAndroid Build Coastguard Worker break;
5912*7c568831SAndroid Build Coastguard Worker }
5913*7c568831SAndroid Build Coastguard Worker cont = cont->c2;
5914*7c568831SAndroid Build Coastguard Worker }
5915*7c568831SAndroid Build Coastguard Worker if (cont == NULL) {
5916*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_CHILD,
5917*7c568831SAndroid Build Coastguard Worker "Element %s is not declared in %s list of possible children\n",
5918*7c568831SAndroid Build Coastguard Worker name, elem->name, NULL);
5919*7c568831SAndroid Build Coastguard Worker ret = 0;
5920*7c568831SAndroid Build Coastguard Worker }
5921*7c568831SAndroid Build Coastguard Worker }
5922*7c568831SAndroid Build Coastguard Worker child_ok:
5923*7c568831SAndroid Build Coastguard Worker child = child->next;
5924*7c568831SAndroid Build Coastguard Worker }
5925*7c568831SAndroid Build Coastguard Worker break;
5926*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ELEMENT:
5927*7c568831SAndroid Build Coastguard Worker if ((doc->standalone == 1) && (extsubset == 1)) {
5928*7c568831SAndroid Build Coastguard Worker /*
5929*7c568831SAndroid Build Coastguard Worker * VC: Standalone Document Declaration
5930*7c568831SAndroid Build Coastguard Worker * - element types with element content, if white space
5931*7c568831SAndroid Build Coastguard Worker * occurs directly within any instance of those types.
5932*7c568831SAndroid Build Coastguard Worker */
5933*7c568831SAndroid Build Coastguard Worker child = elem->children;
5934*7c568831SAndroid Build Coastguard Worker while (child != NULL) {
5935*7c568831SAndroid Build Coastguard Worker if ((child->type == XML_TEXT_NODE) &&
5936*7c568831SAndroid Build Coastguard Worker (child->content != NULL)) {
5937*7c568831SAndroid Build Coastguard Worker const xmlChar *content = child->content;
5938*7c568831SAndroid Build Coastguard Worker
5939*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*content))
5940*7c568831SAndroid Build Coastguard Worker content++;
5941*7c568831SAndroid Build Coastguard Worker if (*content == 0) {
5942*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem,
5943*7c568831SAndroid Build Coastguard Worker XML_DTD_STANDALONE_WHITE_SPACE,
5944*7c568831SAndroid Build Coastguard Worker "standalone: %s declared in the external subset contains white spaces nodes\n",
5945*7c568831SAndroid Build Coastguard Worker elem->name, NULL, NULL);
5946*7c568831SAndroid Build Coastguard Worker ret = 0;
5947*7c568831SAndroid Build Coastguard Worker break;
5948*7c568831SAndroid Build Coastguard Worker }
5949*7c568831SAndroid Build Coastguard Worker }
5950*7c568831SAndroid Build Coastguard Worker child =child->next;
5951*7c568831SAndroid Build Coastguard Worker }
5952*7c568831SAndroid Build Coastguard Worker }
5953*7c568831SAndroid Build Coastguard Worker child = elem->children;
5954*7c568831SAndroid Build Coastguard Worker cont = elemDecl->content;
5955*7c568831SAndroid Build Coastguard Worker tmp = xmlValidateElementContent(ctxt, child, elemDecl, 1, elem);
5956*7c568831SAndroid Build Coastguard Worker if (tmp <= 0)
5957*7c568831SAndroid Build Coastguard Worker ret = 0;
5958*7c568831SAndroid Build Coastguard Worker break;
5959*7c568831SAndroid Build Coastguard Worker }
5960*7c568831SAndroid Build Coastguard Worker } /* not continuous */
5961*7c568831SAndroid Build Coastguard Worker
5962*7c568831SAndroid Build Coastguard Worker /* [ VC: Required Attribute ] */
5963*7c568831SAndroid Build Coastguard Worker attr = elemDecl->attributes;
5964*7c568831SAndroid Build Coastguard Worker while (attr != NULL) {
5965*7c568831SAndroid Build Coastguard Worker if (attr->def == XML_ATTRIBUTE_REQUIRED) {
5966*7c568831SAndroid Build Coastguard Worker int qualified = -1;
5967*7c568831SAndroid Build Coastguard Worker
5968*7c568831SAndroid Build Coastguard Worker if ((attr->prefix == NULL) &&
5969*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) {
5970*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns;
5971*7c568831SAndroid Build Coastguard Worker
5972*7c568831SAndroid Build Coastguard Worker ns = elem->nsDef;
5973*7c568831SAndroid Build Coastguard Worker while (ns != NULL) {
5974*7c568831SAndroid Build Coastguard Worker if (ns->prefix == NULL)
5975*7c568831SAndroid Build Coastguard Worker goto found;
5976*7c568831SAndroid Build Coastguard Worker ns = ns->next;
5977*7c568831SAndroid Build Coastguard Worker }
5978*7c568831SAndroid Build Coastguard Worker } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) {
5979*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns;
5980*7c568831SAndroid Build Coastguard Worker
5981*7c568831SAndroid Build Coastguard Worker ns = elem->nsDef;
5982*7c568831SAndroid Build Coastguard Worker while (ns != NULL) {
5983*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(attr->name, ns->prefix))
5984*7c568831SAndroid Build Coastguard Worker goto found;
5985*7c568831SAndroid Build Coastguard Worker ns = ns->next;
5986*7c568831SAndroid Build Coastguard Worker }
5987*7c568831SAndroid Build Coastguard Worker } else {
5988*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attrib;
5989*7c568831SAndroid Build Coastguard Worker
5990*7c568831SAndroid Build Coastguard Worker attrib = elem->properties;
5991*7c568831SAndroid Build Coastguard Worker while (attrib != NULL) {
5992*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(attrib->name, attr->name)) {
5993*7c568831SAndroid Build Coastguard Worker if (attr->prefix != NULL) {
5994*7c568831SAndroid Build Coastguard Worker xmlNsPtr nameSpace = attrib->ns;
5995*7c568831SAndroid Build Coastguard Worker
5996*7c568831SAndroid Build Coastguard Worker if (nameSpace == NULL)
5997*7c568831SAndroid Build Coastguard Worker nameSpace = elem->ns;
5998*7c568831SAndroid Build Coastguard Worker /*
5999*7c568831SAndroid Build Coastguard Worker * qualified names handling is problematic, having a
6000*7c568831SAndroid Build Coastguard Worker * different prefix should be possible but DTDs don't
6001*7c568831SAndroid Build Coastguard Worker * allow to define the URI instead of the prefix :-(
6002*7c568831SAndroid Build Coastguard Worker */
6003*7c568831SAndroid Build Coastguard Worker if (nameSpace == NULL) {
6004*7c568831SAndroid Build Coastguard Worker if (qualified < 0)
6005*7c568831SAndroid Build Coastguard Worker qualified = 0;
6006*7c568831SAndroid Build Coastguard Worker } else if (!xmlStrEqual(nameSpace->prefix,
6007*7c568831SAndroid Build Coastguard Worker attr->prefix)) {
6008*7c568831SAndroid Build Coastguard Worker if (qualified < 1)
6009*7c568831SAndroid Build Coastguard Worker qualified = 1;
6010*7c568831SAndroid Build Coastguard Worker } else
6011*7c568831SAndroid Build Coastguard Worker goto found;
6012*7c568831SAndroid Build Coastguard Worker } else {
6013*7c568831SAndroid Build Coastguard Worker /*
6014*7c568831SAndroid Build Coastguard Worker * We should allow applications to define namespaces
6015*7c568831SAndroid Build Coastguard Worker * for their application even if the DTD doesn't
6016*7c568831SAndroid Build Coastguard Worker * carry one, otherwise, basically we would always
6017*7c568831SAndroid Build Coastguard Worker * break.
6018*7c568831SAndroid Build Coastguard Worker */
6019*7c568831SAndroid Build Coastguard Worker goto found;
6020*7c568831SAndroid Build Coastguard Worker }
6021*7c568831SAndroid Build Coastguard Worker }
6022*7c568831SAndroid Build Coastguard Worker attrib = attrib->next;
6023*7c568831SAndroid Build Coastguard Worker }
6024*7c568831SAndroid Build Coastguard Worker }
6025*7c568831SAndroid Build Coastguard Worker if (qualified == -1) {
6026*7c568831SAndroid Build Coastguard Worker if (attr->prefix == NULL) {
6027*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE,
6028*7c568831SAndroid Build Coastguard Worker "Element %s does not carry attribute %s\n",
6029*7c568831SAndroid Build Coastguard Worker elem->name, attr->name, NULL);
6030*7c568831SAndroid Build Coastguard Worker ret = 0;
6031*7c568831SAndroid Build Coastguard Worker } else {
6032*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE,
6033*7c568831SAndroid Build Coastguard Worker "Element %s does not carry attribute %s:%s\n",
6034*7c568831SAndroid Build Coastguard Worker elem->name, attr->prefix,attr->name);
6035*7c568831SAndroid Build Coastguard Worker ret = 0;
6036*7c568831SAndroid Build Coastguard Worker }
6037*7c568831SAndroid Build Coastguard Worker } else if (qualified == 0) {
6038*7c568831SAndroid Build Coastguard Worker xmlErrValidWarning(ctxt, elem, XML_DTD_NO_PREFIX,
6039*7c568831SAndroid Build Coastguard Worker "Element %s required attribute %s:%s has no prefix\n",
6040*7c568831SAndroid Build Coastguard Worker elem->name, attr->prefix, attr->name);
6041*7c568831SAndroid Build Coastguard Worker } else if (qualified == 1) {
6042*7c568831SAndroid Build Coastguard Worker xmlErrValidWarning(ctxt, elem, XML_DTD_DIFFERENT_PREFIX,
6043*7c568831SAndroid Build Coastguard Worker "Element %s required attribute %s:%s has different prefix\n",
6044*7c568831SAndroid Build Coastguard Worker elem->name, attr->prefix, attr->name);
6045*7c568831SAndroid Build Coastguard Worker }
6046*7c568831SAndroid Build Coastguard Worker } else if (attr->def == XML_ATTRIBUTE_FIXED) {
6047*7c568831SAndroid Build Coastguard Worker /*
6048*7c568831SAndroid Build Coastguard Worker * Special tests checking #FIXED namespace declarations
6049*7c568831SAndroid Build Coastguard Worker * have the right value since this is not done as an
6050*7c568831SAndroid Build Coastguard Worker * attribute checking
6051*7c568831SAndroid Build Coastguard Worker */
6052*7c568831SAndroid Build Coastguard Worker if ((attr->prefix == NULL) &&
6053*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) {
6054*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns;
6055*7c568831SAndroid Build Coastguard Worker
6056*7c568831SAndroid Build Coastguard Worker ns = elem->nsDef;
6057*7c568831SAndroid Build Coastguard Worker while (ns != NULL) {
6058*7c568831SAndroid Build Coastguard Worker if (ns->prefix == NULL) {
6059*7c568831SAndroid Build Coastguard Worker if (!xmlStrEqual(attr->defaultValue, ns->href)) {
6060*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem,
6061*7c568831SAndroid Build Coastguard Worker XML_DTD_ELEM_DEFAULT_NAMESPACE,
6062*7c568831SAndroid Build Coastguard Worker "Element %s namespace name for default namespace does not match the DTD\n",
6063*7c568831SAndroid Build Coastguard Worker elem->name, NULL, NULL);
6064*7c568831SAndroid Build Coastguard Worker ret = 0;
6065*7c568831SAndroid Build Coastguard Worker }
6066*7c568831SAndroid Build Coastguard Worker goto found;
6067*7c568831SAndroid Build Coastguard Worker }
6068*7c568831SAndroid Build Coastguard Worker ns = ns->next;
6069*7c568831SAndroid Build Coastguard Worker }
6070*7c568831SAndroid Build Coastguard Worker } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) {
6071*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns;
6072*7c568831SAndroid Build Coastguard Worker
6073*7c568831SAndroid Build Coastguard Worker ns = elem->nsDef;
6074*7c568831SAndroid Build Coastguard Worker while (ns != NULL) {
6075*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(attr->name, ns->prefix)) {
6076*7c568831SAndroid Build Coastguard Worker if (!xmlStrEqual(attr->defaultValue, ns->href)) {
6077*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
6078*7c568831SAndroid Build Coastguard Worker "Element %s namespace name for %s does not match the DTD\n",
6079*7c568831SAndroid Build Coastguard Worker elem->name, ns->prefix, NULL);
6080*7c568831SAndroid Build Coastguard Worker ret = 0;
6081*7c568831SAndroid Build Coastguard Worker }
6082*7c568831SAndroid Build Coastguard Worker goto found;
6083*7c568831SAndroid Build Coastguard Worker }
6084*7c568831SAndroid Build Coastguard Worker ns = ns->next;
6085*7c568831SAndroid Build Coastguard Worker }
6086*7c568831SAndroid Build Coastguard Worker }
6087*7c568831SAndroid Build Coastguard Worker }
6088*7c568831SAndroid Build Coastguard Worker found:
6089*7c568831SAndroid Build Coastguard Worker attr = attr->nexth;
6090*7c568831SAndroid Build Coastguard Worker }
6091*7c568831SAndroid Build Coastguard Worker return(ret);
6092*7c568831SAndroid Build Coastguard Worker }
6093*7c568831SAndroid Build Coastguard Worker
6094*7c568831SAndroid Build Coastguard Worker /**
6095*7c568831SAndroid Build Coastguard Worker * xmlValidateRoot:
6096*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
6097*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
6098*7c568831SAndroid Build Coastguard Worker *
6099*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
6100*7c568831SAndroid Build Coastguard Worker *
6101*7c568831SAndroid Build Coastguard Worker * Try to validate a the root element
6102*7c568831SAndroid Build Coastguard Worker * basically it does the following check as described by the
6103*7c568831SAndroid Build Coastguard Worker * XML-1.0 recommendation:
6104*7c568831SAndroid Build Coastguard Worker * - [ VC: Root Element Type ]
6105*7c568831SAndroid Build Coastguard Worker * it doesn't try to recurse or apply other check to the element
6106*7c568831SAndroid Build Coastguard Worker *
6107*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
6108*7c568831SAndroid Build Coastguard Worker */
6109*7c568831SAndroid Build Coastguard Worker
6110*7c568831SAndroid Build Coastguard Worker int
xmlValidateRoot(xmlValidCtxtPtr ctxt,xmlDocPtr doc)6111*7c568831SAndroid Build Coastguard Worker xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6112*7c568831SAndroid Build Coastguard Worker xmlNodePtr root;
6113*7c568831SAndroid Build Coastguard Worker int ret;
6114*7c568831SAndroid Build Coastguard Worker
6115*7c568831SAndroid Build Coastguard Worker if (doc == NULL) return(0);
6116*7c568831SAndroid Build Coastguard Worker
6117*7c568831SAndroid Build Coastguard Worker root = xmlDocGetRootElement(doc);
6118*7c568831SAndroid Build Coastguard Worker if ((root == NULL) || (root->name == NULL)) {
6119*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_NO_ROOT,
6120*7c568831SAndroid Build Coastguard Worker "no root element\n", NULL);
6121*7c568831SAndroid Build Coastguard Worker return(0);
6122*7c568831SAndroid Build Coastguard Worker }
6123*7c568831SAndroid Build Coastguard Worker
6124*7c568831SAndroid Build Coastguard Worker /*
6125*7c568831SAndroid Build Coastguard Worker * When doing post validation against a separate DTD, those may
6126*7c568831SAndroid Build Coastguard Worker * no internal subset has been generated
6127*7c568831SAndroid Build Coastguard Worker */
6128*7c568831SAndroid Build Coastguard Worker if ((doc->intSubset != NULL) &&
6129*7c568831SAndroid Build Coastguard Worker (doc->intSubset->name != NULL)) {
6130*7c568831SAndroid Build Coastguard Worker /*
6131*7c568831SAndroid Build Coastguard Worker * Check first the document root against the NQName
6132*7c568831SAndroid Build Coastguard Worker */
6133*7c568831SAndroid Build Coastguard Worker if (!xmlStrEqual(doc->intSubset->name, root->name)) {
6134*7c568831SAndroid Build Coastguard Worker if ((root->ns != NULL) && (root->ns->prefix != NULL)) {
6135*7c568831SAndroid Build Coastguard Worker xmlChar fn[50];
6136*7c568831SAndroid Build Coastguard Worker xmlChar *fullname;
6137*7c568831SAndroid Build Coastguard Worker
6138*7c568831SAndroid Build Coastguard Worker fullname = xmlBuildQName(root->name, root->ns->prefix, fn, 50);
6139*7c568831SAndroid Build Coastguard Worker if (fullname == NULL) {
6140*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
6141*7c568831SAndroid Build Coastguard Worker return(0);
6142*7c568831SAndroid Build Coastguard Worker }
6143*7c568831SAndroid Build Coastguard Worker ret = xmlStrEqual(doc->intSubset->name, fullname);
6144*7c568831SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != root->name))
6145*7c568831SAndroid Build Coastguard Worker xmlFree(fullname);
6146*7c568831SAndroid Build Coastguard Worker if (ret == 1)
6147*7c568831SAndroid Build Coastguard Worker goto name_ok;
6148*7c568831SAndroid Build Coastguard Worker }
6149*7c568831SAndroid Build Coastguard Worker if ((xmlStrEqual(doc->intSubset->name, BAD_CAST "HTML")) &&
6150*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(root->name, BAD_CAST "html")))
6151*7c568831SAndroid Build Coastguard Worker goto name_ok;
6152*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, root, XML_DTD_ROOT_NAME,
6153*7c568831SAndroid Build Coastguard Worker "root and DTD name do not match '%s' and '%s'\n",
6154*7c568831SAndroid Build Coastguard Worker root->name, doc->intSubset->name, NULL);
6155*7c568831SAndroid Build Coastguard Worker return(0);
6156*7c568831SAndroid Build Coastguard Worker }
6157*7c568831SAndroid Build Coastguard Worker }
6158*7c568831SAndroid Build Coastguard Worker name_ok:
6159*7c568831SAndroid Build Coastguard Worker return(1);
6160*7c568831SAndroid Build Coastguard Worker }
6161*7c568831SAndroid Build Coastguard Worker
6162*7c568831SAndroid Build Coastguard Worker
6163*7c568831SAndroid Build Coastguard Worker /**
6164*7c568831SAndroid Build Coastguard Worker * xmlValidateElement:
6165*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
6166*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
6167*7c568831SAndroid Build Coastguard Worker * @root: an element instance
6168*7c568831SAndroid Build Coastguard Worker *
6169*7c568831SAndroid Build Coastguard Worker * Try to validate the subtree under an element
6170*7c568831SAndroid Build Coastguard Worker *
6171*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
6172*7c568831SAndroid Build Coastguard Worker */
6173*7c568831SAndroid Build Coastguard Worker
6174*7c568831SAndroid Build Coastguard Worker int
xmlValidateElement(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr root)6175*7c568831SAndroid Build Coastguard Worker xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr root) {
6176*7c568831SAndroid Build Coastguard Worker xmlNodePtr elem;
6177*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr;
6178*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns;
6179*7c568831SAndroid Build Coastguard Worker const xmlChar *value;
6180*7c568831SAndroid Build Coastguard Worker int ret = 1;
6181*7c568831SAndroid Build Coastguard Worker
6182*7c568831SAndroid Build Coastguard Worker if (root == NULL) return(0);
6183*7c568831SAndroid Build Coastguard Worker
6184*7c568831SAndroid Build Coastguard Worker CHECK_DTD;
6185*7c568831SAndroid Build Coastguard Worker
6186*7c568831SAndroid Build Coastguard Worker elem = root;
6187*7c568831SAndroid Build Coastguard Worker while (1) {
6188*7c568831SAndroid Build Coastguard Worker ret &= xmlValidateOneElement(ctxt, doc, elem);
6189*7c568831SAndroid Build Coastguard Worker
6190*7c568831SAndroid Build Coastguard Worker if (elem->type == XML_ELEMENT_NODE) {
6191*7c568831SAndroid Build Coastguard Worker attr = elem->properties;
6192*7c568831SAndroid Build Coastguard Worker while (attr != NULL) {
6193*7c568831SAndroid Build Coastguard Worker if (attr->children == NULL)
6194*7c568831SAndroid Build Coastguard Worker value = xmlStrdup(BAD_CAST "");
6195*7c568831SAndroid Build Coastguard Worker else
6196*7c568831SAndroid Build Coastguard Worker value = xmlNodeListGetString(doc, attr->children, 0);
6197*7c568831SAndroid Build Coastguard Worker if (value == NULL) {
6198*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
6199*7c568831SAndroid Build Coastguard Worker ret = 0;
6200*7c568831SAndroid Build Coastguard Worker } else {
6201*7c568831SAndroid Build Coastguard Worker ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
6202*7c568831SAndroid Build Coastguard Worker xmlFree((char *)value);
6203*7c568831SAndroid Build Coastguard Worker }
6204*7c568831SAndroid Build Coastguard Worker attr= attr->next;
6205*7c568831SAndroid Build Coastguard Worker }
6206*7c568831SAndroid Build Coastguard Worker
6207*7c568831SAndroid Build Coastguard Worker ns = elem->nsDef;
6208*7c568831SAndroid Build Coastguard Worker while (ns != NULL) {
6209*7c568831SAndroid Build Coastguard Worker if (elem->ns == NULL)
6210*7c568831SAndroid Build Coastguard Worker ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
6211*7c568831SAndroid Build Coastguard Worker ns, ns->href);
6212*7c568831SAndroid Build Coastguard Worker else
6213*7c568831SAndroid Build Coastguard Worker ret &= xmlValidateOneNamespace(ctxt, doc, elem,
6214*7c568831SAndroid Build Coastguard Worker elem->ns->prefix, ns,
6215*7c568831SAndroid Build Coastguard Worker ns->href);
6216*7c568831SAndroid Build Coastguard Worker ns = ns->next;
6217*7c568831SAndroid Build Coastguard Worker }
6218*7c568831SAndroid Build Coastguard Worker
6219*7c568831SAndroid Build Coastguard Worker if (elem->children != NULL) {
6220*7c568831SAndroid Build Coastguard Worker elem = elem->children;
6221*7c568831SAndroid Build Coastguard Worker continue;
6222*7c568831SAndroid Build Coastguard Worker }
6223*7c568831SAndroid Build Coastguard Worker }
6224*7c568831SAndroid Build Coastguard Worker
6225*7c568831SAndroid Build Coastguard Worker while (1) {
6226*7c568831SAndroid Build Coastguard Worker if (elem == root)
6227*7c568831SAndroid Build Coastguard Worker goto done;
6228*7c568831SAndroid Build Coastguard Worker if (elem->next != NULL)
6229*7c568831SAndroid Build Coastguard Worker break;
6230*7c568831SAndroid Build Coastguard Worker elem = elem->parent;
6231*7c568831SAndroid Build Coastguard Worker }
6232*7c568831SAndroid Build Coastguard Worker elem = elem->next;
6233*7c568831SAndroid Build Coastguard Worker }
6234*7c568831SAndroid Build Coastguard Worker
6235*7c568831SAndroid Build Coastguard Worker done:
6236*7c568831SAndroid Build Coastguard Worker return(ret);
6237*7c568831SAndroid Build Coastguard Worker }
6238*7c568831SAndroid Build Coastguard Worker
6239*7c568831SAndroid Build Coastguard Worker /**
6240*7c568831SAndroid Build Coastguard Worker * xmlValidateRef:
6241*7c568831SAndroid Build Coastguard Worker * @ref: A reference to be validated
6242*7c568831SAndroid Build Coastguard Worker * @ctxt: Validation context
6243*7c568831SAndroid Build Coastguard Worker * @name: Name of ID we are searching for
6244*7c568831SAndroid Build Coastguard Worker *
6245*7c568831SAndroid Build Coastguard Worker */
6246*7c568831SAndroid Build Coastguard Worker static void
xmlValidateRef(xmlRefPtr ref,xmlValidCtxtPtr ctxt,const xmlChar * name)6247*7c568831SAndroid Build Coastguard Worker xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
6248*7c568831SAndroid Build Coastguard Worker const xmlChar *name) {
6249*7c568831SAndroid Build Coastguard Worker xmlAttrPtr id;
6250*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr;
6251*7c568831SAndroid Build Coastguard Worker
6252*7c568831SAndroid Build Coastguard Worker if (ref == NULL)
6253*7c568831SAndroid Build Coastguard Worker return;
6254*7c568831SAndroid Build Coastguard Worker if ((ref->attr == NULL) && (ref->name == NULL))
6255*7c568831SAndroid Build Coastguard Worker return;
6256*7c568831SAndroid Build Coastguard Worker attr = ref->attr;
6257*7c568831SAndroid Build Coastguard Worker if (attr == NULL) {
6258*7c568831SAndroid Build Coastguard Worker xmlChar *dup, *str = NULL, *cur, save;
6259*7c568831SAndroid Build Coastguard Worker
6260*7c568831SAndroid Build Coastguard Worker dup = xmlStrdup(name);
6261*7c568831SAndroid Build Coastguard Worker if (dup == NULL) {
6262*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
6263*7c568831SAndroid Build Coastguard Worker return;
6264*7c568831SAndroid Build Coastguard Worker }
6265*7c568831SAndroid Build Coastguard Worker cur = dup;
6266*7c568831SAndroid Build Coastguard Worker while (*cur != 0) {
6267*7c568831SAndroid Build Coastguard Worker str = cur;
6268*7c568831SAndroid Build Coastguard Worker while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
6269*7c568831SAndroid Build Coastguard Worker save = *cur;
6270*7c568831SAndroid Build Coastguard Worker *cur = 0;
6271*7c568831SAndroid Build Coastguard Worker id = xmlGetID(ctxt->doc, str);
6272*7c568831SAndroid Build Coastguard Worker if (id == NULL) {
6273*7c568831SAndroid Build Coastguard Worker xmlErrValidNodeNr(ctxt, NULL, XML_DTD_UNKNOWN_ID,
6274*7c568831SAndroid Build Coastguard Worker "attribute %s line %d references an unknown ID \"%s\"\n",
6275*7c568831SAndroid Build Coastguard Worker ref->name, ref->lineno, str);
6276*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
6277*7c568831SAndroid Build Coastguard Worker }
6278*7c568831SAndroid Build Coastguard Worker if (save == 0)
6279*7c568831SAndroid Build Coastguard Worker break;
6280*7c568831SAndroid Build Coastguard Worker *cur = save;
6281*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
6282*7c568831SAndroid Build Coastguard Worker }
6283*7c568831SAndroid Build Coastguard Worker xmlFree(dup);
6284*7c568831SAndroid Build Coastguard Worker } else if (attr->atype == XML_ATTRIBUTE_IDREF) {
6285*7c568831SAndroid Build Coastguard Worker id = xmlGetID(ctxt->doc, name);
6286*7c568831SAndroid Build Coastguard Worker if (id == NULL) {
6287*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
6288*7c568831SAndroid Build Coastguard Worker "IDREF attribute %s references an unknown ID \"%s\"\n",
6289*7c568831SAndroid Build Coastguard Worker attr->name, name, NULL);
6290*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
6291*7c568831SAndroid Build Coastguard Worker }
6292*7c568831SAndroid Build Coastguard Worker } else if (attr->atype == XML_ATTRIBUTE_IDREFS) {
6293*7c568831SAndroid Build Coastguard Worker xmlChar *dup, *str = NULL, *cur, save;
6294*7c568831SAndroid Build Coastguard Worker
6295*7c568831SAndroid Build Coastguard Worker dup = xmlStrdup(name);
6296*7c568831SAndroid Build Coastguard Worker if (dup == NULL) {
6297*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
6298*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
6299*7c568831SAndroid Build Coastguard Worker return;
6300*7c568831SAndroid Build Coastguard Worker }
6301*7c568831SAndroid Build Coastguard Worker cur = dup;
6302*7c568831SAndroid Build Coastguard Worker while (*cur != 0) {
6303*7c568831SAndroid Build Coastguard Worker str = cur;
6304*7c568831SAndroid Build Coastguard Worker while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
6305*7c568831SAndroid Build Coastguard Worker save = *cur;
6306*7c568831SAndroid Build Coastguard Worker *cur = 0;
6307*7c568831SAndroid Build Coastguard Worker id = xmlGetID(ctxt->doc, str);
6308*7c568831SAndroid Build Coastguard Worker if (id == NULL) {
6309*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
6310*7c568831SAndroid Build Coastguard Worker "IDREFS attribute %s references an unknown ID \"%s\"\n",
6311*7c568831SAndroid Build Coastguard Worker attr->name, str, NULL);
6312*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
6313*7c568831SAndroid Build Coastguard Worker }
6314*7c568831SAndroid Build Coastguard Worker if (save == 0)
6315*7c568831SAndroid Build Coastguard Worker break;
6316*7c568831SAndroid Build Coastguard Worker *cur = save;
6317*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
6318*7c568831SAndroid Build Coastguard Worker }
6319*7c568831SAndroid Build Coastguard Worker xmlFree(dup);
6320*7c568831SAndroid Build Coastguard Worker }
6321*7c568831SAndroid Build Coastguard Worker }
6322*7c568831SAndroid Build Coastguard Worker
6323*7c568831SAndroid Build Coastguard Worker /**
6324*7c568831SAndroid Build Coastguard Worker * xmlWalkValidateList:
6325*7c568831SAndroid Build Coastguard Worker * @data: Contents of current link
6326*7c568831SAndroid Build Coastguard Worker * @user: Value supplied by the user
6327*7c568831SAndroid Build Coastguard Worker *
6328*7c568831SAndroid Build Coastguard Worker * Returns 0 to abort the walk or 1 to continue
6329*7c568831SAndroid Build Coastguard Worker */
6330*7c568831SAndroid Build Coastguard Worker static int
xmlWalkValidateList(const void * data,void * user)6331*7c568831SAndroid Build Coastguard Worker xmlWalkValidateList(const void *data, void *user)
6332*7c568831SAndroid Build Coastguard Worker {
6333*7c568831SAndroid Build Coastguard Worker xmlValidateMemoPtr memo = (xmlValidateMemoPtr)user;
6334*7c568831SAndroid Build Coastguard Worker xmlValidateRef((xmlRefPtr)data, memo->ctxt, memo->name);
6335*7c568831SAndroid Build Coastguard Worker return 1;
6336*7c568831SAndroid Build Coastguard Worker }
6337*7c568831SAndroid Build Coastguard Worker
6338*7c568831SAndroid Build Coastguard Worker /**
6339*7c568831SAndroid Build Coastguard Worker * xmlValidateCheckRefCallback:
6340*7c568831SAndroid Build Coastguard Worker * @ref_list: List of references
6341*7c568831SAndroid Build Coastguard Worker * @ctxt: Validation context
6342*7c568831SAndroid Build Coastguard Worker * @name: Name of ID we are searching for
6343*7c568831SAndroid Build Coastguard Worker *
6344*7c568831SAndroid Build Coastguard Worker */
6345*7c568831SAndroid Build Coastguard Worker static void
xmlValidateCheckRefCallback(void * payload,void * data,const xmlChar * name)6346*7c568831SAndroid Build Coastguard Worker xmlValidateCheckRefCallback(void *payload, void *data, const xmlChar *name) {
6347*7c568831SAndroid Build Coastguard Worker xmlListPtr ref_list = (xmlListPtr) payload;
6348*7c568831SAndroid Build Coastguard Worker xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
6349*7c568831SAndroid Build Coastguard Worker xmlValidateMemo memo;
6350*7c568831SAndroid Build Coastguard Worker
6351*7c568831SAndroid Build Coastguard Worker if (ref_list == NULL)
6352*7c568831SAndroid Build Coastguard Worker return;
6353*7c568831SAndroid Build Coastguard Worker memo.ctxt = ctxt;
6354*7c568831SAndroid Build Coastguard Worker memo.name = name;
6355*7c568831SAndroid Build Coastguard Worker
6356*7c568831SAndroid Build Coastguard Worker xmlListWalk(ref_list, xmlWalkValidateList, &memo);
6357*7c568831SAndroid Build Coastguard Worker
6358*7c568831SAndroid Build Coastguard Worker }
6359*7c568831SAndroid Build Coastguard Worker
6360*7c568831SAndroid Build Coastguard Worker /**
6361*7c568831SAndroid Build Coastguard Worker * xmlValidateDocumentFinal:
6362*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
6363*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
6364*7c568831SAndroid Build Coastguard Worker *
6365*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
6366*7c568831SAndroid Build Coastguard Worker *
6367*7c568831SAndroid Build Coastguard Worker * Does the final step for the document validation once all the
6368*7c568831SAndroid Build Coastguard Worker * incremental validation steps have been completed
6369*7c568831SAndroid Build Coastguard Worker *
6370*7c568831SAndroid Build Coastguard Worker * basically it does the following checks described by the XML Rec
6371*7c568831SAndroid Build Coastguard Worker *
6372*7c568831SAndroid Build Coastguard Worker * Check all the IDREF/IDREFS attributes definition for validity
6373*7c568831SAndroid Build Coastguard Worker *
6374*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
6375*7c568831SAndroid Build Coastguard Worker */
6376*7c568831SAndroid Build Coastguard Worker
6377*7c568831SAndroid Build Coastguard Worker int
xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt,xmlDocPtr doc)6378*7c568831SAndroid Build Coastguard Worker xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6379*7c568831SAndroid Build Coastguard Worker xmlRefTablePtr table;
6380*7c568831SAndroid Build Coastguard Worker xmlParserCtxtPtr pctxt = NULL;
6381*7c568831SAndroid Build Coastguard Worker xmlParserInputPtr oldInput = NULL;
6382*7c568831SAndroid Build Coastguard Worker
6383*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
6384*7c568831SAndroid Build Coastguard Worker return(0);
6385*7c568831SAndroid Build Coastguard Worker if (doc == NULL) {
6386*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_NO_DOC,
6387*7c568831SAndroid Build Coastguard Worker "xmlValidateDocumentFinal: doc == NULL\n", NULL);
6388*7c568831SAndroid Build Coastguard Worker return(0);
6389*7c568831SAndroid Build Coastguard Worker }
6390*7c568831SAndroid Build Coastguard Worker
6391*7c568831SAndroid Build Coastguard Worker /*
6392*7c568831SAndroid Build Coastguard Worker * Check all the NOTATION/NOTATIONS attributes
6393*7c568831SAndroid Build Coastguard Worker */
6394*7c568831SAndroid Build Coastguard Worker /*
6395*7c568831SAndroid Build Coastguard Worker * Check all the ENTITY/ENTITIES attributes definition for validity
6396*7c568831SAndroid Build Coastguard Worker */
6397*7c568831SAndroid Build Coastguard Worker /*
6398*7c568831SAndroid Build Coastguard Worker * Check all the IDREF/IDREFS attributes definition for validity
6399*7c568831SAndroid Build Coastguard Worker */
6400*7c568831SAndroid Build Coastguard Worker
6401*7c568831SAndroid Build Coastguard Worker /*
6402*7c568831SAndroid Build Coastguard Worker * Don't print line numbers.
6403*7c568831SAndroid Build Coastguard Worker */
6404*7c568831SAndroid Build Coastguard Worker if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
6405*7c568831SAndroid Build Coastguard Worker pctxt = ctxt->userData;
6406*7c568831SAndroid Build Coastguard Worker oldInput = pctxt->input;
6407*7c568831SAndroid Build Coastguard Worker pctxt->input = NULL;
6408*7c568831SAndroid Build Coastguard Worker }
6409*7c568831SAndroid Build Coastguard Worker
6410*7c568831SAndroid Build Coastguard Worker table = (xmlRefTablePtr) doc->refs;
6411*7c568831SAndroid Build Coastguard Worker ctxt->doc = doc;
6412*7c568831SAndroid Build Coastguard Worker ctxt->valid = 1;
6413*7c568831SAndroid Build Coastguard Worker xmlHashScan(table, xmlValidateCheckRefCallback, ctxt);
6414*7c568831SAndroid Build Coastguard Worker
6415*7c568831SAndroid Build Coastguard Worker if (ctxt->flags & XML_VCTXT_USE_PCTXT)
6416*7c568831SAndroid Build Coastguard Worker pctxt->input = oldInput;
6417*7c568831SAndroid Build Coastguard Worker
6418*7c568831SAndroid Build Coastguard Worker return(ctxt->valid);
6419*7c568831SAndroid Build Coastguard Worker }
6420*7c568831SAndroid Build Coastguard Worker
6421*7c568831SAndroid Build Coastguard Worker /**
6422*7c568831SAndroid Build Coastguard Worker * xmlValidateDtd:
6423*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
6424*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
6425*7c568831SAndroid Build Coastguard Worker * @dtd: a dtd instance
6426*7c568831SAndroid Build Coastguard Worker *
6427*7c568831SAndroid Build Coastguard Worker * Try to validate the document against the dtd instance
6428*7c568831SAndroid Build Coastguard Worker *
6429*7c568831SAndroid Build Coastguard Worker * Basically it does check all the definitions in the DtD.
6430*7c568831SAndroid Build Coastguard Worker * Note the the internal subset (if present) is de-coupled
6431*7c568831SAndroid Build Coastguard Worker * (i.e. not used), which could give problems if ID or IDREF
6432*7c568831SAndroid Build Coastguard Worker * is present.
6433*7c568831SAndroid Build Coastguard Worker *
6434*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
6435*7c568831SAndroid Build Coastguard Worker */
6436*7c568831SAndroid Build Coastguard Worker
6437*7c568831SAndroid Build Coastguard Worker int
xmlValidateDtd(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlDtdPtr dtd)6438*7c568831SAndroid Build Coastguard Worker xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) {
6439*7c568831SAndroid Build Coastguard Worker int ret;
6440*7c568831SAndroid Build Coastguard Worker xmlDtdPtr oldExt, oldInt;
6441*7c568831SAndroid Build Coastguard Worker xmlNodePtr root;
6442*7c568831SAndroid Build Coastguard Worker
6443*7c568831SAndroid Build Coastguard Worker if (dtd == NULL)
6444*7c568831SAndroid Build Coastguard Worker return(0);
6445*7c568831SAndroid Build Coastguard Worker if (doc == NULL)
6446*7c568831SAndroid Build Coastguard Worker return(0);
6447*7c568831SAndroid Build Coastguard Worker
6448*7c568831SAndroid Build Coastguard Worker oldExt = doc->extSubset;
6449*7c568831SAndroid Build Coastguard Worker oldInt = doc->intSubset;
6450*7c568831SAndroid Build Coastguard Worker doc->extSubset = dtd;
6451*7c568831SAndroid Build Coastguard Worker doc->intSubset = NULL;
6452*7c568831SAndroid Build Coastguard Worker if (doc->ids != NULL) {
6453*7c568831SAndroid Build Coastguard Worker xmlFreeIDTable(doc->ids);
6454*7c568831SAndroid Build Coastguard Worker doc->ids = NULL;
6455*7c568831SAndroid Build Coastguard Worker }
6456*7c568831SAndroid Build Coastguard Worker if (doc->refs != NULL) {
6457*7c568831SAndroid Build Coastguard Worker xmlFreeRefTable(doc->refs);
6458*7c568831SAndroid Build Coastguard Worker doc->refs = NULL;
6459*7c568831SAndroid Build Coastguard Worker }
6460*7c568831SAndroid Build Coastguard Worker
6461*7c568831SAndroid Build Coastguard Worker ret = xmlValidateRoot(ctxt, doc);
6462*7c568831SAndroid Build Coastguard Worker if (ret != 0) {
6463*7c568831SAndroid Build Coastguard Worker root = xmlDocGetRootElement(doc);
6464*7c568831SAndroid Build Coastguard Worker ret = xmlValidateElement(ctxt, doc, root);
6465*7c568831SAndroid Build Coastguard Worker ret &= xmlValidateDocumentFinal(ctxt, doc);
6466*7c568831SAndroid Build Coastguard Worker }
6467*7c568831SAndroid Build Coastguard Worker
6468*7c568831SAndroid Build Coastguard Worker doc->extSubset = oldExt;
6469*7c568831SAndroid Build Coastguard Worker doc->intSubset = oldInt;
6470*7c568831SAndroid Build Coastguard Worker if (doc->ids != NULL) {
6471*7c568831SAndroid Build Coastguard Worker xmlFreeIDTable(doc->ids);
6472*7c568831SAndroid Build Coastguard Worker doc->ids = NULL;
6473*7c568831SAndroid Build Coastguard Worker }
6474*7c568831SAndroid Build Coastguard Worker if (doc->refs != NULL) {
6475*7c568831SAndroid Build Coastguard Worker xmlFreeRefTable(doc->refs);
6476*7c568831SAndroid Build Coastguard Worker doc->refs = NULL;
6477*7c568831SAndroid Build Coastguard Worker }
6478*7c568831SAndroid Build Coastguard Worker
6479*7c568831SAndroid Build Coastguard Worker return(ret);
6480*7c568831SAndroid Build Coastguard Worker }
6481*7c568831SAndroid Build Coastguard Worker
6482*7c568831SAndroid Build Coastguard Worker static void
xmlValidateNotationCallback(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)6483*7c568831SAndroid Build Coastguard Worker xmlValidateNotationCallback(void *payload, void *data,
6484*7c568831SAndroid Build Coastguard Worker const xmlChar *name ATTRIBUTE_UNUSED) {
6485*7c568831SAndroid Build Coastguard Worker xmlEntityPtr cur = (xmlEntityPtr) payload;
6486*7c568831SAndroid Build Coastguard Worker xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
6487*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
6488*7c568831SAndroid Build Coastguard Worker return;
6489*7c568831SAndroid Build Coastguard Worker if (cur->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
6490*7c568831SAndroid Build Coastguard Worker xmlChar *notation = cur->content;
6491*7c568831SAndroid Build Coastguard Worker
6492*7c568831SAndroid Build Coastguard Worker if (notation != NULL) {
6493*7c568831SAndroid Build Coastguard Worker int ret;
6494*7c568831SAndroid Build Coastguard Worker
6495*7c568831SAndroid Build Coastguard Worker ret = xmlValidateNotationUse(ctxt, cur->doc, notation);
6496*7c568831SAndroid Build Coastguard Worker if (ret != 1) {
6497*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
6498*7c568831SAndroid Build Coastguard Worker }
6499*7c568831SAndroid Build Coastguard Worker }
6500*7c568831SAndroid Build Coastguard Worker }
6501*7c568831SAndroid Build Coastguard Worker }
6502*7c568831SAndroid Build Coastguard Worker
6503*7c568831SAndroid Build Coastguard Worker static void
xmlValidateAttributeCallback(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)6504*7c568831SAndroid Build Coastguard Worker xmlValidateAttributeCallback(void *payload, void *data,
6505*7c568831SAndroid Build Coastguard Worker const xmlChar *name ATTRIBUTE_UNUSED) {
6506*7c568831SAndroid Build Coastguard Worker xmlAttributePtr cur = (xmlAttributePtr) payload;
6507*7c568831SAndroid Build Coastguard Worker xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
6508*7c568831SAndroid Build Coastguard Worker int ret;
6509*7c568831SAndroid Build Coastguard Worker xmlDocPtr doc;
6510*7c568831SAndroid Build Coastguard Worker xmlElementPtr elem = NULL;
6511*7c568831SAndroid Build Coastguard Worker
6512*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
6513*7c568831SAndroid Build Coastguard Worker return;
6514*7c568831SAndroid Build Coastguard Worker switch (cur->atype) {
6515*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_CDATA:
6516*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ID:
6517*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREF :
6518*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREFS:
6519*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKEN:
6520*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKENS:
6521*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENUMERATION:
6522*7c568831SAndroid Build Coastguard Worker break;
6523*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITY:
6524*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITIES:
6525*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NOTATION:
6526*7c568831SAndroid Build Coastguard Worker if (cur->defaultValue != NULL) {
6527*7c568831SAndroid Build Coastguard Worker
6528*7c568831SAndroid Build Coastguard Worker ret = xmlValidateAttributeValue2(ctxt, ctxt->doc, cur->name,
6529*7c568831SAndroid Build Coastguard Worker cur->atype, cur->defaultValue);
6530*7c568831SAndroid Build Coastguard Worker if ((ret == 0) && (ctxt->valid == 1))
6531*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
6532*7c568831SAndroid Build Coastguard Worker }
6533*7c568831SAndroid Build Coastguard Worker if (cur->tree != NULL) {
6534*7c568831SAndroid Build Coastguard Worker xmlEnumerationPtr tree = cur->tree;
6535*7c568831SAndroid Build Coastguard Worker while (tree != NULL) {
6536*7c568831SAndroid Build Coastguard Worker ret = xmlValidateAttributeValue2(ctxt, ctxt->doc,
6537*7c568831SAndroid Build Coastguard Worker cur->name, cur->atype, tree->name);
6538*7c568831SAndroid Build Coastguard Worker if ((ret == 0) && (ctxt->valid == 1))
6539*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
6540*7c568831SAndroid Build Coastguard Worker tree = tree->next;
6541*7c568831SAndroid Build Coastguard Worker }
6542*7c568831SAndroid Build Coastguard Worker }
6543*7c568831SAndroid Build Coastguard Worker }
6544*7c568831SAndroid Build Coastguard Worker if (cur->atype == XML_ATTRIBUTE_NOTATION) {
6545*7c568831SAndroid Build Coastguard Worker const xmlChar *elemLocalName;
6546*7c568831SAndroid Build Coastguard Worker xmlChar *elemPrefix;
6547*7c568831SAndroid Build Coastguard Worker
6548*7c568831SAndroid Build Coastguard Worker doc = cur->doc;
6549*7c568831SAndroid Build Coastguard Worker if (cur->elem == NULL) {
6550*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
6551*7c568831SAndroid Build Coastguard Worker "xmlValidateAttributeCallback(%s): internal error\n",
6552*7c568831SAndroid Build Coastguard Worker (const char *) cur->name);
6553*7c568831SAndroid Build Coastguard Worker return;
6554*7c568831SAndroid Build Coastguard Worker }
6555*7c568831SAndroid Build Coastguard Worker
6556*7c568831SAndroid Build Coastguard Worker elemLocalName = xmlSplitQName4(cur->elem, &elemPrefix);
6557*7c568831SAndroid Build Coastguard Worker if (elemLocalName == NULL) {
6558*7c568831SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
6559*7c568831SAndroid Build Coastguard Worker return;
6560*7c568831SAndroid Build Coastguard Worker }
6561*7c568831SAndroid Build Coastguard Worker
6562*7c568831SAndroid Build Coastguard Worker if ((doc != NULL) && (doc->intSubset != NULL))
6563*7c568831SAndroid Build Coastguard Worker elem = xmlHashLookup2(doc->intSubset->elements,
6564*7c568831SAndroid Build Coastguard Worker elemLocalName, elemPrefix);
6565*7c568831SAndroid Build Coastguard Worker if ((elem == NULL) && (doc != NULL) && (doc->extSubset != NULL))
6566*7c568831SAndroid Build Coastguard Worker elem = xmlHashLookup2(doc->extSubset->elements,
6567*7c568831SAndroid Build Coastguard Worker elemLocalName, elemPrefix);
6568*7c568831SAndroid Build Coastguard Worker if ((elem == NULL) && (cur->parent != NULL) &&
6569*7c568831SAndroid Build Coastguard Worker (cur->parent->type == XML_DTD_NODE))
6570*7c568831SAndroid Build Coastguard Worker elem = xmlHashLookup2(((xmlDtdPtr) cur->parent)->elements,
6571*7c568831SAndroid Build Coastguard Worker elemLocalName, elemPrefix);
6572*7c568831SAndroid Build Coastguard Worker
6573*7c568831SAndroid Build Coastguard Worker xmlFree(elemPrefix);
6574*7c568831SAndroid Build Coastguard Worker
6575*7c568831SAndroid Build Coastguard Worker if (elem == NULL) {
6576*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, NULL, XML_DTD_UNKNOWN_ELEM,
6577*7c568831SAndroid Build Coastguard Worker "attribute %s: could not find decl for element %s\n",
6578*7c568831SAndroid Build Coastguard Worker cur->name, cur->elem, NULL);
6579*7c568831SAndroid Build Coastguard Worker return;
6580*7c568831SAndroid Build Coastguard Worker }
6581*7c568831SAndroid Build Coastguard Worker if (elem->etype == XML_ELEMENT_TYPE_EMPTY) {
6582*7c568831SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, NULL, XML_DTD_EMPTY_NOTATION,
6583*7c568831SAndroid Build Coastguard Worker "NOTATION attribute %s declared for EMPTY element %s\n",
6584*7c568831SAndroid Build Coastguard Worker cur->name, cur->elem, NULL);
6585*7c568831SAndroid Build Coastguard Worker ctxt->valid = 0;
6586*7c568831SAndroid Build Coastguard Worker }
6587*7c568831SAndroid Build Coastguard Worker }
6588*7c568831SAndroid Build Coastguard Worker }
6589*7c568831SAndroid Build Coastguard Worker
6590*7c568831SAndroid Build Coastguard Worker /**
6591*7c568831SAndroid Build Coastguard Worker * xmlValidateDtdFinal:
6592*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
6593*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
6594*7c568831SAndroid Build Coastguard Worker *
6595*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
6596*7c568831SAndroid Build Coastguard Worker *
6597*7c568831SAndroid Build Coastguard Worker * Does the final step for the dtds validation once all the
6598*7c568831SAndroid Build Coastguard Worker * subsets have been parsed
6599*7c568831SAndroid Build Coastguard Worker *
6600*7c568831SAndroid Build Coastguard Worker * basically it does the following checks described by the XML Rec
6601*7c568831SAndroid Build Coastguard Worker * - check that ENTITY and ENTITIES type attributes default or
6602*7c568831SAndroid Build Coastguard Worker * possible values matches one of the defined entities.
6603*7c568831SAndroid Build Coastguard Worker * - check that NOTATION type attributes default or
6604*7c568831SAndroid Build Coastguard Worker * possible values matches one of the defined notations.
6605*7c568831SAndroid Build Coastguard Worker *
6606*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 if invalid and -1 if not well-formed
6607*7c568831SAndroid Build Coastguard Worker */
6608*7c568831SAndroid Build Coastguard Worker
6609*7c568831SAndroid Build Coastguard Worker int
xmlValidateDtdFinal(xmlValidCtxtPtr ctxt,xmlDocPtr doc)6610*7c568831SAndroid Build Coastguard Worker xmlValidateDtdFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6611*7c568831SAndroid Build Coastguard Worker xmlDtdPtr dtd;
6612*7c568831SAndroid Build Coastguard Worker xmlAttributeTablePtr table;
6613*7c568831SAndroid Build Coastguard Worker xmlEntitiesTablePtr entities;
6614*7c568831SAndroid Build Coastguard Worker
6615*7c568831SAndroid Build Coastguard Worker if ((doc == NULL) || (ctxt == NULL)) return(0);
6616*7c568831SAndroid Build Coastguard Worker if ((doc->intSubset == NULL) && (doc->extSubset == NULL))
6617*7c568831SAndroid Build Coastguard Worker return(0);
6618*7c568831SAndroid Build Coastguard Worker ctxt->doc = doc;
6619*7c568831SAndroid Build Coastguard Worker ctxt->valid = 1;
6620*7c568831SAndroid Build Coastguard Worker dtd = doc->intSubset;
6621*7c568831SAndroid Build Coastguard Worker if ((dtd != NULL) && (dtd->attributes != NULL)) {
6622*7c568831SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) dtd->attributes;
6623*7c568831SAndroid Build Coastguard Worker xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
6624*7c568831SAndroid Build Coastguard Worker }
6625*7c568831SAndroid Build Coastguard Worker if ((dtd != NULL) && (dtd->entities != NULL)) {
6626*7c568831SAndroid Build Coastguard Worker entities = (xmlEntitiesTablePtr) dtd->entities;
6627*7c568831SAndroid Build Coastguard Worker xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
6628*7c568831SAndroid Build Coastguard Worker }
6629*7c568831SAndroid Build Coastguard Worker dtd = doc->extSubset;
6630*7c568831SAndroid Build Coastguard Worker if ((dtd != NULL) && (dtd->attributes != NULL)) {
6631*7c568831SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) dtd->attributes;
6632*7c568831SAndroid Build Coastguard Worker xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
6633*7c568831SAndroid Build Coastguard Worker }
6634*7c568831SAndroid Build Coastguard Worker if ((dtd != NULL) && (dtd->entities != NULL)) {
6635*7c568831SAndroid Build Coastguard Worker entities = (xmlEntitiesTablePtr) dtd->entities;
6636*7c568831SAndroid Build Coastguard Worker xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
6637*7c568831SAndroid Build Coastguard Worker }
6638*7c568831SAndroid Build Coastguard Worker return(ctxt->valid);
6639*7c568831SAndroid Build Coastguard Worker }
6640*7c568831SAndroid Build Coastguard Worker
6641*7c568831SAndroid Build Coastguard Worker /**
6642*7c568831SAndroid Build Coastguard Worker * xmlValidateDocument:
6643*7c568831SAndroid Build Coastguard Worker * @ctxt: the validation context
6644*7c568831SAndroid Build Coastguard Worker * @doc: a document instance
6645*7c568831SAndroid Build Coastguard Worker *
6646*7c568831SAndroid Build Coastguard Worker * Try to validate the document instance
6647*7c568831SAndroid Build Coastguard Worker *
6648*7c568831SAndroid Build Coastguard Worker * basically it does the all the checks described by the XML Rec
6649*7c568831SAndroid Build Coastguard Worker * i.e. validates the internal and external subset (if present)
6650*7c568831SAndroid Build Coastguard Worker * and validate the document tree.
6651*7c568831SAndroid Build Coastguard Worker *
6652*7c568831SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
6653*7c568831SAndroid Build Coastguard Worker */
6654*7c568831SAndroid Build Coastguard Worker
6655*7c568831SAndroid Build Coastguard Worker int
xmlValidateDocument(xmlValidCtxtPtr ctxt,xmlDocPtr doc)6656*7c568831SAndroid Build Coastguard Worker xmlValidateDocument(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6657*7c568831SAndroid Build Coastguard Worker int ret;
6658*7c568831SAndroid Build Coastguard Worker xmlNodePtr root;
6659*7c568831SAndroid Build Coastguard Worker
6660*7c568831SAndroid Build Coastguard Worker if (doc == NULL)
6661*7c568831SAndroid Build Coastguard Worker return(0);
6662*7c568831SAndroid Build Coastguard Worker if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
6663*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_NO_DTD,
6664*7c568831SAndroid Build Coastguard Worker "no DTD found!\n", NULL);
6665*7c568831SAndroid Build Coastguard Worker return(0);
6666*7c568831SAndroid Build Coastguard Worker }
6667*7c568831SAndroid Build Coastguard Worker if ((doc->intSubset != NULL) && ((doc->intSubset->SystemID != NULL) ||
6668*7c568831SAndroid Build Coastguard Worker (doc->intSubset->ExternalID != NULL)) && (doc->extSubset == NULL)) {
6669*7c568831SAndroid Build Coastguard Worker xmlChar *sysID;
6670*7c568831SAndroid Build Coastguard Worker if (doc->intSubset->SystemID != NULL) {
6671*7c568831SAndroid Build Coastguard Worker sysID = xmlBuildURI(doc->intSubset->SystemID,
6672*7c568831SAndroid Build Coastguard Worker doc->URL);
6673*7c568831SAndroid Build Coastguard Worker if (sysID == NULL) {
6674*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6675*7c568831SAndroid Build Coastguard Worker "Could not build URI for external subset \"%s\"\n",
6676*7c568831SAndroid Build Coastguard Worker (const char *) doc->intSubset->SystemID);
6677*7c568831SAndroid Build Coastguard Worker return 0;
6678*7c568831SAndroid Build Coastguard Worker }
6679*7c568831SAndroid Build Coastguard Worker } else
6680*7c568831SAndroid Build Coastguard Worker sysID = NULL;
6681*7c568831SAndroid Build Coastguard Worker doc->extSubset = xmlParseDTD(doc->intSubset->ExternalID,
6682*7c568831SAndroid Build Coastguard Worker (const xmlChar *)sysID);
6683*7c568831SAndroid Build Coastguard Worker if (sysID != NULL)
6684*7c568831SAndroid Build Coastguard Worker xmlFree(sysID);
6685*7c568831SAndroid Build Coastguard Worker if (doc->extSubset == NULL) {
6686*7c568831SAndroid Build Coastguard Worker if (doc->intSubset->SystemID != NULL) {
6687*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6688*7c568831SAndroid Build Coastguard Worker "Could not load the external subset \"%s\"\n",
6689*7c568831SAndroid Build Coastguard Worker (const char *) doc->intSubset->SystemID);
6690*7c568831SAndroid Build Coastguard Worker } else {
6691*7c568831SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6692*7c568831SAndroid Build Coastguard Worker "Could not load the external subset \"%s\"\n",
6693*7c568831SAndroid Build Coastguard Worker (const char *) doc->intSubset->ExternalID);
6694*7c568831SAndroid Build Coastguard Worker }
6695*7c568831SAndroid Build Coastguard Worker return(0);
6696*7c568831SAndroid Build Coastguard Worker }
6697*7c568831SAndroid Build Coastguard Worker }
6698*7c568831SAndroid Build Coastguard Worker
6699*7c568831SAndroid Build Coastguard Worker if (doc->ids != NULL) {
6700*7c568831SAndroid Build Coastguard Worker xmlFreeIDTable(doc->ids);
6701*7c568831SAndroid Build Coastguard Worker doc->ids = NULL;
6702*7c568831SAndroid Build Coastguard Worker }
6703*7c568831SAndroid Build Coastguard Worker if (doc->refs != NULL) {
6704*7c568831SAndroid Build Coastguard Worker xmlFreeRefTable(doc->refs);
6705*7c568831SAndroid Build Coastguard Worker doc->refs = NULL;
6706*7c568831SAndroid Build Coastguard Worker }
6707*7c568831SAndroid Build Coastguard Worker ret = xmlValidateDtdFinal(ctxt, doc);
6708*7c568831SAndroid Build Coastguard Worker if (!xmlValidateRoot(ctxt, doc)) return(0);
6709*7c568831SAndroid Build Coastguard Worker
6710*7c568831SAndroid Build Coastguard Worker root = xmlDocGetRootElement(doc);
6711*7c568831SAndroid Build Coastguard Worker ret &= xmlValidateElement(ctxt, doc, root);
6712*7c568831SAndroid Build Coastguard Worker ret &= xmlValidateDocumentFinal(ctxt, doc);
6713*7c568831SAndroid Build Coastguard Worker return(ret);
6714*7c568831SAndroid Build Coastguard Worker }
6715*7c568831SAndroid Build Coastguard Worker
6716*7c568831SAndroid Build Coastguard Worker /************************************************************************
6717*7c568831SAndroid Build Coastguard Worker * *
6718*7c568831SAndroid Build Coastguard Worker * Routines for dynamic validation editing *
6719*7c568831SAndroid Build Coastguard Worker * *
6720*7c568831SAndroid Build Coastguard Worker ************************************************************************/
6721*7c568831SAndroid Build Coastguard Worker
6722*7c568831SAndroid Build Coastguard Worker /**
6723*7c568831SAndroid Build Coastguard Worker * xmlValidGetPotentialChildren:
6724*7c568831SAndroid Build Coastguard Worker * @ctree: an element content tree
6725*7c568831SAndroid Build Coastguard Worker * @names: an array to store the list of child names
6726*7c568831SAndroid Build Coastguard Worker * @len: a pointer to the number of element in the list
6727*7c568831SAndroid Build Coastguard Worker * @max: the size of the array
6728*7c568831SAndroid Build Coastguard Worker *
6729*7c568831SAndroid Build Coastguard Worker * Build/extend a list of potential children allowed by the content tree
6730*7c568831SAndroid Build Coastguard Worker *
6731*7c568831SAndroid Build Coastguard Worker * returns the number of element in the list, or -1 in case of error.
6732*7c568831SAndroid Build Coastguard Worker */
6733*7c568831SAndroid Build Coastguard Worker
6734*7c568831SAndroid Build Coastguard Worker int
xmlValidGetPotentialChildren(xmlElementContent * ctree,const xmlChar ** names,int * len,int max)6735*7c568831SAndroid Build Coastguard Worker xmlValidGetPotentialChildren(xmlElementContent *ctree,
6736*7c568831SAndroid Build Coastguard Worker const xmlChar **names,
6737*7c568831SAndroid Build Coastguard Worker int *len, int max) {
6738*7c568831SAndroid Build Coastguard Worker int i;
6739*7c568831SAndroid Build Coastguard Worker
6740*7c568831SAndroid Build Coastguard Worker if ((ctree == NULL) || (names == NULL) || (len == NULL))
6741*7c568831SAndroid Build Coastguard Worker return(-1);
6742*7c568831SAndroid Build Coastguard Worker if (*len >= max) return(*len);
6743*7c568831SAndroid Build Coastguard Worker
6744*7c568831SAndroid Build Coastguard Worker switch (ctree->type) {
6745*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
6746*7c568831SAndroid Build Coastguard Worker for (i = 0; i < *len;i++)
6747*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(BAD_CAST "#PCDATA", names[i])) return(*len);
6748*7c568831SAndroid Build Coastguard Worker names[(*len)++] = BAD_CAST "#PCDATA";
6749*7c568831SAndroid Build Coastguard Worker break;
6750*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT:
6751*7c568831SAndroid Build Coastguard Worker for (i = 0; i < *len;i++)
6752*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(ctree->name, names[i])) return(*len);
6753*7c568831SAndroid Build Coastguard Worker names[(*len)++] = ctree->name;
6754*7c568831SAndroid Build Coastguard Worker break;
6755*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
6756*7c568831SAndroid Build Coastguard Worker xmlValidGetPotentialChildren(ctree->c1, names, len, max);
6757*7c568831SAndroid Build Coastguard Worker xmlValidGetPotentialChildren(ctree->c2, names, len, max);
6758*7c568831SAndroid Build Coastguard Worker break;
6759*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
6760*7c568831SAndroid Build Coastguard Worker xmlValidGetPotentialChildren(ctree->c1, names, len, max);
6761*7c568831SAndroid Build Coastguard Worker xmlValidGetPotentialChildren(ctree->c2, names, len, max);
6762*7c568831SAndroid Build Coastguard Worker break;
6763*7c568831SAndroid Build Coastguard Worker }
6764*7c568831SAndroid Build Coastguard Worker
6765*7c568831SAndroid Build Coastguard Worker return(*len);
6766*7c568831SAndroid Build Coastguard Worker }
6767*7c568831SAndroid Build Coastguard Worker
6768*7c568831SAndroid Build Coastguard Worker /*
6769*7c568831SAndroid Build Coastguard Worker * Dummy function to suppress messages while we try out valid elements
6770*7c568831SAndroid Build Coastguard Worker */
xmlNoValidityErr(void * ctx ATTRIBUTE_UNUSED,const char * msg ATTRIBUTE_UNUSED,...)6771*7c568831SAndroid Build Coastguard Worker static void xmlNoValidityErr(void *ctx ATTRIBUTE_UNUSED,
6772*7c568831SAndroid Build Coastguard Worker const char *msg ATTRIBUTE_UNUSED, ...) {
6773*7c568831SAndroid Build Coastguard Worker }
6774*7c568831SAndroid Build Coastguard Worker
6775*7c568831SAndroid Build Coastguard Worker /**
6776*7c568831SAndroid Build Coastguard Worker * xmlValidGetValidElements:
6777*7c568831SAndroid Build Coastguard Worker * @prev: an element to insert after
6778*7c568831SAndroid Build Coastguard Worker * @next: an element to insert next
6779*7c568831SAndroid Build Coastguard Worker * @names: an array to store the list of child names
6780*7c568831SAndroid Build Coastguard Worker * @max: the size of the array
6781*7c568831SAndroid Build Coastguard Worker *
6782*7c568831SAndroid Build Coastguard Worker * This function returns the list of authorized children to insert
6783*7c568831SAndroid Build Coastguard Worker * within an existing tree while respecting the validity constraints
6784*7c568831SAndroid Build Coastguard Worker * forced by the Dtd. The insertion point is defined using @prev and
6785*7c568831SAndroid Build Coastguard Worker * @next in the following ways:
6786*7c568831SAndroid Build Coastguard Worker * to insert before 'node': xmlValidGetValidElements(node->prev, node, ...
6787*7c568831SAndroid Build Coastguard Worker * to insert next 'node': xmlValidGetValidElements(node, node->next, ...
6788*7c568831SAndroid Build Coastguard Worker * to replace 'node': xmlValidGetValidElements(node->prev, node->next, ...
6789*7c568831SAndroid Build Coastguard Worker * to prepend a child to 'node': xmlValidGetValidElements(NULL, node->childs,
6790*7c568831SAndroid Build Coastguard Worker * to append a child to 'node': xmlValidGetValidElements(node->last, NULL, ...
6791*7c568831SAndroid Build Coastguard Worker *
6792*7c568831SAndroid Build Coastguard Worker * pointers to the element names are inserted at the beginning of the array
6793*7c568831SAndroid Build Coastguard Worker * and do not need to be freed.
6794*7c568831SAndroid Build Coastguard Worker *
6795*7c568831SAndroid Build Coastguard Worker * returns the number of element in the list, or -1 in case of error. If
6796*7c568831SAndroid Build Coastguard Worker * the function returns the value @max the caller is invited to grow the
6797*7c568831SAndroid Build Coastguard Worker * receiving array and retry.
6798*7c568831SAndroid Build Coastguard Worker */
6799*7c568831SAndroid Build Coastguard Worker
6800*7c568831SAndroid Build Coastguard Worker int
xmlValidGetValidElements(xmlNode * prev,xmlNode * next,const xmlChar ** names,int max)6801*7c568831SAndroid Build Coastguard Worker xmlValidGetValidElements(xmlNode *prev, xmlNode *next, const xmlChar **names,
6802*7c568831SAndroid Build Coastguard Worker int max) {
6803*7c568831SAndroid Build Coastguard Worker xmlValidCtxt vctxt;
6804*7c568831SAndroid Build Coastguard Worker int nb_valid_elements = 0;
6805*7c568831SAndroid Build Coastguard Worker const xmlChar *elements[256]={0};
6806*7c568831SAndroid Build Coastguard Worker int nb_elements = 0, i;
6807*7c568831SAndroid Build Coastguard Worker const xmlChar *name;
6808*7c568831SAndroid Build Coastguard Worker
6809*7c568831SAndroid Build Coastguard Worker xmlNode *ref_node;
6810*7c568831SAndroid Build Coastguard Worker xmlNode *parent;
6811*7c568831SAndroid Build Coastguard Worker xmlNode *test_node;
6812*7c568831SAndroid Build Coastguard Worker
6813*7c568831SAndroid Build Coastguard Worker xmlNode *prev_next;
6814*7c568831SAndroid Build Coastguard Worker xmlNode *next_prev;
6815*7c568831SAndroid Build Coastguard Worker xmlNode *parent_childs;
6816*7c568831SAndroid Build Coastguard Worker xmlNode *parent_last;
6817*7c568831SAndroid Build Coastguard Worker
6818*7c568831SAndroid Build Coastguard Worker xmlElement *element_desc;
6819*7c568831SAndroid Build Coastguard Worker
6820*7c568831SAndroid Build Coastguard Worker if (prev == NULL && next == NULL)
6821*7c568831SAndroid Build Coastguard Worker return(-1);
6822*7c568831SAndroid Build Coastguard Worker
6823*7c568831SAndroid Build Coastguard Worker if (names == NULL) return(-1);
6824*7c568831SAndroid Build Coastguard Worker if (max <= 0) return(-1);
6825*7c568831SAndroid Build Coastguard Worker
6826*7c568831SAndroid Build Coastguard Worker memset(&vctxt, 0, sizeof (xmlValidCtxt));
6827*7c568831SAndroid Build Coastguard Worker vctxt.error = xmlNoValidityErr; /* this suppresses err/warn output */
6828*7c568831SAndroid Build Coastguard Worker
6829*7c568831SAndroid Build Coastguard Worker nb_valid_elements = 0;
6830*7c568831SAndroid Build Coastguard Worker ref_node = prev ? prev : next;
6831*7c568831SAndroid Build Coastguard Worker parent = ref_node->parent;
6832*7c568831SAndroid Build Coastguard Worker
6833*7c568831SAndroid Build Coastguard Worker /*
6834*7c568831SAndroid Build Coastguard Worker * Retrieves the parent element declaration
6835*7c568831SAndroid Build Coastguard Worker */
6836*7c568831SAndroid Build Coastguard Worker element_desc = xmlGetDtdElementDesc(parent->doc->intSubset,
6837*7c568831SAndroid Build Coastguard Worker parent->name);
6838*7c568831SAndroid Build Coastguard Worker if ((element_desc == NULL) && (parent->doc->extSubset != NULL))
6839*7c568831SAndroid Build Coastguard Worker element_desc = xmlGetDtdElementDesc(parent->doc->extSubset,
6840*7c568831SAndroid Build Coastguard Worker parent->name);
6841*7c568831SAndroid Build Coastguard Worker if (element_desc == NULL) return(-1);
6842*7c568831SAndroid Build Coastguard Worker
6843*7c568831SAndroid Build Coastguard Worker /*
6844*7c568831SAndroid Build Coastguard Worker * Do a backup of the current tree structure
6845*7c568831SAndroid Build Coastguard Worker */
6846*7c568831SAndroid Build Coastguard Worker prev_next = prev ? prev->next : NULL;
6847*7c568831SAndroid Build Coastguard Worker next_prev = next ? next->prev : NULL;
6848*7c568831SAndroid Build Coastguard Worker parent_childs = parent->children;
6849*7c568831SAndroid Build Coastguard Worker parent_last = parent->last;
6850*7c568831SAndroid Build Coastguard Worker
6851*7c568831SAndroid Build Coastguard Worker /*
6852*7c568831SAndroid Build Coastguard Worker * Creates a dummy node and insert it into the tree
6853*7c568831SAndroid Build Coastguard Worker */
6854*7c568831SAndroid Build Coastguard Worker test_node = xmlNewDocNode (ref_node->doc, NULL, BAD_CAST "<!dummy?>", NULL);
6855*7c568831SAndroid Build Coastguard Worker if (test_node == NULL)
6856*7c568831SAndroid Build Coastguard Worker return(-1);
6857*7c568831SAndroid Build Coastguard Worker
6858*7c568831SAndroid Build Coastguard Worker test_node->parent = parent;
6859*7c568831SAndroid Build Coastguard Worker test_node->prev = prev;
6860*7c568831SAndroid Build Coastguard Worker test_node->next = next;
6861*7c568831SAndroid Build Coastguard Worker name = test_node->name;
6862*7c568831SAndroid Build Coastguard Worker
6863*7c568831SAndroid Build Coastguard Worker if (prev) prev->next = test_node;
6864*7c568831SAndroid Build Coastguard Worker else parent->children = test_node;
6865*7c568831SAndroid Build Coastguard Worker
6866*7c568831SAndroid Build Coastguard Worker if (next) next->prev = test_node;
6867*7c568831SAndroid Build Coastguard Worker else parent->last = test_node;
6868*7c568831SAndroid Build Coastguard Worker
6869*7c568831SAndroid Build Coastguard Worker /*
6870*7c568831SAndroid Build Coastguard Worker * Insert each potential child node and check if the parent is
6871*7c568831SAndroid Build Coastguard Worker * still valid
6872*7c568831SAndroid Build Coastguard Worker */
6873*7c568831SAndroid Build Coastguard Worker nb_elements = xmlValidGetPotentialChildren(element_desc->content,
6874*7c568831SAndroid Build Coastguard Worker elements, &nb_elements, 256);
6875*7c568831SAndroid Build Coastguard Worker
6876*7c568831SAndroid Build Coastguard Worker for (i = 0;i < nb_elements;i++) {
6877*7c568831SAndroid Build Coastguard Worker test_node->name = elements[i];
6878*7c568831SAndroid Build Coastguard Worker if (xmlValidateOneElement(&vctxt, parent->doc, parent)) {
6879*7c568831SAndroid Build Coastguard Worker int j;
6880*7c568831SAndroid Build Coastguard Worker
6881*7c568831SAndroid Build Coastguard Worker for (j = 0; j < nb_valid_elements;j++)
6882*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(elements[i], names[j])) break;
6883*7c568831SAndroid Build Coastguard Worker names[nb_valid_elements++] = elements[i];
6884*7c568831SAndroid Build Coastguard Worker if (nb_valid_elements >= max) break;
6885*7c568831SAndroid Build Coastguard Worker }
6886*7c568831SAndroid Build Coastguard Worker }
6887*7c568831SAndroid Build Coastguard Worker
6888*7c568831SAndroid Build Coastguard Worker /*
6889*7c568831SAndroid Build Coastguard Worker * Restore the tree structure
6890*7c568831SAndroid Build Coastguard Worker */
6891*7c568831SAndroid Build Coastguard Worker if (prev) prev->next = prev_next;
6892*7c568831SAndroid Build Coastguard Worker if (next) next->prev = next_prev;
6893*7c568831SAndroid Build Coastguard Worker parent->children = parent_childs;
6894*7c568831SAndroid Build Coastguard Worker parent->last = parent_last;
6895*7c568831SAndroid Build Coastguard Worker
6896*7c568831SAndroid Build Coastguard Worker /*
6897*7c568831SAndroid Build Coastguard Worker * Free up the dummy node
6898*7c568831SAndroid Build Coastguard Worker */
6899*7c568831SAndroid Build Coastguard Worker test_node->name = name;
6900*7c568831SAndroid Build Coastguard Worker xmlFreeNode(test_node);
6901*7c568831SAndroid Build Coastguard Worker
6902*7c568831SAndroid Build Coastguard Worker return(nb_valid_elements);
6903*7c568831SAndroid Build Coastguard Worker }
6904*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
6905*7c568831SAndroid Build Coastguard Worker
6906