1
0
mirror of https://gitlab.gnome.org/GNOME/libxslt synced 2025-11-08 11:02:18 +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:
Daniel Veillard
2001-01-20 22:40:37 +00:00
parent 6b5e9df67f
commit 007037dd75
9 changed files with 354 additions and 25 deletions

View File

@@ -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

View File

@@ -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
View 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
View 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__ */

View File

@@ -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);
} }
/* /*

View File

@@ -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,9 +434,8 @@ 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
select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE); select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);

View File

@@ -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");

View File

@@ -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)

View File

@@ -1,18 +1,18 @@
<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"/>
<text x="0" y="10">Revenue</text> <text x="0" y="10">Revenue</text>
<text x="150" y="165">Division</text> <text x="150" y="165">Division</text>
<rect x="10" y="50" width="20" height="100"/> <rect x="10" y="50" width="20" height="100"/>
<text x="10" y="165">North</text> <text x="10" y="165">North</text>
<text x="10" y="45">10</text> <text x="10" y="45">10</text>
<rect x="50" y="110" width="20" height="40"/> <rect x="50" y="110" width="20" height="40"/>
<text x="50" y="165">South</text> <text x="50" y="165">South</text>
<text x="50" y="105">4</text> <text x="50" y="105">4</text>
<rect x="90" y="90" width="20" height="60"/> <rect x="90" y="90" width="20" height="60"/>
<text x="90" y="165">West</text> <text x="90" y="165">West</text>
<text x="90" y="85">6</text> <text x="90" y="85">6</text>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 723 B

After

Width:  |  Height:  |  Size: 684 B