+ * Grammar checks *
+ * *
+ ************************************************************************/
+
+/**
+ * xsltCheckTopLevelElement:
+ * @style: the XSLT stylesheet
+ * @inst: the XSLT instruction
+ * @err: raise an error or not
+ *
+ * Check that the instruction is instanciated as a top level element.
+ *
+ * Returns -1 in case of error, 0 if failed and 1 in case of success
+ */
+static int
+xsltCheckTopLevelElement(xsltStylesheetPtr style, xmlNodePtr inst, int err) {
+ xmlNodePtr parent;
+ if ((style == NULL) || (inst == NULL) || (inst->ns == NULL))
+ return(-1);
+
+ parent = inst->parent;
+ if (parent == NULL) {
+ if (err) {
+ xsltTransformError(NULL, style, inst,
+ "internal problem: element has no parent\n");
+ style->errors++;
+ }
+ return(0);
+ }
+ if ((parent->ns == NULL) ||
+ ((parent->ns != inst->ns) &&
+ (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
+ ((!xmlStrEqual(parent->name, BAD_CAST "stylesheet")) &&
+ (!xmlStrEqual(parent->name, BAD_CAST "transform")))) {
+ if (err) {
+ xsltTransformError(NULL, style, inst,
+ "element %s only allowed as child of stylesheet\n",
+ inst->name);
+ style->errors++;
+ }
+ return(0);
+ }
+ return(1);
+}
+
+/**
+ * xsltCheckInstructionElement:
+ * @style: the XSLT stylesheet
+ * @inst: the XSLT instruction
+ *
+ * Check that the instruction is instanciated as an instruction element.
+ */
+static void
+xsltCheckInstructionElement(xsltStylesheetPtr style, xmlNodePtr inst) {
+ xmlNodePtr parent;
+ int has_ext;
+
+ if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||
+ (style->literal_result))
+ return;
+
+ has_ext = (style->extInfos != NULL);
+
+ parent = inst->parent;
+ if (parent == NULL) {
+ xsltTransformError(NULL, style, inst,
+ "internal problem: element has no parent\n");
+ style->errors++;
+ return;
+ }
+ while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {
+ if (((parent->ns == inst->ns) ||
+ ((parent->ns != NULL) &&
+ (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&
+ ((xmlStrEqual(parent->name, BAD_CAST "template")) ||
+ (xmlStrEqual(parent->name, BAD_CAST "param")) ||
+ (xmlStrEqual(parent->name, BAD_CAST "attribute")) ||
+ (xmlStrEqual(parent->name, BAD_CAST "variable")))) {
+ return;
+ }
+
+ /*
+ * if we are within an extension element all bets are off
+ * about the semantic there e.g. xsl:param within func:function
+ */
+ if ((has_ext) && (parent->ns != NULL) &&
+ (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))
+ return;
+
+ parent = parent->parent;
+ }
+ xsltTransformError(NULL, style, inst,
+ "element %s only allowed within a template, variable or param\n",
+ inst->name);
+ style->errors++;
+}
+
+/**
+ * xsltCheckParentElement:
+ * @style: the XSLT stylesheet
+ * @inst: the XSLT instruction
+ * @allow1: allowed parent1
+ * @allow2: allowed parent2
+ *
+ * Check that the instruction is instanciated as the childre of one of the
+ * possible parents.
+ */
+static void
+xsltCheckParentElement(xsltStylesheetPtr style, xmlNodePtr inst,
+ const xmlChar *allow1, const xmlChar *allow2) {
+ xmlNodePtr parent;
+
+ if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||
+ (style->literal_result))
+ return;
+
+ parent = inst->parent;
+ if (parent == NULL) {
+ xsltTransformError(NULL, style, inst,
+ "internal problem: element has no parent\n");
+ style->errors++;
+ return;
+ }
+ if (((parent->ns == inst->ns) ||
+ ((parent->ns != NULL) &&
+ (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&
+ ((xmlStrEqual(parent->name, allow1)) ||
+ (xmlStrEqual(parent->name, allow2)))) {
+ return;
+ }
+
+ if (style->extInfos != NULL) {
+ while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {
+ /*
+ * if we are within an extension element all bets are off
+ * about the semantic there e.g. xsl:param within func:function
+ */
+ if ((parent->ns != NULL) &&
+ (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))
+ return;
+
+ parent = parent->parent;
+ }
+ }
+ xsltTransformError(NULL, style, inst,
+ "element %s is not allowed within that context\n",
+ inst->name);
+ style->errors++;
+}
+
+/************************************************************************
+ * *