Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 64a784a6fd
Fetching contributors…

Cannot retrieve contributors at this time

28773 lines (27198 sloc) 820.751 kB
/*
* schemas.c : implementation of the XML Schema handling and
* schema validity checking
*
* See Copyright for the status of this software.
*
* Daniel Veillard <veillard@redhat.com>
*/
/*
* TODO:
* - when types are redefined in includes, check that all
* types in the redef list are equal
* -> need a type equality operation.
* - if we don't intend to use the schema for schemas, we
* need to validate all schema attributes (ref, type, name)
* against their types.
* - Eliminate item creation for: ??
*
* URGENT TODO:
* - For xsi-driven schema acquisition, augment the IDCs after every
* acquisition episode (xmlSchemaAugmentIDC).
*
* NOTES:
* - Elimated item creation for: <restriction>, <extension>,
* <simpleContent>, <complexContent>, <list>, <union>
*
* PROBLEMS:
* - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
* IDC XPath expression and chameleon includes: the targetNamespace is changed, so
* XPath will have trouble to resolve to this namespace, since not known.
*
*
* CONSTRAINTS:
*
* Schema Component Constraint:
* All Group Limited (cos-all-limited)
* Status: complete
* (1.2)
* In xmlSchemaGroupDefReferenceTermFixup() and
* (2)
* In xmlSchemaParseModelGroup()
* TODO: Actually this should go to component-level checks,
* but is done here due to performance. Move it to an other layer
* is schema construction via an API is implemented.
*/
#define IN_LIBXML
#include "libxml.h"
#ifdef LIBXML_SCHEMAS_ENABLED
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <libxml/hash.h>
#include <libxml/uri.h>
#include <libxml/xmlschemas.h>
#include <libxml/schemasInternals.h>
#include <libxml/xmlschemastypes.h>
#include <libxml/xmlautomata.h>
#include <libxml/xmlregexp.h>
#include <libxml/dict.h>
#include <libxml/encoding.h>
#include <libxml/xmlIO.h>
#ifdef LIBXML_PATTERN_ENABLED
#include <libxml/pattern.h>
#endif
#ifdef LIBXML_READER_ENABLED
#include <libxml/xmlreader.h>
#endif
/* #define DEBUG 1 */
/* #define DEBUG_CONTENT 1 */
/* #define DEBUG_TYPE 1 */
/* #define DEBUG_CONTENT_REGEXP 1 */
/* #define DEBUG_AUTOMATA 1 */
/* #define DEBUG_IDC */
/* #define DEBUG_IDC_NODE_TABLE */
/* #define WXS_ELEM_DECL_CONS_ENABLED */
#ifdef DEBUG_IDC
#ifndef DEBUG_IDC_NODE_TABLE
#define DEBUG_IDC_NODE_TABLE
#endif
#endif
/* #define ENABLE_PARTICLE_RESTRICTION 1 */
#define ENABLE_REDEFINE
/* #define ENABLE_NAMED_LOCALS */
/* #define ENABLE_IDC_NODE_TABLES_TEST */
#define DUMP_CONTENT_MODEL
#ifdef LIBXML_READER_ENABLED
/* #define XML_SCHEMA_READER_ENABLED */
#endif
#define UNBOUNDED (1 << 30)
#define TODO \
xmlGenericError(xmlGenericErrorContext, \
"Unimplemented block at %s:%d\n", \
__FILE__, __LINE__);
#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
/*
* The XML Schemas namespaces
*/
static const xmlChar *xmlSchemaNs = (const xmlChar *)
"http://www.w3.org/2001/XMLSchema";
static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
"http://www.w3.org/2001/XMLSchema-instance";
static const xmlChar *xmlNamespaceNs = (const xmlChar *)
"http://www.w3.org/2000/xmlns/";
/*
* Come casting macros.
*/
#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
#define PCTXT_CAST (xmlSchemaParserCtxtPtr)
#define VCTXT_CAST (xmlSchemaValidCtxtPtr)
#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
#define WXS_PTC_CAST (xmlSchemaParticlePtr)
#define WXS_TYPE_CAST (xmlSchemaTypePtr)
#define WXS_ELEM_CAST (xmlSchemaElementPtr)
#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
#define WXS_IDC_CAST (xmlSchemaIDCPtr)
#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
#define WXS_LIST_CAST (xmlSchemaItemListPtr)
/*
* Macros to query common properties of components.
*/
#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
/*
* Macros for element declarations.
*/
#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
#define WXS_SUBST_HEAD(item) (item)->refDecl
/*
* Macros for attribute declarations.
*/
#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
/*
* Macros for attribute uses.
*/
#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
/*
* Macros for attribute groups.
*/
#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
/*
* Macros for particles.
*/
#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
#define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
/*
* Macros for model groups definitions.
*/
#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
/*
* Macros for model groups.
*/
#define WXS_IS_MODEL_GROUP(i) \
(((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
((i)->type == XML_SCHEMA_TYPE_ALL))
#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
/*
* Macros for schema buckets.
*/
#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
((t) == XML_SCHEMA_SCHEMA_REDEFINE))
#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
((t) == XML_SCHEMA_SCHEMA_IMPORT))
#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
/*
* Macros for complex/simple types.
*/
#define WXS_IS_ANYTYPE(i) \
(( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
#define WXS_IS_COMPLEX(i) \
(((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
((i)->builtInType == XML_SCHEMAS_ANYTYPE))
#define WXS_IS_SIMPLE(item) \
((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
((item->type == XML_SCHEMA_TYPE_BASIC) && \
(item->builtInType != XML_SCHEMAS_ANYTYPE)))
#define WXS_IS_ANY_SIMPLE_TYPE(i) \
(((i)->type == XML_SCHEMA_TYPE_BASIC) && \
((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
#define WXS_IS_RESTRICTION(t) \
((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
#define WXS_IS_EXTENSION(t) \
((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
#define WXS_IS_TYPE_NOT_FIXED(i) \
(((i)->type != XML_SCHEMA_TYPE_BASIC) && \
(((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
#define WXS_IS_TYPE_NOT_FIXED_1(item) \
(((item)->type != XML_SCHEMA_TYPE_BASIC) && \
(((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
#define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
#define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
/*
* Macros for exclusively for complex types.
*/
#define WXS_HAS_COMPLEX_CONTENT(item) \
((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
(item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
(item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
#define WXS_HAS_SIMPLE_CONTENT(item) \
((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
(item->contentType == XML_SCHEMA_CONTENT_BASIC))
#define WXS_HAS_MIXED_CONTENT(item) \
(item->contentType == XML_SCHEMA_CONTENT_MIXED)
#define WXS_EMPTIABLE(t) \
(xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
/*
* Macros for exclusively for simple types.
*/
#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
/*
* Misc parser context macros.
*/
#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
#define WXS_HAS_BUCKETS(ctx) \
( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
#define WXS_SCHEMA(ctx) (ctx)->schema
#define WXS_ADD_LOCAL(ctx, item) \
xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
#define WXS_ADD_GLOBAL(ctx, item) \
xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
#define WXS_ADD_PENDING(ctx, item) \
xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
/*
* xmlSchemaItemList macros.
*/
#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
/*
* Misc macros.
*/
#define IS_SCHEMA(node, type) \
((node != NULL) && (node->ns != NULL) && \
(xmlStrEqual(node->name, (const xmlChar *) type)) && \
(xmlStrEqual(node->ns->href, xmlSchemaNs)))
#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
/*
* Since we put the default/fixed values into the dict, we can
* use pointer comparison for those values.
* REMOVED: (xmlStrEqual((v1), (v2)))
*/
#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
#define HFAILURE if (res == -1) goto exit_failure;
#define HERROR if (res != 0) goto exit_error;
#define HSTOP(ctx) if ((ctx)->stop) goto exit;
/*
* Some flags used for various schema constraints.
*/
#define SUBSET_RESTRICTION 1<<0
#define SUBSET_EXTENSION 1<<1
#define SUBSET_SUBSTITUTION 1<<2
#define SUBSET_LIST 1<<3
#define SUBSET_UNION 1<<4
typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
typedef struct _xmlSchemaItemList xmlSchemaItemList;
typedef xmlSchemaItemList *xmlSchemaItemListPtr;
struct _xmlSchemaItemList {
void **items; /* used for dynamic addition of schemata */
int nbItems; /* used for dynamic addition of schemata */
int sizeItems; /* used for dynamic addition of schemata */
};
#define XML_SCHEMA_CTXT_PARSER 1
#define XML_SCHEMA_CTXT_VALIDATOR 2
typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
struct _xmlSchemaAbstractCtxt {
int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
};
typedef struct _xmlSchemaBucket xmlSchemaBucket;
typedef xmlSchemaBucket *xmlSchemaBucketPtr;
#define XML_SCHEMA_SCHEMA_MAIN 0
#define XML_SCHEMA_SCHEMA_IMPORT 1
#define XML_SCHEMA_SCHEMA_INCLUDE 2
#define XML_SCHEMA_SCHEMA_REDEFINE 3
/**
* xmlSchemaSchemaRelation:
*
* Used to create a graph of schema relationships.
*/
typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
struct _xmlSchemaSchemaRelation {
xmlSchemaSchemaRelationPtr next;
int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
const xmlChar *importNamespace;
xmlSchemaBucketPtr bucket;
};
#define XML_SCHEMA_BUCKET_MARKED 1<<0
#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
struct _xmlSchemaBucket {
int type;
int flags;
const xmlChar *schemaLocation;
const xmlChar *origTargetNamespace;
const xmlChar *targetNamespace;
xmlDocPtr doc;
xmlSchemaSchemaRelationPtr relations;
int located;
int parsed;
int imported;
int preserveDoc;
xmlSchemaItemListPtr globals; /* Global components. */
xmlSchemaItemListPtr locals; /* Local components. */
};
/**
* xmlSchemaImport:
* (extends xmlSchemaBucket)
*
* Reflects a schema. Holds some information
* about the schema and its toplevel components. Duplicate
* toplevel components are not checked at this level.
*/
typedef struct _xmlSchemaImport xmlSchemaImport;
typedef xmlSchemaImport *xmlSchemaImportPtr;
struct _xmlSchemaImport {
int type; /* Main OR import OR include. */
int flags;
const xmlChar *schemaLocation; /* The URI of the schema document. */
/* For chameleon includes, @origTargetNamespace will be NULL */
const xmlChar *origTargetNamespace;
/*
* For chameleon includes, @targetNamespace will be the
* targetNamespace of the including schema.
*/
const xmlChar *targetNamespace;
xmlDocPtr doc; /* The schema node-tree. */
/* @relations will hold any included/imported/redefined schemas. */
xmlSchemaSchemaRelationPtr relations;
int located;
int parsed;
int imported;
int preserveDoc;
xmlSchemaItemListPtr globals;
xmlSchemaItemListPtr locals;
/* The imported schema. */
xmlSchemaPtr schema;
};
/*
* (extends xmlSchemaBucket)
*/
typedef struct _xmlSchemaInclude xmlSchemaInclude;
typedef xmlSchemaInclude *xmlSchemaIncludePtr;
struct _xmlSchemaInclude {
int type;
int flags;
const xmlChar *schemaLocation;
const xmlChar *origTargetNamespace;
const xmlChar *targetNamespace;
xmlDocPtr doc;
xmlSchemaSchemaRelationPtr relations;
int located;
int parsed;
int imported;
int preserveDoc;
xmlSchemaItemListPtr globals; /* Global components. */
xmlSchemaItemListPtr locals; /* Local components. */
/* The owning main or import schema bucket. */
xmlSchemaImportPtr ownerImport;
};
/**
* xmlSchemaBasicItem:
*
* The abstract base type for schema components.
*/
typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
struct _xmlSchemaBasicItem {
xmlSchemaTypeType type;
};
/**
* xmlSchemaAnnotItem:
*
* The abstract base type for annotated schema components.
* (Extends xmlSchemaBasicItem)
*/
typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
struct _xmlSchemaAnnotItem {
xmlSchemaTypeType type;
xmlSchemaAnnotPtr annot;
};
/**
* xmlSchemaTreeItem:
*
* The abstract base type for tree-like structured schema components.
* (Extends xmlSchemaAnnotItem)
*/
typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
struct _xmlSchemaTreeItem {
xmlSchemaTypeType type;
xmlSchemaAnnotPtr annot;
xmlSchemaTreeItemPtr next;
xmlSchemaTreeItemPtr children;
};
#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
/**
* xmlSchemaAttributeUsePtr:
*
* The abstract base type for tree-like structured schema components.
* (Extends xmlSchemaTreeItem)
*/
typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
struct _xmlSchemaAttributeUse {
xmlSchemaTypeType type;
xmlSchemaAnnotPtr annot;
xmlSchemaAttributeUsePtr next; /* The next attr. use. */
/*
* The attr. decl. OR a QName-ref. to an attr. decl. OR
* a QName-ref. to an attribute group definition.
*/
xmlSchemaAttributePtr attrDecl;
int flags;
xmlNodePtr node;
int occurs; /* required, optional */
const xmlChar * defValue;
xmlSchemaValPtr defVal;
};
/**
* xmlSchemaAttributeUseProhibPtr:
*
* A helper component to reflect attribute prohibitions.
* (Extends xmlSchemaBasicItem)
*/
typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
struct _xmlSchemaAttributeUseProhib {
xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
xmlNodePtr node;
const xmlChar *name;
const xmlChar *targetNamespace;
int isRef;
};
/**
* xmlSchemaRedef:
*/
typedef struct _xmlSchemaRedef xmlSchemaRedef;
typedef xmlSchemaRedef *xmlSchemaRedefPtr;
struct _xmlSchemaRedef {
xmlSchemaRedefPtr next;
xmlSchemaBasicItemPtr item; /* The redefining component. */
xmlSchemaBasicItemPtr reference; /* The referencing component. */
xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
const xmlChar *refName; /* The name of the to-be-redefined component. */
const xmlChar *refTargetNs; /* The target namespace of the
to-be-redefined comp. */
xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
};
/**
* xmlSchemaConstructionCtxt:
*/
typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
struct _xmlSchemaConstructionCtxt {
xmlSchemaPtr mainSchema; /* The main schema. */
xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
xmlDictPtr dict;
xmlSchemaItemListPtr buckets; /* List of schema buckets. */
/* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
xmlSchemaBucketPtr bucket; /* The current schema bucket */
xmlSchemaItemListPtr pending; /* All Components of all schemas that
need to be fixed. */
xmlHashTablePtr substGroups;
xmlSchemaRedefPtr redefs;
xmlSchemaRedefPtr lastRedef;
};
#define XML_SCHEMAS_PARSE_ERROR 1
#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
struct _xmlSchemaParserCtxt {
int type;
void *errCtxt; /* user specific error context */
xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
int err;
int nberrors;
xmlStructuredErrorFunc serror;
xmlSchemaConstructionCtxtPtr constructor;
int ownsConstructor; /* TODO: Move this to parser *flags*. */
/* xmlSchemaPtr topschema; */
/* xmlHashTablePtr namespaces; */
xmlSchemaPtr schema; /* The main schema in use */
int counter;
const xmlChar *URL;
xmlDocPtr doc;
int preserve; /* Whether the doc should be freed */
const char *buffer;
int size;
/*
* Used to build complex element content models
*/
xmlAutomataPtr am;
xmlAutomataStatePtr start;
xmlAutomataStatePtr end;
xmlAutomataStatePtr state;
xmlDictPtr dict; /* dictionnary for interned string names */
xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
int options;
xmlSchemaValidCtxtPtr vctxt;
int isS4S;
int isRedefine;
int xsiAssemble;
int stop; /* If the parser should stop; i.e. a critical error. */
const xmlChar *targetNamespace;
xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
xmlSchemaRedefPtr redef; /* Used for redefinitions. */
int redefCounter; /* Used for redefinitions. */
xmlSchemaItemListPtr attrProhibs;
};
/**
* xmlSchemaQNameRef:
*
* A component reference item (not a schema component)
* (Extends xmlSchemaBasicItem)
*/
typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
struct _xmlSchemaQNameRef {
xmlSchemaTypeType type;
xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
xmlSchemaTypeType itemType;
const xmlChar *name;
const xmlChar *targetNamespace;
xmlNodePtr node;
};
/**
* xmlSchemaParticle:
*
* A particle component.
* (Extends xmlSchemaTreeItem)
*/
typedef struct _xmlSchemaParticle xmlSchemaParticle;
typedef xmlSchemaParticle *xmlSchemaParticlePtr;
struct _xmlSchemaParticle {
xmlSchemaTypeType type;
xmlSchemaAnnotPtr annot;
xmlSchemaTreeItemPtr next; /* next particle */
xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
etc.) */
int minOccurs;
int maxOccurs;
xmlNodePtr node;
};
/**
* xmlSchemaModelGroup:
*
* A model group component.
* (Extends xmlSchemaTreeItem)
*/
typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
struct _xmlSchemaModelGroup {
xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
xmlSchemaAnnotPtr annot;
xmlSchemaTreeItemPtr next; /* not used */
xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
xmlNodePtr node;
};
#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
/**
* xmlSchemaModelGroupDef:
*
* A model group definition component.
* (Extends xmlSchemaTreeItem)
*/
typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
struct _xmlSchemaModelGroupDef {
xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
xmlSchemaAnnotPtr annot;
xmlSchemaTreeItemPtr next; /* not used */
xmlSchemaTreeItemPtr children; /* the "model group" */
const xmlChar *name;
const xmlChar *targetNamespace;
xmlNodePtr node;
int flags;
};
typedef struct _xmlSchemaIDC xmlSchemaIDC;
typedef xmlSchemaIDC *xmlSchemaIDCPtr;
/**
* xmlSchemaIDCSelect:
*
* The identity-constraint "field" and "selector" item, holding the
* XPath expression.
*/
typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
struct _xmlSchemaIDCSelect {
xmlSchemaIDCSelectPtr next;
xmlSchemaIDCPtr idc;
int index; /* an index position if significant for IDC key-sequences */
const xmlChar *xpath; /* the XPath expression */
void *xpathComp; /* the compiled XPath expression */
};
/**
* xmlSchemaIDC:
*
* The identity-constraint definition component.
* (Extends xmlSchemaAnnotItem)
*/
struct _xmlSchemaIDC {
xmlSchemaTypeType type;
xmlSchemaAnnotPtr annot;
xmlSchemaIDCPtr next;
xmlNodePtr node;
const xmlChar *name;
const xmlChar *targetNamespace;
xmlSchemaIDCSelectPtr selector;
xmlSchemaIDCSelectPtr fields;
int nbFields;
xmlSchemaQNameRefPtr ref;
};
/**
* xmlSchemaIDCAug:
*
* The augmented IDC information used for validation.
*/
typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
struct _xmlSchemaIDCAug {
xmlSchemaIDCAugPtr next; /* next in a list */
xmlSchemaIDCPtr def; /* the IDC definition */
int keyrefDepth; /* the lowest tree level to which IDC
tables need to be bubbled upwards */
};
/**
* xmlSchemaPSVIIDCKeySequence:
*
* The key sequence of a node table item.
*/
typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
struct _xmlSchemaPSVIIDCKey {
xmlSchemaTypePtr type;
xmlSchemaValPtr val;
};
/**
* xmlSchemaPSVIIDCNode:
*
* The node table item of a node table.
*/
typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
struct _xmlSchemaPSVIIDCNode {
xmlNodePtr node;
xmlSchemaPSVIIDCKeyPtr *keys;
int nodeLine;
int nodeQNameID;
};
/**
* xmlSchemaPSVIIDCBinding:
*
* The identity-constraint binding item of the [identity-constraint table].
*/
typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
struct _xmlSchemaPSVIIDCBinding {
xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
xmlSchemaIDCPtr definition; /* the IDC definition */
xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
int nbNodes; /* number of entries in the node table */
int sizeNodes; /* size of the node table */
xmlSchemaItemListPtr dupls;
};
#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
#define XPATH_STATE_OBJ_MATCHES -2
#define XPATH_STATE_OBJ_BLOCKED -3
typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
/**
* xmlSchemaIDCStateObj:
*
* The state object used to evaluate XPath expressions.
*/
typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
struct _xmlSchemaIDCStateObj {
int type;
xmlSchemaIDCStateObjPtr next; /* next if in a list */
int depth; /* depth of creation */
int *history; /* list of (depth, state-id) tuples */
int nbHistory;
int sizeHistory;
xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
matcher */
xmlSchemaIDCSelectPtr sel;
void *xpathCtxt;
};
#define IDC_MATCHER 0
/**
* xmlSchemaIDCMatcher:
*
* Used to evaluate IDC selectors (and fields).
*/
struct _xmlSchemaIDCMatcher {
int type;
int depth; /* the tree depth at creation time */
xmlSchemaIDCMatcherPtr next; /* next in the list */
xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
int idcType;
xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
elements */
int sizeKeySeqs;
xmlSchemaItemListPtr targets; /* list of target-node
(xmlSchemaPSVIIDCNodePtr) entries */
};
/*
* Element info flags.
*/
#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
/**
* xmlSchemaNodeInfo:
*
* Holds information of an element node.
*/
struct _xmlSchemaNodeInfo {
int nodeType;
xmlNodePtr node;
int nodeLine;
const xmlChar *localName;
const xmlChar *nsName;
const xmlChar *value;
xmlSchemaValPtr val; /* the pre-computed value if any */
xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
int flags; /* combination of node info flags */
int valNeeded;
int normVal;
xmlSchemaElementPtr decl; /* the element/attribute declaration */
int depth;
xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
for the scope element*/
xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
element */
xmlRegExecCtxtPtr regexCtxt;
const xmlChar **nsBindings; /* Namespace bindings on this element */
int nbNsBindings;
int sizeNsBindings;
int hasKeyrefs;
int appliedXPath; /* Indicates that an XPath has been applied. */
};
#define XML_SCHEMAS_ATTR_UNKNOWN 1
#define XML_SCHEMAS_ATTR_ASSESSED 2
#define XML_SCHEMAS_ATTR_PROHIBITED 3
#define XML_SCHEMAS_ATTR_ERR_MISSING 4
#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
#define XML_SCHEMAS_ATTR_DEFAULT 8
#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
#define XML_SCHEMAS_ATTR_WILD_SKIP 13
#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
#define XML_SCHEMAS_ATTR_META 17
/*
* @metaType values of xmlSchemaAttrInfo.
*/
#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
struct _xmlSchemaAttrInfo {
int nodeType;
xmlNodePtr node;
int nodeLine;
const xmlChar *localName;
const xmlChar *nsName;
const xmlChar *value;
xmlSchemaValPtr val; /* the pre-computed value if any */
xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
int flags; /* combination of node info flags */
xmlSchemaAttributePtr decl; /* the attribute declaration */
xmlSchemaAttributeUsePtr use; /* the attribute use */
int state;
int metaType;
const xmlChar *vcValue; /* the value constraint value */
xmlSchemaNodeInfoPtr parent;
};
#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
/**
* xmlSchemaValidCtxt:
*
* A Schemas validation context
*/
struct _xmlSchemaValidCtxt {
int type;
void *errCtxt; /* user specific data block */
xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
xmlStructuredErrorFunc serror;
xmlSchemaPtr schema; /* The schema in use */
xmlDocPtr doc;
xmlParserInputBufferPtr input;
xmlCharEncoding enc;
xmlSAXHandlerPtr sax;
xmlParserCtxtPtr parserCtxt;
void *user_data; /* TODO: What is this for? */
int err;
int nberrors;
xmlNodePtr node;
xmlNodePtr cur;
/* xmlSchemaTypePtr type; */
xmlRegExecCtxtPtr regexp;
xmlSchemaValPtr value;
int valueWS;
int options;
xmlNodePtr validationRoot;
xmlSchemaParserCtxtPtr pctxt;
int xsiAssemble;
int depth;
xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
int sizeElemInfos;
xmlSchemaNodeInfoPtr inode; /* the current element information */
xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
int nbIdcNodes;
int sizeIdcNodes;
xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
int nbIdcKeys;
int sizeIdcKeys;
int flags;
xmlDictPtr dict;
#ifdef LIBXML_READER_ENABLED
xmlTextReaderPtr reader;
#endif
xmlSchemaAttrInfoPtr *attrInfos;
int nbAttrInfos;
int sizeAttrInfos;
int skipDepth;
xmlSchemaItemListPtr nodeQNames;
int hasKeyrefs;
int createIDCNodeTables;
int psviExposeIDCNodeTables;
};
/**
* xmlSchemaSubstGroup:
*
*
*/
typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
struct _xmlSchemaSubstGroup {
xmlSchemaElementPtr head;
xmlSchemaItemListPtr members;
};
/************************************************************************
* *
* Some predeclarations *
* *
************************************************************************/
static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema,
xmlNodePtr node);
static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema,
xmlNodePtr node);
static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,
xmlSchemaAbstractCtxtPtr ctxt);
static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
xmlNodePtr node);
static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
xmlSchemaParserCtxtPtr ctxt);
static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
xmlNodePtr node, xmlSchemaTypeType type,
int withParticle);
static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
static void
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
const char *funcName,
const char *message);
static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
xmlSchemaTypePtr type,
xmlSchemaTypePtr baseType,
int subset);
static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
xmlSchemaParserCtxtPtr ctxt);
static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
xmlSchemaPtr schema,
xmlNodePtr node);
/************************************************************************
* *
* Helper functions *
* *
************************************************************************/
/**
* xmlSchemaItemTypeToStr:
* @type: the type of the schema item
*
* Returns the component name of a schema item.
*/
static const xmlChar *
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
{
switch (type) {
case XML_SCHEMA_TYPE_BASIC:
return(BAD_CAST "simple type definition");
case XML_SCHEMA_TYPE_SIMPLE:
return(BAD_CAST "simple type definition");
case XML_SCHEMA_TYPE_COMPLEX:
return(BAD_CAST "complex type definition");
case XML_SCHEMA_TYPE_ELEMENT:
return(BAD_CAST "element declaration");
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
return(BAD_CAST "attribute use");
case XML_SCHEMA_TYPE_ATTRIBUTE:
return(BAD_CAST "attribute declaration");
case XML_SCHEMA_TYPE_GROUP:
return(BAD_CAST "model group definition");
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
return(BAD_CAST "attribute group definition");
case XML_SCHEMA_TYPE_NOTATION:
return(BAD_CAST "notation declaration");
case XML_SCHEMA_TYPE_SEQUENCE:
return(BAD_CAST "model group (sequence)");
case XML_SCHEMA_TYPE_CHOICE:
return(BAD_CAST "model group (choice)");
case XML_SCHEMA_TYPE_ALL:
return(BAD_CAST "model group (all)");
case XML_SCHEMA_TYPE_PARTICLE:
return(BAD_CAST "particle");
case XML_SCHEMA_TYPE_IDC_UNIQUE:
return(BAD_CAST "unique identity-constraint");
/* return(BAD_CAST "IDC (unique)"); */
case XML_SCHEMA_TYPE_IDC_KEY:
return(BAD_CAST "key identity-constraint");
/* return(BAD_CAST "IDC (key)"); */
case XML_SCHEMA_TYPE_IDC_KEYREF:
return(BAD_CAST "keyref identity-constraint");
/* return(BAD_CAST "IDC (keyref)"); */
case XML_SCHEMA_TYPE_ANY:
return(BAD_CAST "wildcard (any)");
case XML_SCHEMA_EXTRA_QNAMEREF:
return(BAD_CAST "[helper component] QName reference");
case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
return(BAD_CAST "[helper component] attribute use prohibition");
default:
return(BAD_CAST "Not a schema component");
}
}
/**
* xmlSchemaGetComponentTypeStr:
* @type: the type of the schema item
*
* Returns the component name of a schema item.
*/
static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
{
switch (item->type) {
case XML_SCHEMA_TYPE_BASIC:
if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
return(BAD_CAST "complex type definition");
else
return(BAD_CAST "simple type definition");
default:
return(xmlSchemaItemTypeToStr(item->type));
}
}
/**
* xmlSchemaGetComponentNode:
* @item: a schema component
*
* Returns node associated with the schema component.
* NOTE that such a node need not be available; plus, a component's
* node need not to reflect the component directly, since there is no
* one-to-one relationship between the XML Schema representation and
* the component representation.
*/
static xmlNodePtr
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
{
switch (item->type) {
case XML_SCHEMA_TYPE_ELEMENT:
return (((xmlSchemaElementPtr) item)->node);
case XML_SCHEMA_TYPE_ATTRIBUTE:
return (((xmlSchemaAttributePtr) item)->node);
case XML_SCHEMA_TYPE_COMPLEX:
case XML_SCHEMA_TYPE_SIMPLE:
return (((xmlSchemaTypePtr) item)->node);
case XML_SCHEMA_TYPE_ANY:
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
return (((xmlSchemaWildcardPtr) item)->node);
case XML_SCHEMA_TYPE_PARTICLE:
return (((xmlSchemaParticlePtr) item)->node);
case XML_SCHEMA_TYPE_SEQUENCE:
case XML_SCHEMA_TYPE_CHOICE:
case XML_SCHEMA_TYPE_ALL:
return (((xmlSchemaModelGroupPtr) item)->node);
case XML_SCHEMA_TYPE_GROUP:
return (((xmlSchemaModelGroupDefPtr) item)->node);
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
return (((xmlSchemaAttributeGroupPtr) item)->node);
case XML_SCHEMA_TYPE_IDC_UNIQUE:
case XML_SCHEMA_TYPE_IDC_KEY:
case XML_SCHEMA_TYPE_IDC_KEYREF:
return (((xmlSchemaIDCPtr) item)->node);
case XML_SCHEMA_EXTRA_QNAMEREF:
return(((xmlSchemaQNameRefPtr) item)->node);
/* TODO: What to do with NOTATIONs?
case XML_SCHEMA_TYPE_NOTATION:
return (((xmlSchemaNotationPtr) item)->node);
*/
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
return (((xmlSchemaAttributeUsePtr) item)->node);
default:
return (NULL);
}
}
#if 0
/**
* xmlSchemaGetNextComponent:
* @item: a schema component
*
* Returns the next sibling of the schema component.
*/
static xmlSchemaBasicItemPtr
xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
{
switch (item->type) {
case XML_SCHEMA_TYPE_ELEMENT:
return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
case XML_SCHEMA_TYPE_ATTRIBUTE:
return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
case XML_SCHEMA_TYPE_COMPLEX:
case XML_SCHEMA_TYPE_SIMPLE:
return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
case XML_SCHEMA_TYPE_ANY:
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
return (NULL);
case XML_SCHEMA_TYPE_PARTICLE:
return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
case XML_SCHEMA_TYPE_SEQUENCE:
case XML_SCHEMA_TYPE_CHOICE:
case XML_SCHEMA_TYPE_ALL:
return (NULL);
case XML_SCHEMA_TYPE_GROUP:
return (NULL);
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
case XML_SCHEMA_TYPE_IDC_UNIQUE:
case XML_SCHEMA_TYPE_IDC_KEY:
case XML_SCHEMA_TYPE_IDC_KEYREF:
return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
default:
return (NULL);
}
}
#endif
/**
* xmlSchemaFormatQName:
* @buf: the string buffer
* @namespaceName: the namespace name
* @localName: the local name
*
* Returns the given QName in the format "{namespaceName}localName" or
* just "localName" if @namespaceName is NULL.
*
* Returns the localName if @namespaceName is NULL, a formatted
* string otherwise.
*/
static const xmlChar*
xmlSchemaFormatQName(xmlChar **buf,
const xmlChar *namespaceName,
const xmlChar *localName)
{
FREE_AND_NULL(*buf)
if (namespaceName != NULL) {
*buf = xmlStrdup(BAD_CAST "{");
*buf = xmlStrcat(*buf, namespaceName);
*buf = xmlStrcat(*buf, BAD_CAST "}");
}
if (localName != NULL) {
if (namespaceName == NULL)
return(localName);
*buf = xmlStrcat(*buf, localName);
} else {
*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
}
return ((const xmlChar *) *buf);
}
static const xmlChar*
xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
{
if (ns != NULL)
return (xmlSchemaFormatQName(buf, ns->href, localName));
else
return (xmlSchemaFormatQName(buf, NULL, localName));
}
static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
{
switch (item->type) {
case XML_SCHEMA_TYPE_ELEMENT:
return (((xmlSchemaElementPtr) item)->name);
case XML_SCHEMA_TYPE_ATTRIBUTE:
return (((xmlSchemaAttributePtr) item)->name);
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
return (((xmlSchemaAttributeGroupPtr) item)->name);
case XML_SCHEMA_TYPE_BASIC:
case XML_SCHEMA_TYPE_SIMPLE:
case XML_SCHEMA_TYPE_COMPLEX:
return (((xmlSchemaTypePtr) item)->name);
case XML_SCHEMA_TYPE_GROUP:
return (((xmlSchemaModelGroupDefPtr) item)->name);
case XML_SCHEMA_TYPE_IDC_KEY:
case XML_SCHEMA_TYPE_IDC_UNIQUE:
case XML_SCHEMA_TYPE_IDC_KEYREF:
return (((xmlSchemaIDCPtr) item)->name);
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
if (WXS_ATTRUSE_DECL(item) != NULL) {
return(xmlSchemaGetComponentName(
WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
} else
return(NULL);
case XML_SCHEMA_EXTRA_QNAMEREF:
return (((xmlSchemaQNameRefPtr) item)->name);
case XML_SCHEMA_TYPE_NOTATION:
return (((xmlSchemaNotationPtr) item)->name);
default:
/*
* Other components cannot have names.
*/
break;
}
return (NULL);
}
#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
/*
static const xmlChar *
xmlSchemaGetQNameRefName(void *ref)
{
return(((xmlSchemaQNameRefPtr) ref)->name);
}
static const xmlChar *
xmlSchemaGetQNameRefTargetNs(void *ref)
{
return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
}
*/
static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
{
switch (item->type) {
case XML_SCHEMA_TYPE_ELEMENT:
return (((xmlSchemaElementPtr) item)->targetNamespace);
case XML_SCHEMA_TYPE_ATTRIBUTE:
return (((xmlSchemaAttributePtr) item)->targetNamespace);
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
case XML_SCHEMA_TYPE_BASIC:
return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
case XML_SCHEMA_TYPE_SIMPLE:
case XML_SCHEMA_TYPE_COMPLEX:
return (((xmlSchemaTypePtr) item)->targetNamespace);
case XML_SCHEMA_TYPE_GROUP:
return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
case XML_SCHEMA_TYPE_IDC_KEY:
case XML_SCHEMA_TYPE_IDC_UNIQUE:
case XML_SCHEMA_TYPE_IDC_KEYREF:
return (((xmlSchemaIDCPtr) item)->targetNamespace);
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
if (WXS_ATTRUSE_DECL(item) != NULL) {
return(xmlSchemaGetComponentTargetNs(
WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
}
/* TODO: Will returning NULL break something? */
break;
case XML_SCHEMA_EXTRA_QNAMEREF:
return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
case XML_SCHEMA_TYPE_NOTATION:
return (((xmlSchemaNotationPtr) item)->targetNamespace);
default:
/*
* Other components cannot have names.
*/
break;
}
return (NULL);
}
static const xmlChar*
xmlSchemaGetComponentQName(xmlChar **buf,
void *item)
{
return (xmlSchemaFormatQName(buf,
xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
}
static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
{
xmlChar *str = NULL;
*buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
*buf = xmlStrcat(*buf, BAD_CAST " '");
*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
(xmlSchemaBasicItemPtr) item));
*buf = xmlStrcat(*buf, BAD_CAST "'");
FREE_AND_NULL(str);
return(*buf);
}
static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
{
return(xmlSchemaGetComponentDesignation(buf, idc));
}
/**
* xmlSchemaWildcardPCToString:
* @pc: the type of processContents
*
* Returns a string representation of the type of
* processContents.
*/
static const xmlChar *
xmlSchemaWildcardPCToString(int pc)
{
switch (pc) {
case XML_SCHEMAS_ANY_SKIP:
return (BAD_CAST "skip");
case XML_SCHEMAS_ANY_LAX:
return (BAD_CAST "lax");
case XML_SCHEMAS_ANY_STRICT:
return (BAD_CAST "strict");
default:
return (BAD_CAST "invalid process contents");
}
}
/**
* xmlSchemaGetCanonValueWhtspExt:
* @val: the precomputed value
* @retValue: the returned value
* @ws: the whitespace type of the value
*
* Get a the cononical representation of the value.
* The caller has to free the returned retValue.
*
* Returns 0 if the value could be built and -1 in case of
* API errors or if the value type is not supported yet.
*/
static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
xmlSchemaWhitespaceValueType ws,
xmlChar **retValue)
{
int list;
xmlSchemaValType valType;
const xmlChar *value, *value2 = NULL;
if ((retValue == NULL) || (val == NULL))
return (-1);
list = xmlSchemaValueGetNext(val) ? 1 : 0;
*retValue = NULL;
do {
value = NULL;
valType = xmlSchemaGetValType(val);
switch (valType) {
case XML_SCHEMAS_STRING:
case XML_SCHEMAS_NORMSTRING:
case XML_SCHEMAS_ANYSIMPLETYPE:
value = xmlSchemaValueGetAsString(val);
if (value != NULL) {
if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
value2 = xmlSchemaCollapseString(value);
else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
value2 = xmlSchemaWhiteSpaceReplace(value);
if (value2 != NULL)
value = value2;
}
break;
default:
if (xmlSchemaGetCanonValue(val, &value2) == -1) {
if (value2 != NULL)
xmlFree((xmlChar *) value2);
goto internal_error;
}
value = value2;
}
if (*retValue == NULL)
if (value == NULL) {
if (! list)
*retValue = xmlStrdup(BAD_CAST "");
} else
*retValue = xmlStrdup(value);
else if (value != NULL) {
/* List. */
*retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
*retValue = xmlStrcat((xmlChar *) *retValue, value);
}
FREE_AND_NULL(value2)
val = xmlSchemaValueGetNext(val);
} while (val != NULL);
return (0);
internal_error:
if (*retValue != NULL)
xmlFree((xmlChar *) (*retValue));
if (value2 != NULL)
xmlFree((xmlChar *) value2);
return (-1);
}
/**
* xmlSchemaFormatItemForReport:
* @buf: the string buffer
* @itemDes: the designation of the item
* @itemName: the name of the item
* @item: the item as an object
* @itemNode: the node of the item
* @local: the local name
* @parsing: if the function is used during the parse
*
* Returns a representation of the given item used
* for error reports.
*
* The following order is used to build the resulting
* designation if the arguments are not NULL:
* 1a. If itemDes not NULL -> itemDes
* 1b. If (itemDes not NULL) and (itemName not NULL)
* -> itemDes + itemName
* 2. If the preceding was NULL and (item not NULL) -> item
* 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
*
* If the itemNode is an attribute node, the name of the attribute
* will be appended to the result.
*
* Returns the formatted string and sets @buf to the resulting value.
*/
static xmlChar*
xmlSchemaFormatItemForReport(xmlChar **buf,
const xmlChar *itemDes,
xmlSchemaBasicItemPtr item,
xmlNodePtr itemNode)
{
xmlChar *str = NULL;
int named = 1;
if (*buf != NULL) {
xmlFree(*buf);
*buf = NULL;
}
if (itemDes != NULL) {
*buf = xmlStrdup(itemDes);
} else if (item != NULL) {
switch (item->type) {
case XML_SCHEMA_TYPE_BASIC: {
xmlSchemaTypePtr type = WXS_TYPE_CAST item;
if (WXS_IS_ATOMIC(type))
*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
else if (WXS_IS_LIST(type))
*buf = xmlStrdup(BAD_CAST "list type 'xs:");
else if (WXS_IS_UNION(type))
*buf = xmlStrdup(BAD_CAST "union type 'xs:");
else
*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
*buf = xmlStrcat(*buf, type->name);
*buf = xmlStrcat(*buf, BAD_CAST "'");
}
break;
case XML_SCHEMA_TYPE_SIMPLE: {
xmlSchemaTypePtr type = WXS_TYPE_CAST item;
if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
*buf = xmlStrdup(BAD_CAST"");
} else {
*buf = xmlStrdup(BAD_CAST "local ");
}
if (WXS_IS_ATOMIC(type))
*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
else if (WXS_IS_LIST(type))
*buf = xmlStrcat(*buf, BAD_CAST "list type");
else if (WXS_IS_UNION(type))
*buf = xmlStrcat(*buf, BAD_CAST "union type");
else
*buf = xmlStrcat(*buf, BAD_CAST "simple type");
if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
*buf = xmlStrcat(*buf, BAD_CAST " '");
*buf = xmlStrcat(*buf, type->name);
*buf = xmlStrcat(*buf, BAD_CAST "'");
}
}
break;
case XML_SCHEMA_TYPE_COMPLEX: {
xmlSchemaTypePtr type = WXS_TYPE_CAST item;
if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
*buf = xmlStrdup(BAD_CAST "");
else
*buf = xmlStrdup(BAD_CAST "local ");
*buf = xmlStrcat(*buf, BAD_CAST "complex type");
if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
*buf = xmlStrcat(*buf, BAD_CAST " '");
*buf = xmlStrcat(*buf, type->name);
*buf = xmlStrcat(*buf, BAD_CAST "'");
}
}
break;
case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
xmlSchemaAttributeUsePtr ause;
ause = WXS_ATTR_USE_CAST item;
*buf = xmlStrdup(BAD_CAST "attribute use ");
if (WXS_ATTRUSE_DECL(ause) != NULL) {
*buf = xmlStrcat(*buf, BAD_CAST "'");
*buf = xmlStrcat(*buf,
xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
FREE_AND_NULL(str)
*buf = xmlStrcat(*buf, BAD_CAST "'");
} else {
*buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
}
}
break;
case XML_SCHEMA_TYPE_ATTRIBUTE: {
xmlSchemaAttributePtr attr;
attr = (xmlSchemaAttributePtr) item;
*buf = xmlStrdup(BAD_CAST "attribute decl.");
*buf = xmlStrcat(*buf, BAD_CAST " '");
*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
attr->targetNamespace, attr->name));
FREE_AND_NULL(str)
*buf = xmlStrcat(*buf, BAD_CAST "'");
}
break;
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
xmlSchemaGetComponentDesignation(buf, item);
break;
case XML_SCHEMA_TYPE_ELEMENT: {
xmlSchemaElementPtr elem;
elem = (xmlSchemaElementPtr) item;
*buf = xmlStrdup(BAD_CAST "element decl.");
*buf = xmlStrcat(*buf, BAD_CAST " '");
*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
elem->targetNamespace, elem->name));
*buf = xmlStrcat(*buf, BAD_CAST "'");
}
break;
case XML_SCHEMA_TYPE_IDC_UNIQUE:
case XML_SCHEMA_TYPE_IDC_KEY:
case XML_SCHEMA_TYPE_IDC_KEYREF:
if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
*buf = xmlStrdup(BAD_CAST "unique '");
else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
*buf = xmlStrdup(BAD_CAST "key '");
else
*buf = xmlStrdup(BAD_CAST "keyRef '");
*buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
*buf = xmlStrcat(*buf, BAD_CAST "'");
break;
case XML_SCHEMA_TYPE_ANY:
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
*buf = xmlStrdup(xmlSchemaWildcardPCToString(
((xmlSchemaWildcardPtr) item)->processContents));
*buf = xmlStrcat(*buf, BAD_CAST " wildcard");
break;
case XML_SCHEMA_FACET_MININCLUSIVE:
case XML_SCHEMA_FACET_MINEXCLUSIVE:
case XML_SCHEMA_FACET_MAXINCLUSIVE:
case XML_SCHEMA_FACET_MAXEXCLUSIVE:
case XML_SCHEMA_FACET_TOTALDIGITS:
case XML_SCHEMA_FACET_FRACTIONDIGITS:
case XML_SCHEMA_FACET_PATTERN:
case XML_SCHEMA_FACET_ENUMERATION:
case XML_SCHEMA_FACET_WHITESPACE:
case XML_SCHEMA_FACET_LENGTH:
case XML_SCHEMA_FACET_MAXLENGTH:
case XML_SCHEMA_FACET_MINLENGTH:
*buf = xmlStrdup(BAD_CAST "facet '");
*buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
*buf = xmlStrcat(*buf, BAD_CAST "'");
break;
case XML_SCHEMA_TYPE_GROUP: {
*buf = xmlStrdup(BAD_CAST "model group def.");
*buf = xmlStrcat(*buf, BAD_CAST " '");
*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
*buf = xmlStrcat(*buf, BAD_CAST "'");
FREE_AND_NULL(str)
}
break;
case XML_SCHEMA_TYPE_SEQUENCE:
case XML_SCHEMA_TYPE_CHOICE:
case XML_SCHEMA_TYPE_ALL:
case XML_SCHEMA_TYPE_PARTICLE:
*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
break;
case XML_SCHEMA_TYPE_NOTATION: {
*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
*buf = xmlStrcat(*buf, BAD_CAST " '");
*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
*buf = xmlStrcat(*buf, BAD_CAST "'");
FREE_AND_NULL(str);
}
default:
named = 0;
}
} else
named = 0;
if ((named == 0) && (itemNode != NULL)) {
xmlNodePtr elem;
if (itemNode->type == XML_ATTRIBUTE_NODE)
elem = itemNode->parent;
else
elem = itemNode;
*buf = xmlStrdup(BAD_CAST "Element '");
if (elem->ns != NULL) {
*buf = xmlStrcat(*buf,
xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
FREE_AND_NULL(str)
} else
*buf = xmlStrcat(*buf, elem->name);
*buf = xmlStrcat(*buf, BAD_CAST "'");
}
if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
if (itemNode->ns != NULL) {
*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
itemNode->ns->href, itemNode->name));
FREE_AND_NULL(str)
} else
*buf = xmlStrcat(*buf, itemNode->name);
*buf = xmlStrcat(*buf, BAD_CAST "'");
}
FREE_AND_NULL(str)
return (*buf);
}
/**
* xmlSchemaFormatFacetEnumSet:
* @buf: the string buffer
* @type: the type holding the enumeration facets
*
* Builds a string consisting of all enumeration elements.
*
* Returns a string of all enumeration elements.
*/
static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
xmlChar **buf, xmlSchemaTypePtr type)
{
xmlSchemaFacetPtr facet;
xmlSchemaWhitespaceValueType ws;
xmlChar *value = NULL;
int res, found = 0;
if (*buf != NULL)
xmlFree(*buf);
*buf = NULL;
do {
/*
* Use the whitespace type of the base type.
*/
ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
for (facet = type->facets; facet != NULL; facet = facet->next) {
if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
continue;
found = 1;
res = xmlSchemaGetCanonValueWhtspExt(facet->val,
ws, &value);
if (res == -1) {
xmlSchemaInternalErr(actxt,
"xmlSchemaFormatFacetEnumSet",
"compute the canonical lexical representation");
if (*buf != NULL)
xmlFree(*buf);
*buf = NULL;
return (NULL);
}
if (*buf == NULL)
*buf = xmlStrdup(BAD_CAST "'");
else
*buf = xmlStrcat(*buf, BAD_CAST ", '");
*buf = xmlStrcat(*buf, BAD_CAST value);
*buf = xmlStrcat(*buf, BAD_CAST "'");
if (value != NULL) {
xmlFree((xmlChar *)value);
value = NULL;
}
}
/*
* The enumeration facet of a type restricts the enumeration
* facet of the ancestor type; i.e., such restricted enumerations
* do not belong to the set of the given type. Thus we break
* on the first found enumeration.
*/
if (found)
break;
type = type->baseType;
} while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
return ((const xmlChar *) *buf);
}
/************************************************************************
* *
* Error functions *
* *
************************************************************************/
#if 0
static void
xmlSchemaErrMemory(const char *msg)
{
__xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
msg);
}
#endif
static void
xmlSchemaPSimpleErr(const char *msg)
{
__xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
msg);
}
/**
* xmlSchemaPErrMemory:
* @node: a context node
* @extra: extra informations
*
* Handle an out of memory condition
*/
static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
const char *extra, xmlNodePtr node)
{
if (ctxt != NULL)
ctxt->nberrors++;
__xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
extra);
}
/**
* xmlSchemaPErr:
* @ctxt: the parsing context
* @node: the context node
* @error: the error code
* @msg: the error message
* @str1: extra data
* @str2: extra data
*
* Handle a parser error
*/
static void
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
const char *msg, const xmlChar * str1, const xmlChar * str2)
{
xmlGenericErrorFunc channel = NULL;
xmlStructuredErrorFunc schannel = NULL;
void *data = NULL;
if (ctxt != NULL) {
ctxt->nberrors++;
ctxt->err = error;
channel = ctxt->error;
data = ctxt->errCtxt;
schannel = ctxt->serror;
}
__xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
error, XML_ERR_ERROR, NULL, 0,
(const char *) str1, (const char *) str2, NULL, 0, 0,
msg, str1, str2);
}
/**
* xmlSchemaPErr2:
* @ctxt: the parsing context
* @node: the context node
* @node: the current child
* @error: the error code
* @msg: the error message
* @str1: extra data
* @str2: extra data
*
* Handle a parser error
*/
static void
xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
xmlNodePtr child, int error,
const char *msg, const xmlChar * str1, const xmlChar * str2)
{
if (child != NULL)
xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
else
xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
}
/**
* xmlSchemaPErrExt:
* @ctxt: the parsing context
* @node: the context node
* @error: the error code
* @strData1: extra data
* @strData2: extra data
* @strData3: extra data
* @msg: the message
* @str1: extra parameter for the message display
* @str2: extra parameter for the message display
* @str3: extra parameter for the message display
* @str4: extra parameter for the message display
* @str5: extra parameter for the message display
*
* Handle a parser error
*/
static void
xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
const xmlChar * strData1, const xmlChar * strData2,
const xmlChar * strData3, const char *msg, const xmlChar * str1,
const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
const xmlChar * str5)
{
xmlGenericErrorFunc channel = NULL;
xmlStructuredErrorFunc schannel = NULL;
void *data = NULL;
if (ctxt != NULL) {
ctxt->nberrors++;
ctxt->err = error;
channel = ctxt->error;
data = ctxt->errCtxt;
schannel = ctxt->serror;
}
__xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
error, XML_ERR_ERROR, NULL, 0,
(const char *) strData1, (const char *) strData2,
(const char *) strData3, 0, 0, msg, str1, str2,
str3, str4, str5);
}
/************************************************************************
* *
* Allround error functions *
* *
************************************************************************/
/**
* xmlSchemaVTypeErrMemory:
* @node: a context node
* @extra: extra informations
*
* Handle an out of memory condition
*/
static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
const char *extra, xmlNodePtr node)
{
if (ctxt != NULL) {
ctxt->nberrors++;
ctxt->err = XML_SCHEMAV_INTERNAL;
}
__xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
extra);
}
static void
xmlSchemaPSimpleInternalErr(xmlNodePtr node,
const char *msg, const xmlChar *str)
{
__xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
msg, (const char *) str);
}
#define WXS_ERROR_TYPE_ERROR 1
#define WXS_ERROR_TYPE_WARNING 2
/**
* xmlSchemaErr3:
* @ctxt: the validation context
* @node: the context node
* @error: the error code
* @msg: the error message
* @str1: extra data
* @str2: extra data
* @str3: extra data
*
* Handle a validation error
*/
static void
xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
xmlErrorLevel errorLevel,
int error, xmlNodePtr node, int line, const char *msg,
const xmlChar *str1, const xmlChar *str2,
const xmlChar *str3, const xmlChar *str4)
{
xmlStructuredErrorFunc schannel = NULL;
xmlGenericErrorFunc channel = NULL;
void *data = NULL;
if (ctxt != NULL) {
if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
const char *file = NULL;
if (errorLevel != XML_ERR_WARNING) {
vctxt->nberrors++;
vctxt->err = error;
channel = vctxt->error;
} else {
channel = vctxt->warning;
}
schannel = vctxt->serror;
data = vctxt->errCtxt;
/*
* Error node. If we specify a line number, then
* do not channel any node to the error function.
*/
if (line == 0) {
if ((node == NULL) &&
(vctxt->depth >= 0) &&
(vctxt->inode != NULL)) {
node = vctxt->inode->node;
}
/*
* Get filename and line if no node-tree.
*/
if ((node == NULL) &&
(vctxt->parserCtxt != NULL) &&
(vctxt->parserCtxt->input != NULL)) {
file = vctxt->parserCtxt->input->filename;
line = vctxt->parserCtxt->input->line;
}
} else {
/*
* Override the given node's (if any) position
* and channel only the given line number.
*/
node = NULL;
/*
* Get filename.
*/
if (vctxt->doc != NULL)
file = (const char *) vctxt->doc->URL;
else if ((vctxt->parserCtxt != NULL) &&
(vctxt->parserCtxt->input != NULL))
file = vctxt->parserCtxt->input->filename;
}
__xmlRaiseError(schannel, channel, data, ctxt,
node, XML_FROM_SCHEMASV,
error, errorLevel, file, line,
(const char *) str1, (const char *) str2,
(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
if (errorLevel != XML_ERR_WARNING) {
pctxt->nberrors++;
pctxt->err = error;
channel = pctxt->error;
} else {
channel = pctxt->warning;
}
schannel = pctxt->serror;
data = pctxt->errCtxt;
__xmlRaiseError(schannel, channel, data, ctxt,
node, XML_FROM_SCHEMASP, error,
errorLevel, NULL, 0,
(const char *) str1, (const char *) str2,
(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
} else {
TODO
}
}
}
/**
* xmlSchemaErr3:
* @ctxt: the validation context
* @node: the context node
* @error: the error code
* @msg: the error message
* @str1: extra data
* @str2: extra data
* @str3: extra data
*
* Handle a validation error
*/
static void
xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
int error, xmlNodePtr node, const char *msg,
const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
{
xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
msg, str1, str2, str3, NULL);
}
static void
xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
int error, xmlNodePtr node, const char *msg,
const xmlChar *str1, const xmlChar *str2,
const xmlChar *str3, const xmlChar *str4)
{
xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
msg, str1, str2, str3, str4);
}
static void
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
int error, xmlNodePtr node, const char *msg,
const xmlChar *str1, const xmlChar *str2)
{
xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
}
static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,
xmlSchemaAbstractCtxtPtr actxt,
xmlNodePtr node)
{
xmlChar *str = NULL;
*msg = NULL;
if ((node != NULL) &&
(node->type != XML_ELEMENT_NODE) &&
(node->type != XML_ATTRIBUTE_NODE))
{
/*
* Don't try to format other nodes than element and
* attribute nodes.
* Play save and return an empty string.
*/
*msg = xmlStrdup(BAD_CAST "");
return(*msg);
}
if (node != NULL) {
/*
* Work on tree nodes.
*/
if (node->type == XML_ATTRIBUTE_NODE) {
xmlNodePtr elem = node->parent;
*msg = xmlStrdup(BAD_CAST "Element '");
if (elem->ns != NULL)
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
elem->ns->href, elem->name));
else
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
NULL, elem->name));
FREE_AND_NULL(str);
*msg = xmlStrcat(*msg, BAD_CAST "', ");
*msg = xmlStrcat(*msg, BAD_CAST "attribute '");
} else {
*msg = xmlStrdup(BAD_CAST "Element '");
}
if (node->ns != NULL)
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
node->ns->href, node->name));
else
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
NULL, node->name));
FREE_AND_NULL(str);
*msg = xmlStrcat(*msg, BAD_CAST "': ");
} else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
/*
* Work on node infos.
*/
if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
xmlSchemaNodeInfoPtr ielem =
vctxt->elemInfos[vctxt->depth];
*msg = xmlStrdup(BAD_CAST "Element '");
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
ielem->nsName, ielem->localName));
FREE_AND_NULL(str);
*msg = xmlStrcat(*msg, BAD_CAST "', ");
*msg = xmlStrcat(*msg, BAD_CAST "attribute '");
} else {
*msg = xmlStrdup(BAD_CAST "Element '");
}
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
vctxt->inode->nsName, vctxt->inode->localName));
FREE_AND_NULL(str);
*msg = xmlStrcat(*msg, BAD_CAST "': ");
} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
/*
* Hmm, no node while parsing?
* Return an empty string, in case NULL will break something.
*/
*msg = xmlStrdup(BAD_CAST "");
} else {
TODO
return (NULL);
}
/*
* VAL TODO: The output of the given schema component is currently
* disabled.
*/
#if 0
if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
*msg = xmlStrcat(*msg, BAD_CAST " [");
*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
NULL, type, NULL, 0));
FREE_AND_NULL(str)
*msg = xmlStrcat(*msg, BAD_CAST "]");
}
#endif
return (*msg);
}
static void
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
const char *funcName,
const char *message,
const xmlChar *str1,
const xmlChar *str2)
{
xmlChar *msg = NULL;
if (actxt == NULL)
return;
msg = xmlStrdup(BAD_CAST "Internal error: ");
msg = xmlStrcat(msg, BAD_CAST funcName);
msg = xmlStrcat(msg, BAD_CAST ", ");
msg = xmlStrcat(msg, BAD_CAST message);
msg = xmlStrcat(msg, BAD_CAST ".\n");
if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
(const char *) msg, str1, str2);
else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
(const char *) msg, str1, str2);
FREE_AND_NULL(msg)
}
static void
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
const char *funcName,
const char *message)
{
xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
}
#if 0
static void
xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
const char *funcName,
const char *message,
const xmlChar *str1,
const xmlChar *str2)
{
xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
str1, str2);
}
#endif
static void
xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
xmlSchemaBasicItemPtr item,
const char *message,
const xmlChar *str1, const xmlChar *str2,
const xmlChar *str3, const xmlChar *str4)
{
xmlChar *msg = NULL;
if ((node == NULL) && (item != NULL) &&
(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
node = WXS_ITEM_NODE(item);
xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
msg = xmlStrcat(msg, BAD_CAST ": ");
} else
xmlSchemaFormatNodeForError(&msg, actxt, node);
msg = xmlStrcat(msg, (const xmlChar *) message);
msg = xmlStrcat(msg, BAD_CAST ".\n");
xmlSchemaErr4(actxt, error, node,
(const char *) msg, str1, str2, str3, str4);
FREE_AND_NULL(msg)
}
static void
xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
xmlSchemaBasicItemPtr item,
const char *message,
const xmlChar *str1,
const xmlChar *str2)
{
xmlSchemaCustomErr4(actxt, error, node, item,
message, str1, str2, NULL, NULL);
}
static void
xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
const char *message,
const xmlChar *str1,
const xmlChar *str2,
const xmlChar *str3)
{
xmlChar *msg = NULL;
xmlSchemaFormatNodeForError(&msg, actxt, node);
msg = xmlStrcat(msg, (const xmlChar *) message);
msg = xmlStrcat(msg, BAD_CAST ".\n");
/* URGENT TODO: Set the error code to something sane. */
xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
(const char *) msg, str1, str2, str3, NULL);
FREE_AND_NULL(msg)
}
static void
xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
xmlParserErrors error,
xmlSchemaPSVIIDCNodePtr idcNode,
xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
const char *message,
const xmlChar *str1,
const xmlChar *str2)
{
xmlChar *msg = NULL, *qname = NULL;
msg = xmlStrdup(BAD_CAST "Element '%s': ");
msg = xmlStrcat(msg, (const xmlChar *) message);
msg = xmlStrcat(msg, BAD_CAST ".\n");
xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
error, NULL, idcNode->nodeLine, (const char *) msg,
xmlSchemaFormatQName(&qname,
vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
vctxt->nodeQNames->items[idcNode->nodeQNameID]),
str1, str2, NULL);
FREE_AND_NULL(qname);
FREE_AND_NULL(msg);
}
static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
xmlNodePtr node)
{
if (node != NULL)
return (node->type);
if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
return (-1);
}
static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
{
switch (item->type) {
case XML_SCHEMA_TYPE_COMPLEX:
case XML_SCHEMA_TYPE_SIMPLE:
if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
return(1);
break;
case XML_SCHEMA_TYPE_GROUP:
return (1);
case XML_SCHEMA_TYPE_ELEMENT:
if ( ((xmlSchemaElementPtr) item)->flags &
XML_SCHEMAS_ELEM_GLOBAL)
return(1);
break;
case XML_SCHEMA_TYPE_ATTRIBUTE:
if ( ((xmlSchemaAttributePtr) item)->flags &
XML_SCHEMAS_ATTR_GLOBAL)
return(1);
break;
/* Note that attribute groups are always global. */
default:
return(1);
}
return (0);
}
static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
const xmlChar *value,
xmlSchemaTypePtr type,
int displayValue)
{
xmlChar *msg = NULL;
xmlSchemaFormatNodeForError(&msg, actxt, node);
if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
XML_ATTRIBUTE_NODE))
msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
else
msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
"value of ");
if (! xmlSchemaIsGlobalItem(type))
msg = xmlStrcat(msg, BAD_CAST "the local ");
else
msg = xmlStrcat(msg, BAD_CAST "the ");
if (WXS_IS_ATOMIC(type))
msg = xmlStrcat(msg, BAD_CAST "atomic type");
else if (WXS_IS_LIST(type))
msg = xmlStrcat(msg, BAD_CAST "list type");
else if (WXS_IS_UNION(type))
msg = xmlStrcat(msg, BAD_CAST "union type");
if (xmlSchemaIsGlobalItem(type)) {
xmlChar *str = NULL;
msg = xmlStrcat(msg, BAD_CAST " '");
if (type->builtInType != 0) {
msg = xmlStrcat(msg, BAD_CAST "xs:");
msg = xmlStrcat(msg, type->name);
} else
msg = xmlStrcat(msg,
xmlSchemaFormatQName(&str,
type->targetNamespace, type->name));
msg = xmlStrcat(msg, BAD_CAST "'");
FREE_AND_NULL(str);
}
msg = xmlStrcat(msg, BAD_CAST ".\n");
if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
XML_ATTRIBUTE_NODE))
xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
else
xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
FREE_AND_NULL(msg)
}
static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,
xmlSchemaNodeInfoPtr ni,
xmlNodePtr node)
{
if (node != NULL) {
if (node->ns != NULL)
return (xmlSchemaFormatQName(str, node->ns->href, node->name));
else
return (xmlSchemaFormatQName(str, NULL, node->name));
} else if (ni != NULL)
return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
return (NULL);
}
static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlSchemaAttrInfoPtr ni,
xmlNodePtr node)
{
xmlChar *msg = NULL, *str = NULL;
xmlSchemaFormatNodeForError(&msg, actxt, node);
msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
xmlSchemaErr(actxt, error, node, (const char *) msg,
xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
NULL);
FREE_AND_NULL(str)
FREE_AND_NULL(msg)
}
static void
xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
const char *message,
int nbval,
int nbneg,
xmlChar **values)
{
xmlChar *str = NULL, *msg = NULL;
xmlChar *localName, *nsName;
const xmlChar *cur, *end;
int i;
xmlSchemaFormatNodeForError(&msg, actxt, node);
msg = xmlStrcat(msg, (const xmlChar *) message);
msg = xmlStrcat(msg, BAD_CAST ".");
/*
* Note that is does not make sense to report that we have a
* wildcard here, since the wildcard might be unfolded into
* multiple transitions.
*/
if (nbval + nbneg > 0) {
if (nbval + nbneg > 1) {
str = xmlStrdup(BAD_CAST " Expected is one of ( ");
} else
str = xmlStrdup(BAD_CAST " Expected is ( ");
nsName = NULL;
for (i = 0; i < nbval + nbneg; i++) {
cur = values[i];
if (cur == NULL)
continue;
if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
(cur[3] == ' ')) {
cur += 4;
str = xmlStrcat(str, BAD_CAST "##other");
}
/*
* Get the local name.
*/
localName = NULL;
end = cur;
if (*end == '*') {
localName = xmlStrdup(BAD_CAST "*");
end++;
} else {
while ((*end != 0) && (*end != '|'))
end++;
localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
}
if (*end != 0) {
end++;
/*
* Skip "*|*" if they come with negated expressions, since
* they represent the same negated wildcard.
*/
if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
/*
* Get the namespace name.
*/
cur = end;
if (*end == '*') {
nsName = xmlStrdup(BAD_CAST "{*}");
} else {
while (*end != 0)
end++;
if (i >= nbval)
nsName = xmlStrdup(BAD_CAST "{##other:");
else
nsName = xmlStrdup(BAD_CAST "{");
nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
nsName = xmlStrcat(nsName, BAD_CAST "}");
}
str = xmlStrcat(str, BAD_CAST nsName);
FREE_AND_NULL(nsName)
} else {
FREE_AND_NULL(localName);
continue;
}
}
str = xmlStrcat(str, BAD_CAST localName);
FREE_AND_NULL(localName);
if (i < nbval + nbneg -1)
str = xmlStrcat(str, BAD_CAST ", ");
}
str = xmlStrcat(str, BAD_CAST " ).\n");
msg = xmlStrcat(msg, BAD_CAST str);
FREE_AND_NULL(str)
} else
msg = xmlStrcat(msg, BAD_CAST "\n");
xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
xmlFree(msg);
}
static void
xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
const xmlChar *value,
unsigned long length,
xmlSchemaTypePtr type,
xmlSchemaFacetPtr facet,
const char *message,
const xmlChar *str1,
const xmlChar *str2)
{
xmlChar *str = NULL, *msg = NULL;
xmlSchemaTypeType facetType;
int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
xmlSchemaFormatNodeForError(&msg, actxt, node);
if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
facetType = XML_SCHEMA_FACET_ENUMERATION;
/*
* If enumerations are validated, one must not expect the
* facet to be given.
*/
} else
facetType = facet->type;
msg = xmlStrcat(msg, BAD_CAST "[");
msg = xmlStrcat(msg, BAD_CAST "facet '");
msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
msg = xmlStrcat(msg, BAD_CAST "'] ");
if (message == NULL) {
/*
* Use a default message.
*/
if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
(facetType == XML_SCHEMA_FACET_MINLENGTH) ||
(facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
char len[25], actLen[25];
/* FIXME, TODO: What is the max expected string length of the
* this value?
*/
if (nodeType == XML_ATTRIBUTE_NODE)
msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
else
msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
snprintf(actLen, 24, "%lu", length);
if (facetType == XML_SCHEMA_FACET_LENGTH)
msg = xmlStrcat(msg,
BAD_CAST "this differs from the allowed length of '%s'.\n");
else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
msg = xmlStrcat(msg,
BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
msg = xmlStrcat(msg,
BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
if (nodeType == XML_ATTRIBUTE_NODE)
xmlSchemaErr3(actxt, error, node, (const char *) msg,
value, (const xmlChar *) actLen, (const xmlChar *) len);
else
xmlSchemaErr(actxt, error, node, (const char *) msg,
(const xmlChar *) actLen, (const xmlChar *) len);
} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
"of the set {%s}.\n");
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
xmlSchemaFormatFacetEnumSet(actxt, &str, type));
} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
"by the pattern '%s'.\n");
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
facet->value);
} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
"minimum value allowed ('%s').\n");
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
facet->value);
} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
"maximum value allowed ('%s').\n");
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
facet->value);
} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
"'%s'.\n");
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
facet->value);
} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
"'%s'.\n");
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
facet->value);
} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
"digits than are allowed ('%s').\n");
xmlSchemaErr(actxt, error, node, (const char*) msg, value,
facet->value);
} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
"digits than are allowed ('%s').\n");
xmlSchemaErr(actxt, error, node, (const char*) msg, value,
facet->value);
} else if (nodeType == XML_ATTRIBUTE_NODE) {
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
} else {
msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
}
} else {
msg = xmlStrcat(msg, (const xmlChar *) message);
msg = xmlStrcat(msg, BAD_CAST ".\n");
xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
}
FREE_AND_NULL(str)
xmlFree(msg);
}
#define VERROR(err, type, msg) \
xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
/**
* xmlSchemaPMissingAttrErr:
* @ctxt: the schema validation context
* @ownerDes: the designation of the owner
* @ownerName: the name of the owner
* @ownerItem: the owner as a schema object
* @ownerElem: the owner as an element node
* @node: the parent element node of the missing attribute node
* @type: the corresponding type of the attribute node
*
* Reports an illegal attribute.
*/
static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr ownerItem,
xmlNodePtr ownerElem,
const char *name,
const char *message)
{
xmlChar *des = NULL;
xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
if (message != NULL)
xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
else
xmlSchemaPErr(ctxt, ownerElem, error,
"%s: The attribute '%s' is required but missing.\n",
BAD_CAST des, BAD_CAST name);
FREE_AND_NULL(des);
}
/**
* xmlSchemaPResCompAttrErr:
* @ctxt: the schema validation context
* @error: the error code
* @ownerDes: the designation of the owner
* @ownerItem: the owner as a schema object
* @ownerElem: the owner as an element node
* @name: the name of the attribute holding the QName
* @refName: the referenced local name
* @refURI: the referenced namespace URI
* @message: optional message
*
* Used to report QName attribute values that failed to resolve
* to schema components.
*/
static void
xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr ownerItem,
xmlNodePtr ownerElem,
const char *name,
const xmlChar *refName,
const xmlChar *refURI,
xmlSchemaTypeType refType,
const char *refTypeStr)
{
xmlChar *des = NULL, *strA = NULL;
xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
if (refTypeStr == NULL)
refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
xmlSchemaPErrExt(ctxt, ownerElem, error,
NULL, NULL, NULL,
"%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
"%s.\n", BAD_CAST des, BAD_CAST name,
xmlSchemaFormatQName(&strA, refURI, refName),
BAD_CAST refTypeStr, NULL);
FREE_AND_NULL(des)
FREE_AND_NULL(strA)
}
/**
* xmlSchemaPCustomAttrErr:
* @ctxt: the schema parser context
* @error: the error code
* @ownerDes: the designation of the owner
* @ownerItem: the owner as a schema object
* @attr: the illegal attribute node
*
* Reports an illegal attribute during the parse.
*/
static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlChar **ownerDes,
xmlSchemaBasicItemPtr ownerItem,
xmlAttrPtr attr,
const char *msg)
{
xmlChar *des = NULL;
if (ownerDes == NULL)
xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
else if (*ownerDes == NULL) {
xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
des = *ownerDes;
} else
des = *ownerDes;
if (attr == NULL) {
xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
"%s, attribute '%s': %s.\n",
BAD_CAST des, (const xmlChar *) "Unknown",
(const xmlChar *) msg, NULL, NULL);
} else {
xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
"%s, attribute '%s': %s.\n",
BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
}
if (ownerDes == NULL)
FREE_AND_NULL(des);
}
/**
* xmlSchemaPIllegalAttrErr:
* @ctxt: the schema parser context
* @error: the error code
* @ownerDes: the designation of the attribute's owner
* @ownerItem: the attribute's owner item
* @attr: the illegal attribute node
*
* Reports an illegal attribute during the parse.
*/
static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
xmlAttrPtr attr)
{
xmlChar *strA = NULL, *strB = NULL;
xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
NULL, NULL);
FREE_AND_NULL(strA);
FREE_AND_NULL(strB);
}
/**
* xmlSchemaPCustomErr:
* @ctxt: the schema parser context
* @error: the error code
* @itemDes: the designation of the schema item
* @item: the schema item
* @itemElem: the node of the schema item
* @message: the error message
* @str1: an optional param for the error message
* @str2: an optional param for the error message
* @str3: an optional param for the error message
*
* Reports an error during parsing.
*/
static void
xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr item,
xmlNodePtr itemElem,
const char *message,
const xmlChar *str1,
const xmlChar *str2,
const xmlChar *str3)
{
xmlChar *des = NULL, *msg = NULL;
xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
msg = xmlStrdup(BAD_CAST "%s: ");
msg = xmlStrcat(msg, (const xmlChar *) message);
msg = xmlStrcat(msg, BAD_CAST ".\n");
if ((itemElem == NULL) && (item != NULL))
itemElem = WXS_ITEM_NODE(item);
xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
FREE_AND_NULL(des);
FREE_AND_NULL(msg);
}
/**
* xmlSchemaPCustomErr:
* @ctxt: the schema parser context
* @error: the error code
* @itemDes: the designation of the schema item
* @item: the schema item
* @itemElem: the node of the schema item
* @message: the error message
* @str1: the optional param for the error message
*
* Reports an error during parsing.
*/
static void
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr item,
xmlNodePtr itemElem,
const char *message,
const xmlChar *str1)
{
xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
str1, NULL, NULL);
}
/**
* xmlSchemaPAttrUseErr:
* @ctxt: the schema parser context
* @error: the error code
* @itemDes: the designation of the schema type
* @item: the schema type
* @itemElem: the node of the schema type
* @attr: the invalid schema attribute
* @message: the error message
* @str1: the optional param for the error message
*
* Reports an attribute use error during parsing.
*/
static void
xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlNodePtr node,
xmlSchemaBasicItemPtr ownerItem,
const xmlSchemaAttributeUsePtr attruse,
const char *message,
const xmlChar *str1, const xmlChar *str2,
const xmlChar *str3,const xmlChar *str4)
{
xmlChar *str = NULL, *msg = NULL;
xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
msg = xmlStrcat(msg, BAD_CAST ", ");
msg = xmlStrcat(msg,
BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
WXS_BASIC_CAST attruse, NULL));
FREE_AND_NULL(str);
msg = xmlStrcat(msg, BAD_CAST ": ");
msg = xmlStrcat(msg, (const xmlChar *) message);
msg = xmlStrcat(msg, BAD_CAST ".\n");
xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
(const char *) msg, str1, str2, str3, str4);
xmlFree(msg);
}
/**
* xmlSchemaPIllegalFacetAtomicErr:
* @ctxt: the schema parser context
* @error: the error code
* @type: the schema type
* @baseType: the base type of type
* @facet: the illegal facet
*
* Reports an illegal facet for atomic simple types.
*/
static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaTypePtr type,
xmlSchemaTypePtr baseType,
xmlSchemaFacetPtr facet)
{
xmlChar *des = NULL, *strT = NULL;
xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
"%s: The facet '%s' is not allowed on types derived from the "
"type %s.\n",
BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
NULL, NULL);
FREE_AND_NULL(des);
FREE_AND_NULL(strT);
}
/**
* xmlSchemaPIllegalFacetListUnionErr:
* @ctxt: the schema parser context
* @error: the error code
* @itemDes: the designation of the schema item involved
* @item: the schema item involved
* @facet: the illegal facet
*
* Reports an illegal facet for <list> and <union>.
*/
static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaTypePtr type,
xmlSchemaFacetPtr facet)
{
xmlChar *des = NULL;
xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
type->node);
xmlSchemaPErr(ctxt, type->node, error,
"%s: The facet '%s' is not allowed.\n",
BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
FREE_AND_NULL(des);
}
/**
* xmlSchemaPMutualExclAttrErr:
* @ctxt: the schema validation context
* @error: the error code
* @elemDes: the designation of the parent element node
* @attr: the bad attribute node
* @type: the corresponding type of the attribute node
*
* Reports an illegal attribute.
*/
static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr ownerItem,
xmlAttrPtr attr,
const char *name1,
const char *name2)
{
xmlChar *des = NULL;
xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
FREE_AND_NULL(des);
}
/**
* xmlSchemaPSimpleTypeErr:
* @ctxt: the schema validation context
* @error: the error code
* @type: the type specifier
* @ownerDes: the designation of the owner
* @ownerItem: the schema object if existent
* @node: the validated node
* @value: the validated value
*
* Reports a simple type validation error.
* TODO: Should this report the value of an element as well?
*/
static void
xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
xmlNodePtr node,
xmlSchemaTypePtr type,
const char *expected,
const xmlChar *value,
const char *message,
const xmlChar *str1,
const xmlChar *str2)
{
xmlChar *msg = NULL;
xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
if (message == NULL) {
/*
* Use default messages.
*/
if (type != NULL) {
if (node->type == XML_ATTRIBUTE_NODE)
msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
else
msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
"valid value of ");
if (! xmlSchemaIsGlobalItem(type))
msg = xmlStrcat(msg, BAD_CAST "the local ");
else
msg = xmlStrcat(msg, BAD_CAST "the ");
if (WXS_IS_ATOMIC(type))
msg = xmlStrcat(msg, BAD_CAST "atomic type");
else if (WXS_IS_LIST(type))
msg = xmlStrcat(msg, BAD_CAST "list type");
else if (WXS_IS_UNION(type))
msg = xmlStrcat(msg, BAD_CAST "union type");
if (xmlSchemaIsGlobalItem(type)) {
xmlChar *str = NULL;
msg = xmlStrcat(msg, BAD_CAST " '");
if (type->builtInType != 0) {
msg = xmlStrcat(msg, BAD_CAST "xs:");
msg = xmlStrcat(msg, type->name);
} else
msg = xmlStrcat(msg,
xmlSchemaFormatQName(&str,
type->targetNamespace, type->name));
msg = xmlStrcat(msg, BAD_CAST "'.");
FREE_AND_NULL(str);
}
} else {
if (node->type == XML_ATTRIBUTE_NODE)
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
else
msg = xmlStrcat(msg, BAD_CAST "The character content is not "
"valid.");
}
if (expected) {
msg = xmlStrcat(msg, BAD_CAST " Expected is '");
msg = xmlStrcat(msg, BAD_CAST expected);
msg = xmlStrcat(msg, BAD_CAST "'.\n");
} else
msg = xmlStrcat(msg, BAD_CAST "\n");
if (node->type == XML_ATTRIBUTE_NODE)
xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
else
xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
} else {
msg = xmlStrcat(msg, BAD_CAST message);
msg = xmlStrcat(msg, BAD_CAST ".\n");
xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
(const char*) msg, str1, str2, NULL, NULL, NULL);
}
/* Cleanup. */
FREE_AND_NULL(msg)
}
/**
* xmlSchemaPContentErr:
* @ctxt: the schema parser context
* @error: the error code
* @onwerDes: the designation of the holder of the content
* @ownerItem: the owner item of the holder of the content
* @ownerElem: the node of the holder of the content
* @child: the invalid child node
* @message: the optional error message
* @content: the optional string describing the correct content
*
* Reports an error concerning the content of a schema element.
*/
static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr ownerItem,
xmlNodePtr ownerElem,
xmlNodePtr child,
const char *message,
const char *content)
{
xmlChar *des = NULL;
xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
if (message != NULL)
xmlSchemaPErr2(ctxt, ownerElem, child, error,
"%s: %s.\n",
BAD_CAST des, BAD_CAST message);
else {
if (content != NULL) {
xmlSchemaPErr2(ctxt, ownerElem, child, error,
"%s: The content is not valid. Expected is %s.\n",
BAD_CAST des, BAD_CAST content);
} else {
xmlSchemaPErr2(ctxt, ownerElem, child, error,
"%s: The content is not valid.\n",
BAD_CAST des, NULL);
}
}
FREE_AND_NULL(des)
}
/************************************************************************
* *
* Streamable error functions *
* *
************************************************************************/
/************************************************************************
* *
* Validation helper functions *
* *
************************************************************************/
/************************************************************************
* *
* Allocation functions *
* *
************************************************************************/
/**
* xmlSchemaNewSchemaForParserCtxt:
* @ctxt: a schema validation context
*
* Allocate a new Schema structure.
*
* Returns the newly allocated structure or NULL in case or error
*/
static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
{
xmlSchemaPtr ret;
ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
if (ret == NULL) {
xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchema));
ret->dict = ctxt->dict;
xmlDictReference(ret->dict);
return (ret);
}
/**
* xmlSchemaNewFacet:
*
* Allocate a new Facet structure.
*
* Returns the newly allocated structure or NULL in case or error
*/
xmlSchemaFacetPtr
xmlSchemaNewFacet(void)
{
xmlSchemaFacetPtr ret;
ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
if (ret == NULL) {
return (NULL);
}
memset(ret, 0, sizeof(xmlSchemaFacet));
return (ret);
}
/**
* xmlSchemaNewAnnot:
* @ctxt: a schema validation context
* @node: a node
*
* Allocate a new annotation structure.
*
* Returns the newly allocated structure or NULL in case or error
*/
static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
{
xmlSchemaAnnotPtr ret;
ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
if (ret == NULL) {
xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchemaAnnot));
ret->content = node;
return (ret);
}
static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)
{
xmlSchemaItemListPtr ret;
ret = xmlMalloc(sizeof(xmlSchemaItemList));
if (ret == NULL) {
xmlSchemaPErrMemory(NULL,
"allocating an item list structure", NULL);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchemaItemList));
return (ret);
}
static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)
{
if (list->items != NULL) {
xmlFree(list->items);
list->items = NULL;
}
list->nbItems = 0;
list->sizeItems = 0;
}
static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
{
if (list->items == NULL) {
list->items = (void **) xmlMalloc(
20 * sizeof(void *));
if (list->items == NULL) {
xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
return(-1);
}
list->sizeItems = 20;
} else if (list->sizeItems <= list->nbItems) {
list->sizeItems *= 2;
list->items = (void **) xmlRealloc(list->items,
list->sizeItems * sizeof(void *));
if (list->items == NULL) {
xmlSchemaPErrMemory(NULL, "growing item list", NULL);
list->sizeItems = 0;
return(-1);
}
}
list->items[list->nbItems++] = item;
return(0);
}
static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
int initialSize,
void *item)
{
if (list->items == NULL) {
if (initialSize <= 0)
initialSize = 1;
list->items = (void **) xmlMalloc(
initialSize * sizeof(void *));
if (list->items == NULL) {
xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
return(-1);
}
list->sizeItems = initialSize;
} else if (list->sizeItems <= list->nbItems) {
list->sizeItems *= 2;
list->items = (void **) xmlRealloc(list->items,
list->sizeItems * sizeof(void *));
if (list->items == NULL) {
xmlSchemaPErrMemory(NULL, "growing item list", NULL);
list->sizeItems = 0;
return(-1);
}
}
list->items[list->nbItems++] = item;
return(0);
}
static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
{
if (list->items == NULL) {
list->items = (void **) xmlMalloc(
20 * sizeof(void *));
if (list->items == NULL) {
xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
return(-1);
}
list->sizeItems = 20;
} else if (list->sizeItems <= list->nbItems) {
list->sizeItems *= 2;
list->items = (void **) xmlRealloc(list->items,
list->sizeItems * sizeof(void *));
if (list->items == NULL) {
xmlSchemaPErrMemory(NULL, "growing item list", NULL);
list->sizeItems = 0;
return(-1);
}
}
/*
* Just append if the index is greater/equal than the item count.
*/
if (idx >= list->nbItems) {
list->items[list->nbItems++] = item;
} else {
int i;
for (i = list->nbItems; i > idx; i--)
list->items[i] = list->items[i-1];
list->items[idx] = item;
list->nbItems++;
}
return(0);
}
#if 0 /* enable if ever needed */
static int
xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
int initialSize,
void *item,
int idx)
{
if (list->items == NULL) {
if (initialSize <= 0)
initialSize = 1;
list->items = (void **) xmlMalloc(
initialSize * sizeof(void *));
if (list->items == NULL) {
xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
return(-1);
}
list->sizeItems = initialSize;
} else if (list->sizeItems <= list->nbItems) {
list->sizeItems *= 2;
list->items = (void **) xmlRealloc(list->items,
list->sizeItems * sizeof(void *));
if (list->items == NULL) {
xmlSchemaPErrMemory(NULL, "growing item list", NULL);
list->sizeItems = 0;
return(-1);
}
}
/*
* Just append if the index is greater/equal than the item count.
*/
if (idx >= list->nbItems) {
list->items[list->nbItems++] = item;
} else {
int i;
for (i = list->nbItems; i > idx; i--)
list->items[i] = list->items[i-1];
list->items[idx] = item;
list->nbItems++;
}
return(0);
}
#endif
static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
{
int i;
if ((list->items == NULL) || (idx >= list->nbItems)) {
xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
"index error.\n");
return(-1);
}
if (list->nbItems == 1) {
/* TODO: Really free the list? */
xmlFree(list->items);
list->items = NULL;
list->nbItems = 0;
list->sizeItems = 0;
} else if (list->nbItems -1 == idx) {
list->nbItems--;
} else {
for (i = idx; i < list->nbItems -1; i++)
list->items[i] = list->items[i+1];
list->nbItems--;
}
return(0);
}
/**
* xmlSchemaItemListFree:
* @annot: a schema type structure
*
* Deallocate a annotation structure
*/
static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)
{
if (list == NULL)
return;
if (list->items != NULL)
xmlFree(list->items);
xmlFree(list);
}
static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
{
if (bucket == NULL)
return;
if (bucket->globals != NULL) {
xmlSchemaComponentListFree(bucket->globals);
xmlSchemaItemListFree(bucket->globals);
}
if (bucket->locals != NULL) {
xmlSchemaComponentListFree(bucket->locals);
xmlSchemaItemListFree(bucket->locals);
}
if (bucket->relations != NULL) {
xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
do {
prev = cur;
cur = cur->next;
xmlFree(prev);
} while (cur != NULL);
}
if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
xmlFreeDoc(bucket->doc);
}
if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
if (WXS_IMPBUCKET(bucket)->schema != NULL)
xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
}
xmlFree(bucket);
}
static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
int type, const xmlChar *targetNamespace)
{
xmlSchemaBucketPtr ret;
int size;
xmlSchemaPtr mainSchema;
if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
PERROR_INT("xmlSchemaBucketCreate",
"no main schema on constructor");
return(NULL);
}
mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
/* Create the schema bucket. */
if (WXS_IS_BUCKET_INCREDEF(type))
size = sizeof(xmlSchemaInclude);
else
size = sizeof(xmlSchemaImport);
ret = (xmlSchemaBucketPtr) xmlMalloc(size);
if (ret == NULL) {
xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
return(NULL);
}
memset(ret, 0, size);
ret->targetNamespace = targetNamespace;
ret->type = type;
ret->globals = xmlSchemaItemListCreate();
if (ret->globals == NULL) {
xmlFree(ret);
return(NULL);
}
ret->locals = xmlSchemaItemListCreate();
if (ret->locals == NULL) {
xmlFree(ret);
return(NULL);
}
/*
* The following will assure that only the first bucket is marked as
* XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
* For each following import buckets an xmlSchema will be created.
* An xmlSchema will be created for every distinct targetNamespace.
* We assign the targetNamespace to the schemata here.
*/
if (! WXS_HAS_BUCKETS(pctxt)) {
if (WXS_IS_BUCKET_INCREDEF(type)) {
PERROR_INT("xmlSchemaBucketCreate",
"first bucket but it's an include or redefine");
xmlSchemaBucketFree(ret);
return(NULL);
}
/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
ret->type = XML_SCHEMA_SCHEMA_MAIN;
/* Point to the *main* schema. */
WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
WXS_IMPBUCKET(ret)->schema = mainSchema;
/*
* Ensure that the main schema gets a targetNamespace.
*/
mainSchema->targetNamespace = targetNamespace;
} else {
if (type == XML_SCHEMA_SCHEMA_MAIN) {
PERROR_INT("xmlSchemaBucketCreate",
"main bucket but it's not the first one");
xmlSchemaBucketFree(ret);
return(NULL);
} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
/*
* Create a schema for imports and assign the
* targetNamespace.
*/
WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
if (WXS_IMPBUCKET(ret)->schema == NULL) {
xmlSchemaBucketFree(ret);
return(NULL);
}
WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
}
}
if (WXS_IS_BUCKET_IMPMAIN(type)) {
int res;
/*
* Imports go into the "schemasImports" slot of the main *schema*.
* Note that we create an import entry for the main schema as well; i.e.,
* even if there's only one schema, we'll get an import.
*/
if (mainSchema->schemasImports == NULL) {
mainSchema->schemasImports = xmlHashCreateDict(5,
WXS_CONSTRUCTOR(pctxt)->dict);
if (mainSchema->schemasImports == NULL) {
xmlSchemaBucketFree(ret);
return(NULL);
}
}
if (targetNamespace == NULL)
res = xmlHashAddEntry(mainSchema->schemasImports,
XML_SCHEMAS_NO_NAMESPACE, ret);
else
res = xmlHashAddEntry(mainSchema->schemasImports,
targetNamespace, ret);
if (res != 0) {
PERROR_INT("xmlSchemaBucketCreate",
"failed to add the schema bucket to the hash");
xmlSchemaBucketFree(ret);
return(NULL);
}
} else {
/* Set the @ownerImport of an include bucket. */
if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
WXS_INCBUCKET(ret)->ownerImport =
WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
else
WXS_INCBUCKET(ret)->ownerImport =
WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
/* Includes got into the "includes" slot of the *main* schema. */
if (mainSchema->includes == NULL) {
mainSchema->includes = xmlSchemaItemListCreate();
if (mainSchema->includes == NULL) {
xmlSchemaBucketFree(ret);
return(NULL);
}
}
xmlSchemaItemListAdd(mainSchema->includes, ret);
}
/*
* Add to list of all buckets; this is used for lookup
* during schema construction time only.
*/
if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
return(NULL);
return(ret);
}
static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
{
if (*list == NULL) {
*list = xmlSchemaItemListCreate();
if (*list == NULL)
return(-1);
}
xmlSchemaItemListAddSize(*list, initialSize, item);
return(0);
}
/**
* xmlSchemaFreeAnnot:
* @annot: a schema type structure
*
* Deallocate a annotation structure
*/
static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
{
if (annot == NULL)
return;
if (annot->next == NULL) {
xmlFree(annot);
} else {
xmlSchemaAnnotPtr prev;
do {
prev = annot;
annot = annot->next;
xmlFree(prev);
} while (annot != NULL);
}
}
/**
* xmlSchemaFreeNotation:
* @schema: a schema notation structure
*
* Deallocate a Schema Notation structure.
*/
static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
{
if (nota == NULL)
return;
xmlFree(nota);
}
/**
* xmlSchemaFreeAttribute:
* @attr: an attribute declaration
*
* Deallocates an attribute declaration structure.
*/
static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
{
if (attr == NULL)
return;
if (attr->annot != NULL)
xmlSchemaFreeAnnot(attr->annot);
if (attr->defVal != NULL)
xmlSchemaFreeValue(attr->defVal);
xmlFree(attr);
}
/**
* xmlSchemaFreeAttributeUse:
* @use: an attribute use
*
* Deallocates an attribute use structure.
*/
static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
{
if (use == NULL)
return;
if (use->annot != NULL)
xmlSchemaFreeAnnot(use->annot);
if (use->defVal != NULL)
xmlSchemaFreeValue(use->defVal);
xmlFree(use);
}
/**
* xmlSchemaFreeAttributeUseProhib:
* @prohib: an attribute use prohibition
*
* Deallocates an attribute use structure.
*/
static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
{
if (prohib == NULL)
return;
xmlFree(prohib);
}
/**
* xmlSchemaFreeWildcardNsSet:
* set: a schema wildcard namespace
*
* Deallocates a list of wildcard constraint structures.
*/
static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
{
xmlSchemaWildcardNsPtr next;
while (set != NULL) {
next = set->next;
xmlFree(set);
set = next;
}
}
/**
* xmlSchemaFreeWildcard:
* @wildcard: a wildcard structure
*
* Deallocates a wildcard structure.
*/
void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
{
if (wildcard == NULL)
return;
if (wildcard->annot != NULL)
xmlSchemaFreeAnnot(wildcard->annot);
if (wildcard->nsSet != NULL)
xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
if (wildcard->negNsSet != NULL)
xmlFree(wildcard->negNsSet);
xmlFree(wildcard);
}
/**
* xmlSchemaFreeAttributeGroup:
* @schema: a schema attribute group structure
*
* Deallocate a Schema Attribute Group structure.
*/
static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
{
if (attrGr == NULL)
return;
if (attrGr->annot != NULL)
xmlSchemaFreeAnnot(attrGr->annot);
if (attrGr->attrUses != NULL)
xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
xmlFree(attrGr);
}
/**
* xmlSchemaFreeQNameRef:
* @item: a QName reference structure
*
* Deallocatea a QName reference structure.
*/
static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
{
xmlFree(item);
}
/**
* xmlSchemaFreeTypeLinkList:
* @alink: a type link
*
* Deallocate a list of types.
*/
static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
{
xmlSchemaTypeLinkPtr next;
while (link != NULL) {