1
0
mirror of https://gitlab.gnome.org/GNOME/libxslt synced 2025-07-29 15:41:13 +03:00

added DTD like checking when compiling stylesheets, closes bug #160402 and

* libxslt/preproc.c libxslt/xslt.c libxslt/xsltInternals.h:
  added DTD like checking when compiling stylesheets, closes
  bug #160402 and a long term TODO
* tests/general/bug-89.xsl: thos spotted a misconstruct of one
  of the test cases where <xsl:when> was not within <xsl:choose>
Daniel
This commit is contained in:
Daniel Veillard
2005-03-29 13:16:06 +00:00
parent 9b631cb80d
commit 7cbb21dabd
7 changed files with 240 additions and 28 deletions

View File

@ -1,6 +1,14 @@
Tue Mar 29 15:13:59 CEST 2005 Daniel Veillard <daniel@veillard.com>
* libxslt/preproc.c libxslt/xslt.c libxslt/xsltInternals.h:
added DTD like checking when compiling stylesheets, closes
bug #160402 and a long term TODO
* tests/general/bug-89.xsl: thos spotted a misconstruct of one
of the test cases where <xsl:when> was not within <xsl:choose>
Mon Mar 21 20:56:43 MST 2005 John Fleck (jfleck@inkstain.net)
* doc/xsltproc.xml, xsltproc.html, xsltproc.1
* doc/xsltproc.xml, xsltproc.html, xsltproc.1:
update documentation to reflect addition of --nodtdattr
command line flag. Bug #171098

View File

@ -54,7 +54,7 @@ Output each step taken by xsltproc in processing the stylesheet and the document
.TP
\fB\-o\fR or \fB\-\-output\fR \fIfile\fR
Direct output to the file named \fIfile\fR\&. For multiple outputs, also known as "chunking", \fB\-o\fR \fBdirectory/\fR directs the output files to a specified directory\&. The directory must already exist\&.
Direct output to the file named \fIfile\fR\&. For multiple outputs, also known as "chunking", \fB\-o\fR \fBdirectory/\fR directs the output files to a specified directory\&. The directory must already exist\&.
.TP
\fB\-\-timing\fR

View File

