mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-11-09 22:20:55 +03:00
- libxslt/Makefile.am libxslt/template.[ch]: added a template
specific module. Added attribute value template, at least in one spot. - tests/REC2/Makefile.am tests/REC2/svg.xml: the SVG test from the spec now works too. - libxslt/variables.c: fixed the debug - libxslt/xslt.c: fixed an ugly uninitialized variable - libxslt/transform.c: now using attr template processing Daniel
This commit is contained in:
11
ChangeLog
11
ChangeLog
@@ -1,3 +1,14 @@
|
|||||||
|
Sat Jan 20 23:35:07 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
|
* libxslt/Makefile.am libxslt/template.[ch]: added a template
|
||||||
|
specific module. Added attribute value template, at least in
|
||||||
|
one spot.
|
||||||
|
* tests/REC2/Makefile.am tests/REC2/svg.xml: the SVG test from
|
||||||
|
the spec now works too.
|
||||||
|
* libxslt/variables.c: fixed the debug
|
||||||
|
* libxslt/xslt.c: fixed an ugly uninitialized variable
|
||||||
|
* libxslt/transform.c: now using attr template processing
|
||||||
|
|
||||||
Sat Jan 20 17:59:20 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
Sat Jan 20 17:59:20 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
* libxslt/transform.c libxslt/variables.[ch] libxslt/xslt.c
|
* libxslt/transform.c libxslt/variables.[ch] libxslt/xslt.c
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ libxslt_la_SOURCES = \
|
|||||||
xsltutils.h \
|
xsltutils.h \
|
||||||
pattern.c \
|
pattern.c \
|
||||||
pattern.h \
|
pattern.h \
|
||||||
|
templates.c \
|
||||||
|
templates.h \
|
||||||
variables.c \
|
variables.c \
|
||||||
variables.h \
|
variables.h \
|
||||||
transform.c \
|
transform.c \
|
||||||
|
|||||||
266
libxslt/templates.c
Normal file
266
libxslt/templates.c
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
/*
|
||||||
|
* templates.c: Implementation of the template processing
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* http://www.w3.org/TR/1999/REC-xslt-19991116
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Daniel.Veillard@imag.fr
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xsltconfig.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/xmlerror.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
#include <libxml/parserInternals.h>
|
||||||
|
#include "xslt.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "xsltutils.h"
|
||||||
|
#include "variables.h"
|
||||||
|
#include "templates.h"
|
||||||
|
|
||||||
|
#define DEBUG_TEMPLATES
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Module interfaces *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltEvalXPathString:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @str: the XPath expression
|
||||||
|
*
|
||||||
|
* Process the expression using XPath and get a string
|
||||||
|
*
|
||||||
|
* Returns the computed string value or NULL, must be deallocated by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
xmlChar *
|
||||||
|
xsltEvalXPathString(xsltTransformContextPtr ctxt, const xmlChar *expr) {
|
||||||
|
xmlChar *ret = NULL;
|
||||||
|
xmlXPathObjectPtr res, tmp;
|
||||||
|
xmlXPathParserContextPtr xpathParserCtxt;
|
||||||
|
|
||||||
|
if (ctxt->xpathCtxt == NULL) {
|
||||||
|
xmlXPathInit();
|
||||||
|
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
||||||
|
if (ctxt->xpathCtxt == NULL)
|
||||||
|
return(NULL);
|
||||||
|
XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
|
||||||
|
}
|
||||||
|
xpathParserCtxt =
|
||||||
|
xmlXPathNewParserContext(expr, ctxt->xpathCtxt);
|
||||||
|
if (xpathParserCtxt == NULL)
|
||||||
|
return(NULL);
|
||||||
|
ctxt->xpathCtxt->node = ctxt->node;
|
||||||
|
xmlXPathEvalExpr(xpathParserCtxt);
|
||||||
|
xmlXPathStringFunction(xpathParserCtxt, 1);
|
||||||
|
res = valuePop(xpathParserCtxt);
|
||||||
|
do {
|
||||||
|
tmp = valuePop(xpathParserCtxt);
|
||||||
|
if (tmp != NULL) {
|
||||||
|
xmlXPathFreeObject(tmp);
|
||||||
|
}
|
||||||
|
} while (tmp != NULL);
|
||||||
|
if (res != NULL) {
|
||||||
|
if (res->type == XPATH_STRING) {
|
||||||
|
ret = res->stringval;
|
||||||
|
res->stringval = NULL;
|
||||||
|
} else {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xpath : string() function didn't returned a String\n");
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(res);
|
||||||
|
}
|
||||||
|
xmlXPathFreeParserContext(xpathParserCtxt);
|
||||||
|
#ifdef DEBUG_TEMPLATES
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltEvalXPathString: %s returns %s\n", expr, ret);
|
||||||
|
#endif
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltAttrTemplateValueProcess:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @str: the attribute template node value
|
||||||
|
*
|
||||||
|
* Process the given node and return the new string value.
|
||||||
|
*
|
||||||
|
* Returns the computed string value or NULL, must be deallocated by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
xmlChar *
|
||||||
|
xsltAttrTemplateValueProcess(xsltTransformContextPtr ctxt, const xmlChar *str) {
|
||||||
|
xmlChar *ret = NULL, *ret2;
|
||||||
|
const xmlChar *cur;
|
||||||
|
xmlChar *expr, *val;
|
||||||
|
|
||||||
|
if (str == NULL) return(NULL);
|
||||||
|
cur = str;
|
||||||
|
while (*cur != 0) {
|
||||||
|
if (*cur == '{') {
|
||||||
|
ret2 = xmlStrncat(ret, str, cur - str);
|
||||||
|
if (ret != NULL)
|
||||||
|
xmlFree(ret);
|
||||||
|
ret = ret2;
|
||||||
|
str = cur;
|
||||||
|
cur++;
|
||||||
|
while ((*cur != 0) && (*cur != '}')) cur++;
|
||||||
|
if (*cur == 0) {
|
||||||
|
ret2 = xmlStrncat(ret, str, cur - str);
|
||||||
|
xmlFree(ret);
|
||||||
|
return(ret2);
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
expr = xmlStrndup(str, cur - str);
|
||||||
|
if (expr == NULL)
|
||||||
|
return(ret);
|
||||||
|
else {
|
||||||
|
val = xsltEvalXPathString(ctxt, expr);
|
||||||
|
xmlFree(expr);
|
||||||
|
if (val != NULL) {
|
||||||
|
ret2 = xmlStrcat(ret, val);
|
||||||
|
if (ret != NULL)
|
||||||
|
xmlFree(ret);
|
||||||
|
xmlFree(val);
|
||||||
|
ret = ret2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur++;
|
||||||
|
str = cur;
|
||||||
|
} else
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
if (cur != str) {
|
||||||
|
ret2 = xmlStrncat(ret, str, cur - str);
|
||||||
|
if (ret != NULL)
|
||||||
|
xmlFree(ret);
|
||||||
|
ret = ret2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltAttrTemplateProcess:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @target: the result node
|
||||||
|
* @cur: the attribute template node
|
||||||
|
*
|
||||||
|
* Process the given attribute and return the new processed copy.
|
||||||
|
*
|
||||||
|
* Returns the attribute replacement.
|
||||||
|
*/
|
||||||
|
xmlAttrPtr
|
||||||
|
xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
|
||||||
|
xmlAttrPtr cur) {
|
||||||
|
xmlAttrPtr ret;
|
||||||
|
if ((ctxt == NULL) || (cur == NULL))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
if (cur->type != XML_ATTRIBUTE_NODE)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
if ((cur->ns != NULL) &&
|
||||||
|
(xmlStrEqual(cur->ns->href, XSLT_NAMESPACE))) {
|
||||||
|
/* TODO: check for replacement namespaces */
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = xmlNewDocProp(ctxt->output, cur->name, NULL);
|
||||||
|
if (ret == NULL) return(NULL);
|
||||||
|
ret->parent = target;
|
||||||
|
|
||||||
|
if ((cur->ns != NULL) && (target != NULL)) {
|
||||||
|
if ((target != NULL) && (target->ns != NULL) &&
|
||||||
|
(xmlStrEqual(target->ns->href, cur->ns->href))) {
|
||||||
|
ret->ns = target->ns;
|
||||||
|
} else {
|
||||||
|
xmlNsPtr ns;
|
||||||
|
|
||||||
|
ns = xmlSearchNsByHref(ctxt->output, target, cur->ns->href);
|
||||||
|
if (ns != NULL) {
|
||||||
|
ret->ns = ns;
|
||||||
|
} else {
|
||||||
|
ns = xmlNewNs(target, cur->ns->href, cur->ns->prefix);
|
||||||
|
ret->ns = ns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ret->ns = NULL;
|
||||||
|
|
||||||
|
if (cur->children != NULL) {
|
||||||
|
xmlChar *in = xmlNodeListGetString(ctxt->doc, cur->children, 1);
|
||||||
|
xmlChar *out;
|
||||||
|
|
||||||
|
if (in != NULL) {
|
||||||
|
out = xsltAttrTemplateValueProcess(ctxt, in);
|
||||||
|
ret->children = xmlNewDocText(ctxt->output, out);
|
||||||
|
xmlFree(out);
|
||||||
|
xmlFree(in);
|
||||||
|
} else
|
||||||
|
ret->children = NULL;
|
||||||
|
|
||||||
|
} else
|
||||||
|
ret->children = NULL;
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltAttrListTemplateProcess:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @target: the element where the attributes will be grafted
|
||||||
|
* @cur: the first attribute
|
||||||
|
*
|
||||||
|
* Do a copy of an attribute list with attribute template processing
|
||||||
|
*
|
||||||
|
* Returns: a new xmlAttrPtr, or NULL in case of error.
|
||||||
|
*/
|
||||||
|
xmlAttrPtr
|
||||||
|
xsltAttrListTemplateProcess(xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr target, xmlAttrPtr cur) {
|
||||||
|
xmlAttrPtr ret = NULL;
|
||||||
|
xmlAttrPtr p = NULL,q;
|
||||||
|
|
||||||
|
while (cur != NULL) {
|
||||||
|
q = xsltAttrTemplateProcess(ctxt, target, cur);
|
||||||
|
if (p == NULL) {
|
||||||
|
ret = p = q;
|
||||||
|
} else {
|
||||||
|
p->next = q;
|
||||||
|
q->prev = p;
|
||||||
|
p = q;
|
||||||
|
}
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltTemplateProcess:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @node: the attribute template node
|
||||||
|
*
|
||||||
|
* Process the given node and return the new string value.
|
||||||
|
*
|
||||||
|
* Returns the computed tree replacement
|
||||||
|
*/
|
||||||
|
xmlNodePtr *
|
||||||
|
xsltTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
||||||
|
if (node == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
37
libxslt/templates.h
Normal file
37
libxslt/templates.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* templates.h: interface for the template processing
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Daniel.Veillard@imag.fr
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_TEMPLATES_H__
|
||||||
|
#define __XML_XSLT_TEMPLATES_H__
|
||||||
|
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
xmlChar * xsltEvalXPathString (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *expr);
|
||||||
|
xmlNodePtr * xsltTemplateProcess (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node);
|
||||||
|
xmlAttrPtr xsltAttrListTemplateProcess (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr target,
|
||||||
|
xmlAttrPtr cur);
|
||||||
|
xmlAttrPtr xsltAttrTemplateProcess (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr target,
|
||||||
|
xmlAttrPtr attr);
|
||||||
|
xmlChar * xsltAttrTemplateValueProcess (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar* attr);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_TEMPLATES_H__ */
|
||||||
|
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "pattern.h"
|
#include "pattern.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
|
#include "templates.h"
|
||||||
|
|
||||||
#define DEBUG_PROCESS
|
#define DEBUG_PROCESS
|
||||||
|
|
||||||
@@ -839,7 +840,8 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
* TODO: Do the substitution of {} XPath expressions !!!
|
* TODO: Do the substitution of {} XPath expressions !!!
|
||||||
*/
|
*/
|
||||||
if (cur->properties != NULL)
|
if (cur->properties != NULL)
|
||||||
copy->properties = xmlCopyPropList(copy, cur->properties);
|
copy->properties = xsltAttrListTemplateProcess(ctxt,
|
||||||
|
copy, cur->properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include "xsltutils.h"
|
#include "xsltutils.h"
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
|
|
||||||
#define DEBUG_VARIABLES
|
#define DEBUG_VARIABLE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Types are private:
|
* Types are private:
|
||||||
@@ -293,6 +293,10 @@ xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
|
|||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return(-1);
|
return(-1);
|
||||||
|
|
||||||
|
#ifdef DEBUG_VARIABLE
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Defineing variable %s\n", name);
|
||||||
|
#endif
|
||||||
elem = xsltNewStackElem();
|
elem = xsltNewStackElem();
|
||||||
if (elem == NULL)
|
if (elem == NULL)
|
||||||
return(-1);
|
return(-1);
|
||||||
@@ -310,6 +314,7 @@ xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
|
|||||||
ctxt->xpathCtxt);
|
ctxt->xpathCtxt);
|
||||||
if (xpathParserCtxt == NULL)
|
if (xpathParserCtxt == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
ctxt->xpathCtxt->node = ctxt->node;
|
||||||
xmlXPathEvalExpr(xpathParserCtxt);
|
xmlXPathEvalExpr(xpathParserCtxt);
|
||||||
result = valuePop(xpathParserCtxt);
|
result = valuePop(xpathParserCtxt);
|
||||||
do {
|
do {
|
||||||
@@ -369,9 +374,12 @@ xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
|
|||||||
#endif
|
#endif
|
||||||
TODO /* Variable value computation needed */
|
TODO /* Variable value computation needed */
|
||||||
}
|
}
|
||||||
error:
|
|
||||||
if (elem->value != NULL)
|
if (elem->value != NULL)
|
||||||
return(xmlXPathObjectCopy(elem->value));
|
return(xmlXPathObjectCopy(elem->value));
|
||||||
|
#ifdef DEBUG_VARIABLE
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"variable not found %s\n", name);
|
||||||
|
#endif
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,7 +434,6 @@ xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_VARIABLE
|
#ifdef DEBUG_VARIABLE
|
||||||
if (ret != NULL)
|
|
||||||
xsltGenericDebug(xsltGenericDebugContext,
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
"Parsing variable %s\n", name);
|
"Parsing variable %s\n", name);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -713,7 +713,7 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
|
|||||||
if (top == NULL)
|
if (top == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
prop = xmlGetNsProp(cur, (const xmlChar *)"version", XSLT_NAMESPACE);
|
prop = xmlGetNsProp(top, (const xmlChar *)"version", XSLT_NAMESPACE);
|
||||||
if (prop == NULL) {
|
if (prop == NULL) {
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsl:version is missing: document may not be a stylesheet\n");
|
"xsl:version is missing: document may not be a stylesheet\n");
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ test: $(top_builddir)/libxslt/xsltproc
|
|||||||
@($(top_builddir)/libxslt/xsltproc vrml.xsl data.xml > vrml.res ; \
|
@($(top_builddir)/libxslt/xsltproc vrml.xsl data.xml > vrml.res ; \
|
||||||
diff vrml.xml vrml.res ; \
|
diff vrml.xml vrml.res ; \
|
||||||
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
|
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
|
||||||
rm -f doc.res)
|
rm -f vrml.res)
|
||||||
|
@($(top_builddir)/libxslt/xsltproc svg.xsl data.xml > svg.res ; \
|
||||||
|
diff svg.xml svg.res ; \
|
||||||
|
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
|
||||||
|
rm -f svg.res)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<svg width="3in" height="3in"
|
<?xml version="1.0"?>
|
||||||
xmlns="http://www.w3.org/Graphics/SVG/svg-19990412.dtd">
|
<svg xmlns="http://www.w3.org/Graphics/SVG/SVG-19990812.dtd" width="3in" height="3in">
|
||||||
<g style="stroke: #000000">
|
<g style="stroke: #000000">
|
||||||
<line x1="0" x2="150" y1="150" y2="150"/>
|
<line x1="0" x2="150" y1="150" y2="150"/>
|
||||||
<line x1="0" x2="0" y1="0" y2="150"/>
|
<line x1="0" x2="0" y1="0" y2="150"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 723 B After Width: | Height: | Size: 684 B |
Reference in New Issue
Block a user