XSLT_OP_END=0,
XSLT_OP_ROOT,
XSLT_OP_ELEM,
- XSLT_OP_CHILD,
XSLT_OP_ATTR,
XSLT_OP_PARENT,
XSLT_OP_ANCESTOR,
XSLT_OP_PREDICATE
} xsltOp;
+typedef enum {
+ AXIS_CHILD=1,
+ AXIS_ATTRIBUTE
+} xsltAxis;
+
typedef struct _xsltStepState xsltStepState;
typedef xsltStepState *xsltStepStatePtr;
struct _xsltStepState {
goto rollback;
}
continue;
- case XSLT_OP_CHILD: {
- xmlNodePtr lst;
-
- if ((node->type != XML_ELEMENT_NODE) &&
- (node->type != XML_DOCUMENT_NODE) &&
-#ifdef LIBXML_DOCB_ENABLED
- (node->type != XML_DOCB_DOCUMENT_NODE) &&
-#endif
- (node->type != XML_HTML_DOCUMENT_NODE))
- goto rollback;
-
- lst = node->children;
-
- if (step->value != NULL) {
- while (lst != NULL) {
- if ((lst->type == XML_ELEMENT_NODE) &&
- (step->value[0] == lst->name[0]) &&
- (xmlStrEqual(step->value, lst->name)))
- break;
- lst = lst->next;
- }
- if (lst != NULL)
- continue;
- }
- goto rollback;
- }
case XSLT_OP_ATTR:
if (node->type != XML_ATTRIBUTE_NODE)
goto rollback;
}
/**
- * xsltScanName:
- * @ctxt: the XPath Parser context
- *
- * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' |
- * CombiningChar | Extender
- *
- * [5] Name ::= (Letter | '_' | ':') (NameChar)*
- *
- * [6] Names ::= Name (S Name)*
- *
- * Returns the Name parsed or NULL
- */
-
-static xmlChar *
-xsltScanName(xsltParserContextPtr ctxt) {
- const xmlChar *q, *cur;
- xmlChar *ret = NULL;
- int val, len;
-
- SKIP_BLANKS;
-
- cur = q = CUR_PTR;
- val = xmlStringCurrentChar(NULL, cur, &len);
- if (!IS_LETTER(val) && (val != '_') && (val != ':'))
- return(NULL);
-
- while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
- (val == '.') || (val == '-') ||
- (val == '_') ||
- (IS_COMBINING(val)) ||
- (IS_EXTENDER(val))) {
- cur += len;
- val = xmlStringCurrentChar(NULL, cur, &len);
- }
- ret = xmlStrndup(q, cur - q);
- CUR_PTR = cur;
- return(ret);
-}
-
-/**
* xsltScanNCName:
* @ctxt: the XPath Parser context
*
return(ret);
}
-/**
- * xsltScanQName:
- * @ctxt: the XPath Parser context
- * @prefix: the place to store the prefix
- *
- * Parse a qualified name
- *
- * Returns the Name parsed or NULL
- */
-
-static xmlChar *
-xsltScanQName(xsltParserContextPtr ctxt, xmlChar **prefix) {
- xmlChar *ret = NULL;
-
- *prefix = NULL;
- ret = xsltScanNCName(ctxt);
- if (ret && CUR == ':') {
- *prefix = ret;
- NEXT;
- ret = xsltScanNCName(ctxt);
- }
- return(ret);
-}
-
/*
* xsltCompileIdKeyPattern:
* @ctxt: the compilation context
*/
static void
xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name,
- int aid, int novar) {
+ int aid, int novar, xsltAxis axis) {
xmlChar *lit = NULL;
xmlChar *lit2 = NULL;
return;
}
if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) {
+ if (axis != 0) {
+ xsltTransformError(NULL, NULL, NULL,
+ "xsltCompileIdKeyPattern : NodeTest expected\n");
+ ctxt->error = 1;
+ return;
+ }
NEXT;
SKIP_BLANKS;
lit = xsltScanLiteral(ctxt);
NEXT;
PUSH(XSLT_OP_ID, lit, NULL, novar);
} else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) {
+ if (axis != 0) {
+ xsltTransformError(NULL, NULL, NULL,
+ "xsltCompileIdKeyPattern : NodeTest expected\n");
+ ctxt->error = 1;
+ return;
+ }
NEXT;
SKIP_BLANKS;
lit = xsltScanLiteral(ctxt);
return;
}
NEXT;
- PUSH(XSLT_OP_NODE, NULL, NULL, novar);
+ if (axis == AXIS_ATTRIBUTE) {
+ PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
+ }
+ else {
+ PUSH(XSLT_OP_NODE, NULL, NULL, novar);
+ }
} else if (aid) {
xsltTransformError(NULL, NULL, NULL,
"xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n");
const xmlChar *URI = NULL;
xmlChar *URL = NULL;
int level;
+ xsltAxis axis = 0;
SKIP_BLANKS;
if ((token == NULL) && (CUR == '@')) {
- xmlChar *prefix = NULL;
-
NEXT;
- if (CUR == '*') {
- NEXT;
- PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
- goto parse_predicate;
- }
- token = xsltScanQName(ctxt, &prefix);
- if (prefix != NULL) {
- xmlNsPtr ns;
-
- ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix);
- if (ns == NULL) {
- xsltTransformError(NULL, NULL, NULL,
- "xsltCompileStepPattern : no namespace bound to prefix %s\n",
- prefix);
- } else {
- URL = xmlStrdup(ns->href);
- }
- xmlFree(prefix);
- }
- if (token == NULL) {
- if (CUR == '*') {
- NEXT;
- PUSH(XSLT_OP_ATTR, NULL, URL, novar);
- return;
- }
- xsltTransformError(NULL, NULL, NULL,
- "xsltCompileStepPattern : Name expected\n");
- ctxt->error = 1;
- goto error;
- }
- PUSH(XSLT_OP_ATTR, token, URL, novar);
- goto parse_predicate;
+ axis = AXIS_ATTRIBUTE;
}
+parse_node_test:
if (token == NULL)
- token = xsltScanName(ctxt);
+ token = xsltScanNCName(ctxt);
if (token == NULL) {
if (CUR == '*') {
NEXT;
- PUSH(XSLT_OP_ALL, token, NULL, novar);
+ if (axis == AXIS_ATTRIBUTE) {
+ PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
+ }
+ else {
+ PUSH(XSLT_OP_ALL, NULL, NULL, novar);
+ }
goto parse_predicate;
} else {
xsltTransformError(NULL, NULL, NULL,
SKIP_BLANKS;
if (CUR == '(') {
- xsltCompileIdKeyPattern(ctxt, token, 0, novar);
+ xsltCompileIdKeyPattern(ctxt, token, 0, novar, axis);
if (ctxt->error)
goto error;
} else if (CUR == ':') {
/*
* This is a namespace match
*/
- token = xsltScanName(ctxt);
+ token = xsltScanNCName(ctxt);
ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix);
if (ns == NULL) {
xsltTransformError(NULL, NULL, NULL,
if (token == NULL) {
if (CUR == '*') {
NEXT;
- PUSH(XSLT_OP_NS, URL, NULL, novar);
+ if (axis == AXIS_ATTRIBUTE) {
+ PUSH(XSLT_OP_ATTR, NULL, URL, novar);
+ }
+ else {
+ PUSH(XSLT_OP_NS, URL, NULL, novar);
+ }
} else {
xsltTransformError(NULL, NULL, NULL,
"xsltCompileStepPattern : Name expected\n");
goto error;
}
} else {
- PUSH(XSLT_OP_ELEM, token, URL, novar);
+ if (axis == AXIS_ATTRIBUTE) {
+ PUSH(XSLT_OP_ATTR, token, URL, novar);
+ }
+ else {
+ PUSH(XSLT_OP_ELEM, token, URL, novar);
+ }
}
} else {
+ if (axis != 0) {
+ xsltTransformError(NULL, NULL, NULL,
+ "xsltCompileStepPattern : NodeTest expected\n");
+ ctxt->error = 1;
+ goto error;
+ }
NEXT;
if (xmlStrEqual(token, (const xmlChar *) "child")) {
- xmlFree(token);
- token = xsltScanName(ctxt);
- if (token == NULL) {
- if (CUR == '*') {
- NEXT;
- PUSH(XSLT_OP_ALL, token, NULL, novar);
- goto parse_predicate;
- } else {
- xsltTransformError(NULL, NULL, NULL,
- "xsltCompileStepPattern : QName expected\n");
- ctxt->error = 1;
- goto error;
- }
- }
- URI = xsltGetQNameURI(ctxt->elem, &token);
- if (token == NULL) {
- ctxt->error = 1;
- goto error;
- } else {
- name = xmlStrdup(token);
- if (URI != NULL)
- URL = xmlStrdup(URI);
- }
- PUSH(XSLT_OP_CHILD, name, URL, novar);
+ axis = AXIS_CHILD;
} else if (xmlStrEqual(token, (const xmlChar *) "attribute")) {
- xmlFree(token);
- token = xsltScanName(ctxt);
- if (token == NULL) {
- xsltTransformError(NULL, NULL, NULL,
- "xsltCompileStepPattern : QName expected\n");
- ctxt->error = 1;
- goto error;
- }
- URI = xsltGetQNameURI(ctxt->elem, &token);
- if (token == NULL) {
- ctxt->error = 1;
- goto error;
- } else {
- name = xmlStrdup(token);
- if (URI != NULL)
- URL = xmlStrdup(URI);
- }
- PUSH(XSLT_OP_ATTR, name, URL, novar);
+ axis = AXIS_ATTRIBUTE;
} else {
xsltTransformError(NULL, NULL, NULL,
"xsltCompileStepPattern : 'child' or 'attribute' expected\n");
goto error;
}
xmlFree(token);
+ SKIP_BLANKS;
+ token = xsltScanNCName(ctxt);
+ goto parse_node_test;
}
- } else if (CUR == '*') {
- NEXT;
- PUSH(XSLT_OP_ALL, token, NULL, novar);
} else {
URI = xsltGetQNameURI(ctxt->elem, &token);
if (token == NULL) {
}
if (URI != NULL)
URL = xmlStrdup(URI);
- PUSH(XSLT_OP_ELEM, token, URL, novar);
+ if (axis == AXIS_ATTRIBUTE) {
+ PUSH(XSLT_OP_ATTR, token, URL, novar);
+ }
+ else {
+ PUSH(XSLT_OP_ELEM, token, URL, novar);
+ }
}
parse_predicate:
SKIP_BLANKS;
xsltCompileRelativePathPattern(ctxt, NULL, novar);
} else {
xmlChar *name;
- name = xsltScanName(ctxt);
+ name = xsltScanNCName(ctxt);
if (name == NULL) {
xsltTransformError(NULL, NULL, NULL,
"xsltCompileLocationPathPattern : Name expected\n");
}
SKIP_BLANKS;
if ((CUR == '(') && !xmlXPathIsNodeType(name)) {
- xsltCompileIdKeyPattern(ctxt, name, 1, novar);
+ xsltCompileIdKeyPattern(ctxt, name, 1, novar, 0);
if ((CUR == '/') && (NXT(1) == '/')) {
PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
NEXT;
else
top = &(style->attrMatch);
break;
- case XSLT_OP_CHILD:
case XSLT_OP_PARENT:
case XSLT_OP_ANCESTOR:
top = &(style->elemMatch);