@ -46,6 +46,158 @@
const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element";
/************************************************************************
* *
* 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++;
}
/************************************************************************
* *
* handling of precomputed data *
@ -1192,91 +1344,129 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
xsltStylePreCompPtr cur;
if (IS_XSLT_NAME(inst, "apply-templates")) {
xsltCheckInstructionElement(style, inst);
xsltApplyTemplatesComp(style, inst);
} else if (IS_XSLT_NAME(inst, "with-param")) {
xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
BAD_CAST "call-template");
xsltWithParamComp(style, inst);
} else if (IS_XSLT_NAME(inst, "value-of")) {
xsltCheckInstructionElement(style, inst);
xsltValueOfComp(style, inst);
} else if (IS_XSLT_NAME(inst, "copy")) {
xsltCheckInstructionElement(style, inst);
xsltCopyComp(style, inst);
} else if (IS_XSLT_NAME(inst, "copy-of")) {
xsltCheckInstructionElement(style, inst);
xsltCopyOfComp(style, inst);
} else if (IS_XSLT_NAME(inst, "if")) {
xsltCheckInstructionElement(style, inst);
xsltIfComp(style, inst);
} else if (IS_XSLT_NAME(inst, "when")) {
xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
xsltWhenComp(style, inst);
} else if (IS_XSLT_NAME(inst, "choose")) {
xsltCheckInstructionElement(style, inst);
xsltChooseComp(style, inst);
} else if (IS_XSLT_NAME(inst, "for-each")) {
xsltCheckInstructionElement(style, inst);
xsltForEachComp(style, inst);
} else if (IS_XSLT_NAME(inst, "apply-imports")) {
xsltCheckInstructionElement(style, inst);
xsltApplyImportsComp(style, inst);
} else if (IS_XSLT_NAME(inst, "attribute")) {
xmlNodePtr parent = inst->parent;
if ((parent == NULL) || (parent->ns == NULL) ||
((parent->ns != inst->ns) &&
(!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
(!xmlStrEqual(parent->name, BAD_CAST "attribute-set"))) {
xsltCheckInstructionElement(style, inst);
}
xsltAttributeComp(style, inst);
} else if (IS_XSLT_NAME(inst, "element")) {
xsltCheckInstructionElement(style, inst);
xsltElementComp(style, inst);
} else if (IS_XSLT_NAME(inst, "text")) {
xsltCheckInstructionElement(style, inst);
xsltTextComp(style, inst);
} else if (IS_XSLT_NAME(inst, "sort")) {
xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
BAD_CAST "for-each");
xsltSortComp(style, inst);
} else if (IS_XSLT_NAME(inst, "comment")) {
xsltCheckInstructionElement(style, inst);
xsltCommentComp(style, inst);
} else if (IS_XSLT_NAME(inst, "number")) {
xsltCheckInstructionElement(style, inst);
xsltNumberComp(style, inst);
} else if (IS_XSLT_NAME(inst, "processing-instruction")) {
xsltCheckInstructionElement(style, inst);
xsltProcessingInstructionComp(style, inst);
} else if (IS_XSLT_NAME(inst, "call-template")) {
xsltCheckInstructionElement(style, inst);
xsltCallTemplateComp(style, inst);
} else if (IS_XSLT_NAME(inst, "param")) {
if (xsltCheckTopLevelElement(style, inst, 0) == 0)
xsltCheckInstructionElement(style, inst);
xsltParamComp(style, inst);
} else if (IS_XSLT_NAME(inst, "variable")) {
if (xsltCheckTopLevelElement(style, inst, 0) == 0)
xsltCheckInstructionElement(style, inst);
xsltVariableComp(style, inst);
} else if (IS_XSLT_NAME(inst, "otherwise")) {
/* no computation needed */
xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
xsltCheckInstructionElement(style, inst);
return;
} else if (IS_XSLT_NAME(inst, "template")) {
/* no computation needed */
xsltCheckTopLevelElement(style, inst, 1);
return;
} else if (IS_XSLT_NAME(inst, "output")) {
/* no computation needed */
xsltCheckTopLevelElement(style, inst, 1);
return;
} else if (IS_XSLT_NAME(inst, "preserve-space")) {
/* no computation needed */
xsltCheckTopLevelElement(style, inst, 1);
return;
} else if (IS_XSLT_NAME(inst, "strip-space")) {
/* no computation needed */
xsltCheckTopLevelElement(style, inst, 1);
return;
} else if (IS_XSLT_NAME(inst, "stylesheet")) {
/* no computation needed */
return;
} else if (IS_XSLT_NAME(inst, "transform")) {
/* no computation needed */
} else if ((IS_XSLT_NAME(inst, "stylesheet")) ||
(IS_XSLT_NAME(inst, "transform"))) {
xmlNodePtr parent = inst->parent;
if ((parent == NULL) || (parent->type != XML_DOCUMENT_NODE)) {
xsltTransformError(NULL, style, inst,
"element %s only allowed only as root element\n",
inst->name);
style->errors++;
}
return;
} else if (IS_XSLT_NAME(inst, "key")) {
/* no computation needed */
xsltCheckTopLevelElement(style, inst, 1);
return;
} else if (IS_XSLT_NAME(inst, "message")) {
/* no computation needed */
xsltCheckInstructionElement(style, inst);
return;
} else if (IS_XSLT_NAME(inst, "attribute-set")) {
/* no computation needed */
xsltCheckTopLevelElement(style, inst, 1);
return;
} else if (IS_XSLT_NAME(inst, "namespace-alias")) {
/* no computation needed */
xsltCheckTopLevelElement(style, inst, 1);
return;
} else if (IS_XSLT_NAME(inst, "include")) {
/* no computation needed */
xsltCheckTopLevelElement(style, inst, 1);
return;
} else if (IS_XSLT_NAME(inst, "import")) {
/* no computation needed */
xsltCheckTopLevelElement(style, inst, 1);
return;
} else if (IS_XSLT_NAME(inst, "decimal-format")) {
/* no computation needed */
xsltCheckTopLevelElement(style, inst, 1);
return;
} else if (IS_XSLT_NAME(inst, "fallback")) {
/* no computation needed */
xsltCheckInstructionElement(style, inst);
return;
} else if (IS_XSLT_NAME(inst, "document")) {
xsltCheckInstructionElement(style, inst);
inst->psvi = (void *) xsltDocumentComp(style, inst,
(xsltTransformFunction) xsltDocumentElem);
} else {

View File

@ -375,6 +375,7 @@ xsltNewStylesheet(void) {
cur->extInfos = NULL;
cur->extrasNr = 0;
cur->internalized = 1;
cur->literal_result = 0;
cur->dict = xmlDictCreate();
#ifdef WITH_XSLT_DEBUG
xsltGenericDebug(xsltGenericDebugContext,
@ -1901,8 +1902,6 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
xmlFree(prop);
}
xsltParseStylesheetExtPrefix(style, top);
cur = top->children;
/*
@ -2048,9 +2047,6 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
return(NULL);
}
xsltParseStylesheetExcludePrefix(ret, cur);
if (!ret->nopreproc)
xsltPrecomputeStylesheet(ret, cur);
if ((IS_XSLT_ELEM(cur)) &&
((IS_XSLT_NAME(cur, "stylesheet")) ||
(IS_XSLT_NAME(cur, "transform")))) {
@ -2058,6 +2054,16 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetProcess : found stylesheet\n");
#endif
ret->literal_result = 0;
xsltParseStylesheetExtPrefix(ret, cur);
} else {
ret->literal_result = 1;
}
if (!ret->nopreproc)
xsltPrecomputeStylesheet(ret, cur);
if (ret->literal_result == 0) {
xsltParseStylesheetTop(ret, cur);
} else {
@ -2105,6 +2111,7 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
template->elem = (xmlNodePtr) doc;
template->content = doc->children;
xsltAddTemplate(ret, template, NULL, NULL);
ret->literal_result = 1;
}
return(ret);

View File

@ -447,6 +447,10 @@ struct _xsltStylesheet {
* all document text strings were internalized
*/
int internalized;
/*
* Literal Result Element as Stylesheet c.f. section 2.3
*/
int literal_result;
};
/*

View File

@ -44,7 +44,7 @@ extern "C" {
*
* extra version information, used to show a CVS compilation
*/
#define LIBXSLT_VERSION_EXTRA "-CVS998"
#define LIBXSLT_VERSION_EXTRA "-CVS999"
/**
* WITH_XSLT_DEBUG:

View File

@ -44,9 +44,12 @@ la valeur nulle -->
</xsl:call-template>
</xsl:when>
<xsl:when test="$action='repl'">
<xsl:choose>
<xsl:when test="$action='del'">
<xsl:call-template name="del"/>
</xsl:when> <xsl:call-template name="add">
</xsl:when>
</xsl:choose>
<xsl:call-template name="add">
<xsl:with-param name="type">toto</xsl:with-param>
</xsl:call-template>
</xsl:when> </xsl:choose>