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:
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>
|
||||
|
||||
* libxslt/transform.c libxslt/variables.[ch] libxslt/xslt.c
|
||||
|
||||
@@ -10,6 +10,8 @@ libxslt_la_SOURCES = \
|
||||
xsltutils.h \
|
||||
pattern.c \
|
||||
pattern.h \
|
||||
templates.c \
|
||||
templates.h \
|
||||
variables.c \
|
||||
variables.h \
|
||||
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 "transform.h"
|
||||
#include "variables.h"
|
||||
#include "templates.h"
|
||||
|
||||
#define DEBUG_PROCESS
|
||||
|
||||
@@ -839,7 +840,8 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
||||
* TODO: Do the substitution of {} XPath expressions !!!
|
||||
*/
|
||||
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 "variables.h"
|
||||
|
||||
#define DEBUG_VARIABLES
|
||||
#define DEBUG_VARIABLE
|
||||
|
||||
/*
|
||||
* Types are private:
|
||||
@@ -293,6 +293,10 @@ xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||
if (name == NULL)
|
||||
return(-1);
|
||||
|
||||
#ifdef DEBUG_VARIABLE
|
||||
xsltGenericDebug(xsltGenericDebugContext,
|
||||
"Defineing variable %s\n", name);
|
||||
#endif
|
||||
elem = xsltNewStackElem();
|
||||
if (elem == NULL)
|
||||
return(-1);
|
||||
@@ -310,6 +314,7 @@ xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||
ctxt->xpathCtxt);
|
||||
if (xpathParserCtxt == NULL)
|
||||
goto error;
|
||||
ctxt->xpathCtxt->node = ctxt->node;
|
||||
xmlXPathEvalExpr(xpathParserCtxt);
|
||||
result = valuePop(xpathParserCtxt);
|
||||
do {
|
||||
@@ -369,9 +374,12 @@ xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||
#endif
|
||||
TODO /* Variable value computation needed */
|
||||
}
|
||||
error:
|
||||
if (elem->value != NULL)
|
||||
return(xmlXPathObjectCopy(elem->value));
|
||||
#ifdef DEBUG_VARIABLE
|
||||
xsltGenericDebug(xsltGenericDebugContext,
|
||||
"variable not found %s\n", name);
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
@@ -426,9 +434,8 @@ xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VARIABLE
|
||||
if (ret != NULL)
|
||||
xsltGenericDebug(xsltGenericDebugContext,
|
||||
"Parsing variable %s\n", name);
|
||||
xsltGenericDebug(xsltGenericDebugContext,
|
||||
"Parsing variable %s\n", name);
|
||||
#endif
|
||||
|
||||
select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
|
||||
|
||||
@@ -713,7 +713,7 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
|
||||
if (top == NULL)
|
||||
return;
|
||||
|
||||
prop = xmlGetNsProp(cur, (const xmlChar *)"version", XSLT_NAMESPACE);
|
||||
prop = xmlGetNsProp(top, (const xmlChar *)"version", XSLT_NAMESPACE);
|
||||
if (prop == NULL) {
|
||||
xsltGenericError(xsltGenericErrorContext,
|
||||
"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 ; \
|
||||
diff vrml.xml vrml.res ; \
|
||||
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,18 +1,18 @@
|
||||
<svg width="3in" height="3in"
|
||||
xmlns="http://www.w3.org/Graphics/SVG/svg-19990412.dtd">
|
||||
<g style="stroke: #000000">
|
||||
<line x1="0" x2="150" y1="150" y2="150"/>
|
||||
<line x1="0" x2="0" y1="0" y2="150"/>
|
||||
<text x="0" y="10">Revenue</text>
|
||||
<text x="150" y="165">Division</text>
|
||||
<rect x="10" y="50" width="20" height="100"/>
|
||||
<text x="10" y="165">North</text>
|
||||
<text x="10" y="45">10</text>
|
||||
<rect x="50" y="110" width="20" height="40"/>
|
||||
<text x="50" y="165">South</text>
|
||||
<text x="50" y="105">4</text>
|
||||
<rect x="90" y="90" width="20" height="60"/>
|
||||
<text x="90" y="165">West</text>
|
||||
<text x="90" y="85">6</text>
|
||||
</g>
|
||||
<?xml version="1.0"?>
|
||||
<svg xmlns="http://www.w3.org/Graphics/SVG/SVG-19990812.dtd" width="3in" height="3in">
|
||||
<g style="stroke: #000000">
|
||||
<line x1="0" x2="150" y1="150" y2="150"/>
|
||||
<line x1="0" x2="0" y1="0" y2="150"/>
|
||||
<text x="0" y="10">Revenue</text>
|
||||
<text x="150" y="165">Division</text>
|
||||
<rect x="10" y="50" width="20" height="100"/>
|
||||
<text x="10" y="165">North</text>
|
||||
<text x="10" y="45">10</text>
|
||||
<rect x="50" y="110" width="20" height="40"/>
|
||||
<text x="50" y="165">South</text>
|
||||
<text x="50" y="105">4</text>
|
||||
<rect x="90" y="90" width="20" height="60"/>
|
||||
<text x="90" y="165">West</text>
|
||||
<text x="90" y="85">6</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 723 B After Width: | Height: | Size: 684 B |
Reference in New Issue
Block a user