summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2001-01-25 18:51:41 +0000
committerDaniel Veillard <veillard@src.gnome.org>2001-01-25 18:51:41 +0000
commit6232ed7d6e89358533cf2045655e9c484bfdca4a (patch)
tree7b64126cf3921b0b150ec54a8daaba3bcd1bee54
parenta7da804741d2650c5132ab004d442d7dc4e6b64b (diff)
downloadlibxslt-6232ed7d6e89358533cf2045655e9c484bfdca4a.tar.gz
Hack, hack, hack ... Mostly adding functions:
- FEATURES TODO README INSTALL: updated - libxslt/xslt.h: added URL and version/vendor :-) - libxslt/transform.c: fixed a problem in xsl:attribute, removed attempt to support older libxml2 version. - libxslt/variables.h libxslt/xsltInternals.h: update to structures and macros to add/register new document created by document() - libxslt/functions.c: implemented current(), unparsed-entity-uri() system-property(), element-available() and function-available(). A crippled version of document() has been added too. Daniel
-rw-r--r--ChangeLog12
-rw-r--r--FEATURES20
-rw-r--r--INSTALL2
-rw-r--r--README10
-rw-r--r--TODO26
-rw-r--r--libxslt/functions.c239
-rw-r--r--libxslt/transform.c23
-rw-r--r--libxslt/variables.h3
-rw-r--r--libxslt/xslt.c5
-rw-r--r--libxslt/xslt.h2
-rw-r--r--libxslt/xsltInternals.h1
-rw-r--r--libxslt/xsltutils.c5
12 files changed, 299 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index 9c22ac3d..c091fa8e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+Thu Jan 25 19:36:45 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+ * FEATURES TODO README INSTALL: updated
+ * libxslt/xslt.h: added URL and version/vendor :-)
+ * libxslt/transform.c: fixed a problem in xsl:attribute, removed
+ attempt to support older libxml2 version.
+ * libxslt/variables.h libxslt/xsltInternals.h: update to structures
+ and macros to add/register new document created by document()
+ * libxslt/functions.c: implemented current(), unparsed-entity-uri()
+ system-property(), element-available() and function-available().
+ A crippled version of document() has been added too.
+
Thu Jan 25 12:13:04 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* functions.[ch]: Bjorn Reese <breese@mail1.stofanet.dk> provided
diff --git a/FEATURES b/FEATURES
index 9356fac5..16e2efa4 100644
--- a/FEATURES
+++ b/FEATURES
@@ -186,7 +186,9 @@ General:
========
YES (w.o import) Conflict Resolution for Template Rules
+
YES Whitespace Stripping
+
YES Built-in Template Rules
YES match="*|/"
YES match="text()|@*"
@@ -194,6 +196,10 @@ YES match="processing-instruction()|comment()"
NO Namespace
NO Mode
+NO Extension Elements
+
+NO Extension Functions
+
YES Attribute Value Templates
YES Result Tree Fragments
@@ -201,14 +207,14 @@ YES Result Tree Fragments
Functions:
==========
-NO node-set document(object, node-set?)
+PARTIAL node-set document(object, node-set?)
NO node-set key(string, object)
YES string format-number(number, string, string?)
-NO node-set current()
-NO string unparsed-entity-uri(string)
-NO string generate-id(node-set?)
-NO object system-property(string)
-NO boolean element-available(string)
-NO boolean function-available(string)
+YES node-set current()
+YES string unparsed-entity-uri(string)
+YES string generate-id(node-set?)
+YES object system-property(string)
+YES boolean element-available(string)
+YES boolean function-available(string)
Daniel.Veillard@imag.fr
diff --git a/INSTALL b/INSTALL
index 312f2f66..b522e066 100644
--- a/INSTALL
+++ b/INSTALL
@@ -3,7 +3,7 @@
Requirements:
=============
-this library requires libxml2 which you can grab from
+this library requires libxml2 >= 2.2.12 which you can grab from
either the GNOME FTP or the xmlsoft.org server:
ftp://xmlsoft.org/
diff --git a/README b/README
index 37f544ad..3f3917aa 100644
--- a/README
+++ b/README
@@ -1,10 +1,14 @@
- XSLT support for libxml
+ XSLT support for libxml2
http://xmlsoft.org/
- Requires libxml2 with XPath support.
-Currently unusable, very early steps ...
+ Requires libxml2 >= 2.2.12 with XPath support. It won't even compile
+otherwise.
+ Check the FEATURES file for informations about completeness
+ Check the Changelog too to keep track of progresses.
+
+ report bugs to xml@rpmfind.net or on the bugzilla.gnome.org base.
Daniel Veillard
diff --git a/TODO b/TODO
index 57fbb00a..47d246bb 100644
--- a/TODO
+++ b/TODO
@@ -3,6 +3,13 @@
* TODO *
* *
********
+
+Doc:
+ - put a page at http://xmlsoft.org/XSLT/
+ - generate/transform the DocBook to HTML
+ - add HTML to package
+ - manpage and doc for xsltproc
+
Design:
- should transforms for a given stylesheet be thread clean,
or can a stylesheet be enriched with document specific
@@ -15,10 +22,10 @@ Import:
-> provide functions to circulate in the import tree of stylesheets
Extra functions:
- -> make a separate module.
-> document() should not be a problem since Result Tree Fragments are
implemnted
- -> others
+ => started, incomplete
+ -> missing key support
ID and Key support:
-> Id should be simple, key will probably requires some hash tables.
@@ -36,10 +43,7 @@ Error handling:
and lack of optionnal features.
Support Attribute value templates:
- -> starts to be urgent. Design it in flexible ways but try to optimize
- to handle most of it at the stylesheet parse time ...
- => Done for the most part need to check all attributes in XSLT constructs
- using them and use the dedicated readin function.
+ -> optimization by checking their existence at stylesheet parse time.
Sorting:
-> add support for imbricated sorts
@@ -59,6 +63,16 @@ Contextual error reporting:
* *
********
+Extra functions:
+ -> make a separate module.
+ => done functions.[ch]
+
+Support Attribute value templates:
+ -> starts to be urgent. Design it in flexible ways but try to optimize
+ to handle most of it at the stylesheet parse time ...
+ => Done for the most part need to check all attributes in XSLT constructs
+ using them and use the dedicated readin function.
+
Separate util module:
-> macros, config, verbosity ?
=> xsltutils.[ch]
diff --git a/libxslt/functions.c b/libxslt/functions.c
index ca041c2b..67556c6b 100644
--- a/libxslt/functions.c
+++ b/libxslt/functions.c
@@ -42,6 +42,7 @@
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/parserInternals.h>
+#include <libxml/uri.h>
#include "xslt.h"
#include "xsltInternals.h"
#include "xsltutils.h"
@@ -110,7 +111,80 @@ isinf(double number)
*/
void
xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs){
- TODO /* function */
+ xmlDocPtr doc;
+ xmlXPathObjectPtr obj;
+ xmlChar *base, *URI;
+
+
+ if ((nargs < 1) || (nargs > 2)) {
+ xsltGenericError(xsltGenericErrorContext,
+ "document() : invalid number of args %d\n", nargs);
+ ctxt->error = XPATH_INVALID_ARITY;
+ return;
+ }
+ if (ctxt->value == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "document() : invalid arg value\n");
+ ctxt->error = XPATH_INVALID_TYPE;
+ return;
+ }
+ if (ctxt->value->type == XPATH_NODESET) {
+ TODO
+ xsltGenericError(xsltGenericErrorContext,
+ "document() : with node-sets args not yet supported\n");
+ return;
+ }
+ /*
+ * Make sure it's converted to a string
+ */
+ xmlXPathStringFunction(ctxt, 1);
+ if (ctxt->value->type != XPATH_STRING) {
+ xsltGenericError(xsltGenericErrorContext,
+ "document() : invalid arg expecting a string\n");
+ ctxt->error = XPATH_INVALID_TYPE;
+ return;
+ }
+ obj = valuePop(ctxt);
+ if (obj->stringval == NULL) {
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+ } else {
+ base = xmlNodeGetBase(ctxt->context->doc, ctxt->context->node);
+ URI = xmlBuildURI(obj->stringval, base);
+ if (base != NULL)
+ xmlFree(base);
+ if (URI == NULL) {
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+ } else {
+ doc = xmlParseDoc(URI);
+ if (doc == NULL)
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+ else {
+ xsltTransformContextPtr tctxt;
+
+ /*
+ * link it to the context for cleanup when done
+ */
+ tctxt = (xsltTransformContextPtr) ctxt->context->extra;
+ if (tctxt == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "document() : internal error tctxt == NULL\n");
+ xmlFreeDoc(doc);
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+ } else {
+ /*
+ * Keep a link from the context to be able to deallocate
+ */
+ doc->next = (xmlNodePtr) tctxt->extraDocs;
+ tctxt->extraDocs = doc;
+
+ /* TODO: use XPointer of HTML location for fragment ID */
+ /* pbm #xxx can lead to location sets, not nodesets :-) */
+ valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc));
+ }
+ }
+ }
+ }
+ xmlXPathFreeObject(obj);
}
/**
@@ -136,7 +210,40 @@ xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
*/
void
xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs){
- TODO /* function */
+ xmlXPathObjectPtr obj;
+ xmlChar *str;
+
+ if (nargs != 1) {
+ xsltGenericError(xsltGenericErrorContext,
+ "system-property() : expects one string arg\n");
+ ctxt->error = XPATH_INVALID_ARITY;
+ return;
+ }
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
+ xsltGenericError(xsltGenericErrorContext,
+ "generate-id() : invalid arg expecting a string\n");
+ ctxt->error = XPATH_INVALID_TYPE;
+ return;
+ }
+ obj = valuePop(ctxt);
+ str = obj->stringval;
+ if (str == NULL) {
+ valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
+ } else {
+ xmlEntityPtr entity;
+
+ entity = xmlGetDocEntity(ctxt->context->doc, str);
+ if (entity == NULL) {
+ valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
+ } else {
+ if (entity->URI != NULL)
+ valuePush(ctxt, xmlXPathNewString(entity->URI));
+ else
+ valuePush(ctxt, xmlXPathNewString(
+ xmlStrdup((const xmlChar *)"")));
+ }
+ }
+ xmlXPathFreeObject(obj);
}
/**
@@ -376,6 +483,7 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
break;
default:
XP_ERROR(XPATH_INVALID_ARITY);
+ return;
}
valuePush(ctxt,
@@ -398,7 +506,54 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
*/
void
xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
- TODO /* function */
+ xmlNodePtr cur = NULL;
+ unsigned int val;
+ xmlChar str[20];
+
+ if (nargs == 0) {
+ cur = ctxt->context->node;
+ } else if (nargs == 1) {
+ xmlXPathObjectPtr obj;
+ xmlNodeSetPtr nodelist;
+ int i, ret;
+
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) {
+ ctxt->error = XPATH_INVALID_TYPE;
+ xsltGenericError(xsltGenericErrorContext,
+ "generate-id() : invalid arg expecting a node-set\n");
+ return;
+ }
+ obj = valuePop(ctxt);
+ nodelist = obj->nodesetval;
+ if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) {
+ ctxt->error = XPATH_INVALID_TYPE;
+ xsltGenericError(xsltGenericErrorContext,
+ "generate-id() : got an empty node-set\n");
+ xmlXPathFreeObject(obj);
+ return;
+ }
+ cur = nodelist->nodeTab[0];
+ for (i = 2;i <= nodelist->nodeNr;i++) {
+ ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]);
+ if (ret == -1)
+ cur = nodelist->nodeTab[i];
+ }
+ xmlXPathFreeObject(obj);
+ } else {
+ xsltGenericError(xsltGenericErrorContext,
+ "generate-id() : invalid number of args %d\n", nargs);
+ ctxt->error = XPATH_INVALID_ARITY;
+ return;
+ }
+ /*
+ * Okay this is ugly but should work, use the NodePtr address
+ * to forge the ID
+ */
+ val = (unsigned int) cur;
+ val >>= 2;
+ val |= 0xFFFFFF;
+ sprintf((char *)str, "id%10d", val);
+ valuePush(ctxt, xmlXPathNewString(str));
}
/**
@@ -411,7 +566,39 @@ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
*/
void
xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs){
- TODO /* function */
+ xmlXPathObjectPtr obj;
+ xmlChar *str;
+
+ if (nargs != 1) {
+ xsltGenericError(xsltGenericErrorContext,
+ "system-property() : expects one string arg\n");
+ ctxt->error = XPATH_INVALID_ARITY;
+ return;
+ }
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
+ xsltGenericError(xsltGenericErrorContext,
+ "generate-id() : invalid arg expecting a string\n");
+ ctxt->error = XPATH_INVALID_TYPE;
+ return;
+ }
+ obj = valuePop(ctxt);
+ str = obj->stringval;
+ if (str == NULL) {
+ valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
+ } else if (!xmlStrcmp(str, (const xmlChar *)"xsl:version")) {
+ valuePush(ctxt, xmlXPathNewString(
+ (const xmlChar *)XSLT_DEFAULT_VERSION));
+ } else if (!xmlStrcmp(str, (const xmlChar *)"xsl:vendor")) {
+ valuePush(ctxt, xmlXPathNewString(
+ (const xmlChar *)XSLT_DEFAULT_VENDOR));
+ } else if (!xmlStrcmp(str, (const xmlChar *)"xsl:vendor-url")) {
+ valuePush(ctxt, xmlXPathNewString(
+ (const xmlChar *)XSLT_DEFAULT_URL));
+ } else {
+ /* TODO cheated with the QName resolution */
+ valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
+ }
+ xmlXPathFreeObject(obj);
}
/**
@@ -424,7 +611,23 @@ xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs){
*/
void
xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
- TODO /* function */
+ xmlXPathObjectPtr obj;
+
+ if (nargs != 1) {
+ xsltGenericError(xsltGenericErrorContext,
+ "element-available() : expects one string arg\n");
+ ctxt->error = XPATH_INVALID_ARITY;
+ return;
+ }
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
+ xsltGenericError(xsltGenericErrorContext,
+ "element-available invalid arg expecting a string\n");
+ ctxt->error = XPATH_INVALID_TYPE;
+ return;
+ }
+ obj = valuePop(ctxt);
+ xmlXPathFreeObject(obj);
+ valuePush(ctxt, xmlXPathNewBoolean(0));
}
/**
@@ -437,7 +640,23 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
*/
void
xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
- TODO /* function */
+ xmlXPathObjectPtr obj;
+
+ if (nargs != 1) {
+ xsltGenericError(xsltGenericErrorContext,
+ "function-available() : expects one string arg\n");
+ ctxt->error = XPATH_INVALID_ARITY;
+ return;
+ }
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
+ xsltGenericError(xsltGenericErrorContext,
+ "function-available invalid arg expecting a string\n");
+ ctxt->error = XPATH_INVALID_TYPE;
+ return;
+ }
+ obj = valuePop(ctxt);
+ xmlXPathFreeObject(obj);
+ valuePush(ctxt, xmlXPathNewBoolean(0));
}
/**
@@ -450,7 +669,13 @@ xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
*/
void
xsltCurrentFunction(xmlXPathParserContextPtr ctxt, int nargs){
- TODO /* function */
+ if (nargs != 0) {
+ xsltGenericError(xsltGenericErrorContext,
+ "document() : function uses no argument\n");
+ ctxt->error = XPATH_INVALID_ARITY;
+ return;
+ }
+ valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
}
/**
diff --git a/libxslt/transform.c b/libxslt/transform.c
index 8a42a990..81eb3c96 100644
--- a/libxslt/transform.c
+++ b/libxslt/transform.c
@@ -77,8 +77,16 @@ xsltNewTransformContext(void) {
*/
void
xsltFreeTransformContext(xsltTransformContextPtr ctxt) {
+ xmlDocPtr doc, next;
+
if (ctxt == NULL)
return;
+ doc = ctxt->extraDocs;
+ while (doc != NULL) {
+ next = (xmlDocPtr) doc->next;
+ xmlFreeDoc(doc);
+ doc = next;
+ }
if (ctxt->xpathCtxt != NULL)
xmlXPathFreeContext(ctxt->xpathCtxt);
xsltFreeVariableHashes(ctxt);
@@ -373,29 +381,16 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
}
}
- value = xmlNodeListGetString(inst->doc, inst->children, 1);
+ value = xsltEvalTemplateString(ctxt, node, inst);
if (value == NULL) {
if (ns) {
-#if LIBXML_VERSION > 20211
attr = xmlSetNsProp(ctxt->insert, ns, ncname,
(const xmlChar *)"");
-#else
- xsltGenericError(xsltGenericErrorContext,
- "xsl:attribute: recompile against newer libxml version\n");
- attr = xmlSetProp(ctxt->insert, ncname, (const xmlChar *)"");
-#endif
} else
attr = xmlSetProp(ctxt->insert, ncname, (const xmlChar *)"");
} else {
- /* TODO: attribute value template */
if (ns) {
-#if LIBXML_VERSION > 20211
attr = xmlSetNsProp(ctxt->insert, ns, ncname, value);
-#else
- xsltGenericError(xsltGenericErrorContext,
- "xsl:attribute: recompile against newer libxml version\n");
- attr = xmlSetProp(ctxt->insert, ncname, value);
-#endif
} else
attr = xmlSetProp(ctxt->insert, ncname, value);
diff --git a/libxslt/variables.h b/libxslt/variables.h
index cf4b3834..bc3e450c 100644
--- a/libxslt/variables.h
+++ b/libxslt/variables.h
@@ -21,7 +21,8 @@ extern "C" {
#define XSLT_REGISTER_VARIABLE_LOOKUP(ctxt) \
xmlXPathRegisterVariableLookup((ctxt)->xpathCtxt, \
xsltXPathVariableLookup, (void *)(ctxt)); \
- xsltRegisterAllFunctions((ctxt)->xpathCtxt)
+ xsltRegisterAllFunctions((ctxt)->xpathCtxt); \
+ (ctxt)->xpathCtxt->extra = ctxt
/*
* Interfaces for the variable module.
diff --git a/libxslt/xslt.c b/libxslt/xslt.c
index 7f051efd..4d4898c9 100644
--- a/libxslt/xslt.c
+++ b/libxslt/xslt.c
@@ -493,12 +493,7 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xsltTemplatePtr ret,
XSLT_NAMESPACE);
if (prop != NULL) {
if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
-#if LIBXML_VERSION > 20211
text->name = xmlStringTextNoenc;
-#else
- xsltGenericError(xsltGenericErrorContext,
-"xsl:text disable-output-escaping need newer > 20211 libxml version\n");
-#endif
} else if (!xmlStrEqual(prop,
(const xmlChar *)"no")){
xsltGenericError(xsltGenericErrorContext,
diff --git a/libxslt/xslt.h b/libxslt/xslt.h
index 02d35243..2c658367 100644
--- a/libxslt/xslt.h
+++ b/libxslt/xslt.h
@@ -19,6 +19,8 @@ extern "C" {
* Constants.
*/
#define XSLT_DEFAULT_VERSION "1.0"
+#define XSLT_DEFAULT_VENDOR "libxslt"
+#define XSLT_DEFAULT_URL "http://xmlsoft.org/XSLT/"
#define XSLT_NAMESPACE ((xmlChar *) "http://www.w3.org/1999/XSL/Transform")
#ifdef __cplusplus
diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
index da00c133..7a645851 100644
--- a/libxslt/xsltInternals.h
+++ b/libxslt/xsltInternals.h
@@ -142,6 +142,7 @@ struct _xsltTransformContext {
xmlXPathContextPtr xpathCtxt; /* the XPath context */
void *variablesHash; /* hash table or wherever variables
informations are stored */
+ xmlDocPtr extraDocs; /* extra docs parsed by document() */
};
/*
diff --git a/libxslt/xsltutils.c b/libxslt/xsltutils.c
index 1858d6e5..ba2457a1 100644
--- a/libxslt/xsltutils.c
+++ b/libxslt/xsltutils.c
@@ -222,12 +222,7 @@ xsltSaveResultTo(xmlOutputBufferPtr buf, xmlDocPtr result,
(xmlStrEqual(style->method, (const xmlChar *) "html"))) ||
((root != NULL) &&
(xmlStrEqual(root->name, (const xmlChar *) "html")))){
-#if LIBXML_VERSION > 20211
htmlDocContentDumpOutput(buf, result, (const char *) encoding);
-#else
- xsltGenericError(xsltGenericErrorContext,
- "HTML output requires libxml version > 2.2.11\n");
-#endif
} else if ((style->method != NULL) &&
(xmlStrEqual(style->method, (const xmlChar *) "text"))) {
xmlNodePtr cur;