mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-07-31 02:43:06 +03:00
xsltlocale: Make API platform-independent
Make xsltlocale.h more private. This really is an internal header. Use LCMapStringW on Windows. Make the API platform-independent by passing locales as `void *`. Add support for custom locale handlers in a transform context. Update ICU example to use these handlers.
This commit is contained in:
@ -1,298 +1,146 @@
|
|||||||
/**
|
/**
|
||||||
* xsltICUSort.c: module provided by Richard Jinks to provide a
|
* xsltICUSort.c: module to provide a sort function replacement using ICU,
|
||||||
* sort function replacement using ICU, it is not
|
* it is not included in standard due to the size of the ICU
|
||||||
* included in standard due to the size of the ICU
|
|
||||||
* library
|
* library
|
||||||
*
|
*
|
||||||
* See http://mail.gnome.org/archives/xslt/2002-November/msg00093.html
|
* Requires libxslt 1.1.38
|
||||||
* http://oss.software.ibm.com/icu/index.html
|
|
||||||
*
|
|
||||||
* Copyright Richard Jinks
|
|
||||||
*/
|
*/
|
||||||
#define IN_LIBXSLT
|
|
||||||
#include "libxslt.h"
|
|
||||||
|
|
||||||
#include <libxml/parserInternals.h>
|
|
||||||
|
|
||||||
#include "xslt.h"
|
|
||||||
#include "xsltInternals.h"
|
|
||||||
#include "xsltutils.h"
|
|
||||||
#include "transform.h"
|
|
||||||
#include "templates.h"
|
|
||||||
|
|
||||||
|
#include <libxslt/transform.h>
|
||||||
|
#include <libxslt/xsltutils.h>
|
||||||
#include <unicode/ucnv.h>
|
#include <unicode/ucnv.h>
|
||||||
#include <unicode/ustring.h>
|
|
||||||
#include <unicode/utypes.h>
|
|
||||||
#include <unicode/uloc.h>
|
|
||||||
#include <unicode/ucol.h>
|
#include <unicode/ucol.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltICUSortFunction:
|
* xsltICUNewLocale:
|
||||||
* @ctxt: a XSLT process context
|
* @lang: lang
|
||||||
* @sorts: array of sort nodes
|
|
||||||
* @nbsorts: the number of sorts in the array
|
|
||||||
*
|
*
|
||||||
* reorder the current node list accordingly to the set of sorting
|
* Create a new ICU collator.
|
||||||
* requirement provided by the arry of nodes.
|
|
||||||
* uses the ICU library
|
|
||||||
*/
|
*/
|
||||||
void
|
void *
|
||||||
xsltICUSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
|
xsltICUNewLocale(const xmlChar *lang, int lowerFirst) {
|
||||||
int nbsorts) {
|
UCollator *coll;
|
||||||
xmlXPathObjectPtr *resultsTab[XSLT_MAX_SORT];
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
xmlXPathObjectPtr *results = NULL, *res;
|
|
||||||
xmlNodeSetPtr list = NULL;
|
|
||||||
int len = 0;
|
|
||||||
int i, j, incr;
|
|
||||||
int tst;
|
|
||||||
int depth;
|
|
||||||
xmlNodePtr node;
|
|
||||||
xmlXPathObjectPtr tmp;
|
|
||||||
const xsltStylePreComp *comp;
|
|
||||||
int number[XSLT_MAX_SORT], desc[XSLT_MAX_SORT];
|
|
||||||
|
|
||||||
/* Start ICU change */
|
coll = ucol_open((const char *) lang, &status);
|
||||||
UCollator *coll = 0;
|
if (U_FAILURE(status)) {
|
||||||
UConverter *conv;
|
|
||||||
UErrorCode status;
|
|
||||||
UChar *target,*target2;
|
|
||||||
int targetlen, target2len;
|
|
||||||
/* End ICU change */
|
|
||||||
|
|
||||||
if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
|
|
||||||
(nbsorts >= XSLT_MAX_SORT))
|
|
||||||
return;
|
|
||||||
if (sorts[0] == NULL)
|
|
||||||
return;
|
|
||||||
comp = sorts[0]->_private;
|
|
||||||
if (comp == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
list = ctxt->nodeList;
|
|
||||||
if ((list == NULL) || (list->nodeNr <= 1))
|
|
||||||
return; /* nothing to do */
|
|
||||||
|
|
||||||
for (j = 0; j < nbsorts; j++) {
|
|
||||||
comp = sorts[j]->_private;
|
|
||||||
if ((comp->stype == NULL) && (comp->has_stype != 0)) {
|
|
||||||
xmlChar *stype =
|
|
||||||
xsltEvalAttrValueTemplate(ctxt, sorts[j],
|
|
||||||
(const xmlChar *) "data-type",
|
|
||||||
XSLT_NAMESPACE);
|
|
||||||
number[j] = 0;
|
|
||||||
if (stype != NULL) {
|
|
||||||
if (xmlStrEqual(stype, (const xmlChar *) "text"))
|
|
||||||
;
|
|
||||||
else if (xmlStrEqual(stype, (const xmlChar *) "number"))
|
|
||||||
number[j] = 1;
|
|
||||||
else {
|
|
||||||
xsltTransformError(ctxt, NULL, sorts[j],
|
|
||||||
"xsltDoSortFunction: no support for data-type = %s\n",
|
|
||||||
stype);
|
|
||||||
}
|
|
||||||
xmlFree(stype);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
number[j] = comp->number;
|
|
||||||
}
|
|
||||||
if ((comp->order == NULL) && (comp->has_order != 0)) {
|
|
||||||
xmlChar *order = xsltEvalAttrValueTemplate(ctxt, sorts[j],
|
|
||||||
BAD_CAST "order",
|
|
||||||
XSLT_NAMESPACE);
|
|
||||||
desc[j] = 0;
|
|
||||||
if (order != NULL) {
|
|
||||||
if (xmlStrEqual(order, (const xmlChar *) "ascending"))
|
|
||||||
;
|
|
||||||
else if (xmlStrEqual(order, (const xmlChar *) "descending"))
|
|
||||||
desc[j] = 1;
|
|
||||||
else {
|
|
||||||
xsltTransformError(ctxt, NULL, sorts[j],
|
|
||||||
"xsltDoSortFunction: invalid value %s for order\n",
|
|
||||||
order);
|
|
||||||
}
|
|
||||||
xmlFree(order);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
desc[j] = comp->descending;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len = list->nodeNr;
|
|
||||||
|
|
||||||
resultsTab[0] = xsltComputeSortResult(ctxt, sorts[0]);
|
|
||||||
for (i = 1;i < XSLT_MAX_SORT;i++)
|
|
||||||
resultsTab[i] = NULL;
|
|
||||||
|
|
||||||
results = resultsTab[0];
|
|
||||||
|
|
||||||
comp = sorts[0]->_private;
|
|
||||||
if (results == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Start ICU change */
|
|
||||||
status = U_ZERO_ERROR;
|
|
||||||
conv = ucnv_open("UTF8", &status);
|
|
||||||
if(U_FAILURE(status)) {
|
|
||||||
xsltTransformError(ctxt, NULL, NULL, "xsltICUSortFunction: Error opening converter\n");
|
|
||||||
}
|
|
||||||
if(comp->has_lang)
|
|
||||||
coll = ucol_open((const char *) comp->lang, &status);
|
|
||||||
if(U_FAILURE(status) || !comp->has_lang) {
|
|
||||||
status = U_ZERO_ERROR;
|
status = U_ZERO_ERROR;
|
||||||
coll = ucol_open("en", &status);
|
coll = ucol_open("en", &status);
|
||||||
|
if (U_FAILURE(status)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(U_FAILURE(status)) {
|
|
||||||
xsltTransformError(ctxt, NULL, NULL, "xsltICUSortFunction: Error opening collator\n");
|
if (lowerFirst)
|
||||||
}
|
ucol_setAttribute(coll, UCOL_CASE_FIRST, UCOL_LOWER_FIRST, &status);
|
||||||
if(comp->lower_first)
|
|
||||||
ucol_setAttribute(coll,UCOL_CASE_FIRST,UCOL_LOWER_FIRST,&status);
|
|
||||||
else
|
else
|
||||||
ucol_setAttribute(coll,UCOL_CASE_FIRST,UCOL_UPPER_FIRST,&status);
|
ucol_setAttribute(coll, UCOL_CASE_FIRST, UCOL_UPPER_FIRST, &status);
|
||||||
if(U_FAILURE(status)) {
|
|
||||||
xsltTransformError(ctxt, NULL, NULL, "xsltICUSortFunction: Error setting collator attribute\n");
|
|
||||||
}
|
|
||||||
/* End ICU change */
|
|
||||||
|
|
||||||
/* Shell's sort of node-set */
|
return (void *) coll;
|
||||||
for (incr = len / 2; incr > 0; incr /= 2) {
|
|
||||||
for (i = incr; i < len; i++) {
|
|
||||||
j = i - incr;
|
|
||||||
if (results[i] == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
while (j >= 0) {
|
|
||||||
if (results[j] == NULL)
|
|
||||||
tst = 1;
|
|
||||||
else {
|
|
||||||
if (number[0]) {
|
|
||||||
if (results[j]->floatval == results[j + incr]->floatval)
|
|
||||||
tst = 0;
|
|
||||||
else if (results[j]->floatval >
|
|
||||||
results[j + incr]->floatval)
|
|
||||||
tst = 1;
|
|
||||||
else tst = -1;
|
|
||||||
} else {
|
|
||||||
/* tst = xmlStrcmp(results[j]->stringval,
|
|
||||||
results[j + incr]->stringval); */
|
|
||||||
/* Start ICU change */
|
|
||||||
targetlen = xmlStrlen(results[j]->stringval) * 2;
|
|
||||||
target2len = xmlStrlen(results[j + incr]->stringval) * 2;
|
|
||||||
target = xmlMalloc(targetlen * sizeof(UChar));
|
|
||||||
target2 = xmlMalloc(target2len * sizeof(UChar));
|
|
||||||
targetlen = ucnv_toUChars(conv, target, targetlen,
|
|
||||||
(const char *) results[j]->stringval,
|
|
||||||
-1, &status);
|
|
||||||
target2len = ucnv_toUChars(conv, target2, target2len,
|
|
||||||
(const char *) results[j+incr]->stringval,
|
|
||||||
-1, &status);
|
|
||||||
tst = ucol_strcoll(coll, target, u_strlen(target), target2, u_strlen(target2));
|
|
||||||
/* End ICU change */
|
|
||||||
}
|
|
||||||
if (desc[0])
|
|
||||||
tst = -tst;
|
|
||||||
}
|
|
||||||
if (tst == 0) {
|
|
||||||
/*
|
|
||||||
* Okay we need to use multi level sorts
|
|
||||||
*/
|
|
||||||
depth = 1;
|
|
||||||
while (depth < nbsorts) {
|
|
||||||
if (sorts[depth] == NULL)
|
|
||||||
break;
|
|
||||||
comp = sorts[depth]->_private;
|
|
||||||
if (comp == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compute the result of the next level for the
|
|
||||||
* full set, this might be optimized ... or not
|
|
||||||
*/
|
|
||||||
if (resultsTab[depth] == NULL)
|
|
||||||
resultsTab[depth] = xsltComputeSortResult(ctxt,
|
|
||||||
sorts[depth]);
|
|
||||||
res = resultsTab[depth];
|
|
||||||
if (res == NULL)
|
|
||||||
break;
|
|
||||||
if (res[j] == NULL)
|
|
||||||
tst = 1;
|
|
||||||
else {
|
|
||||||
if (number[depth]) {
|
|
||||||
if (res[j]->floatval == res[j + incr]->floatval)
|
|
||||||
tst = 0;
|
|
||||||
else if (res[j]->floatval >
|
|
||||||
res[j + incr]->floatval)
|
|
||||||
tst = 1;
|
|
||||||
else tst = -1;
|
|
||||||
} else {
|
|
||||||
/* tst = xmlStrcmp(res[j]->stringval,
|
|
||||||
res[j + incr]->stringval); */
|
|
||||||
/* Start ICU change */
|
|
||||||
targetlen = xmlStrlen(res[j]->stringval) * 2;
|
|
||||||
target2len = xmlStrlen(res[j + incr]->stringval) * 2;
|
|
||||||
target = xmlMalloc(targetlen * sizeof(UChar));
|
|
||||||
target2 = xmlMalloc(target2len * sizeof(UChar));
|
|
||||||
targetlen = ucnv_toUChars(conv, target, targetlen,
|
|
||||||
(const char *) res[j]->stringval,
|
|
||||||
-1, &status);
|
|
||||||
target2len = ucnv_toUChars(conv, target2, target2len,
|
|
||||||
(const char *) res[j+incr]->stringval,
|
|
||||||
-1, &status);
|
|
||||||
tst = ucol_strcoll(coll, target, u_strlen(target), target2, u_strlen(target2));
|
|
||||||
/* End ICU change */
|
|
||||||
}
|
|
||||||
if (desc[depth])
|
|
||||||
tst = -tst;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* if we still can't differenciate at this level
|
|
||||||
* try one level deeper.
|
|
||||||
*/
|
|
||||||
if (tst != 0)
|
|
||||||
break;
|
|
||||||
depth++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tst == 0) {
|
|
||||||
tst = results[j]->index > results[j + incr]->index;
|
|
||||||
}
|
|
||||||
if (tst > 0) {
|
|
||||||
tmp = results[j];
|
|
||||||
results[j] = results[j + incr];
|
|
||||||
results[j + incr] = tmp;
|
|
||||||
node = list->nodeTab[j];
|
|
||||||
list->nodeTab[j] = list->nodeTab[j + incr];
|
|
||||||
list->nodeTab[j + incr] = node;
|
|
||||||
depth = 1;
|
|
||||||
while (depth < nbsorts) {
|
|
||||||
if (sorts[depth] == NULL)
|
|
||||||
break;
|
|
||||||
if (resultsTab[depth] == NULL)
|
|
||||||
break;
|
|
||||||
res = resultsTab[depth];
|
|
||||||
tmp = res[j];
|
|
||||||
res[j] = res[j + incr];
|
|
||||||
res[j + incr] = tmp;
|
|
||||||
depth++;
|
|
||||||
}
|
|
||||||
j -= incr;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start ICU change */
|
|
||||||
ucol_close(coll);
|
|
||||||
ucnv_close(conv);
|
|
||||||
/* End ICU change */
|
|
||||||
|
|
||||||
for (j = 0; j < nbsorts; j++) {
|
|
||||||
comp = sorts[j]->_private;
|
|
||||||
if (resultsTab[j] != NULL) {
|
|
||||||
for (i = 0;i < len;i++)
|
|
||||||
xmlXPathFreeObject(resultsTab[j][i]);
|
|
||||||
xmlFree(resultsTab[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltICUNewLocale:
|
||||||
|
* @locale: ICU collator
|
||||||
|
*
|
||||||
|
* Free the ICU collator.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltICUFreeLocale(void *coll) {
|
||||||
|
ucol_close((UCollator *) coll);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltICUGenSortKey:
|
||||||
|
* @locale: ICU collator
|
||||||
|
* @str: source string
|
||||||
|
*
|
||||||
|
* Generate a localized sort key.
|
||||||
|
*/
|
||||||
|
xmlChar *
|
||||||
|
xsltICUGenSortKey(void *coll, const xmlChar *str) {
|
||||||
|
UConverter *conv;
|
||||||
|
UChar *ustr = NULL;
|
||||||
|
xmlChar *result = NULL;
|
||||||
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
|
int32_t ustrLen, resultLen;
|
||||||
|
|
||||||
|
conv = ucnv_open("UTF8", &status);
|
||||||
|
if (U_FAILURE(status))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ustrLen = ucnv_toUChars(conv, NULL, 0, (const char *) str, -1, &status);
|
||||||
|
if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
|
||||||
|
goto error;
|
||||||
|
status = U_ZERO_ERROR;
|
||||||
|
ustr = (UChar *) xmlMalloc((ustrLen + 1) * sizeof(UChar));
|
||||||
|
if (ustr == NULL)
|
||||||
|
goto error;
|
||||||
|
ustrLen = ucnv_toUChars(conv, ustr, ustrLen, (const char *) str, -1,
|
||||||
|
&status);
|
||||||
|
if (U_FAILURE(status))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
resultLen = ucol_getSortKey((UCollator *) coll, ustr, ustrLen, NULL, 0);
|
||||||
|
if (resultLen == 0)
|
||||||
|
goto error;
|
||||||
|
result = (xmlChar *) xmlMalloc(resultLen);
|
||||||
|
if (result == NULL)
|
||||||
|
goto error;
|
||||||
|
resultLen = ucol_getSortKey((UCollator *) coll, ustr, ustrLen, result,
|
||||||
|
resultLen);
|
||||||
|
if (resultLen == 0) {
|
||||||
|
xmlFree(result);
|
||||||
|
result = NULL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
xmlFree(ustr);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
xmlDocPtr sourceDoc = xmlReadDoc(
|
||||||
|
BAD_CAST
|
||||||
|
"<d>\n"
|
||||||
|
" <e>Berta</e>\n"
|
||||||
|
" <e>Ärger</e>\n"
|
||||||
|
"</d>\n",
|
||||||
|
NULL, NULL, 0
|
||||||
|
);
|
||||||
|
xmlDocPtr styleDoc = xmlReadDoc(
|
||||||
|
BAD_CAST
|
||||||
|
"<xsl:stylesheet"
|
||||||
|
" version='1.0'"
|
||||||
|
" xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>\n"
|
||||||
|
" <xsl:template match='d'>\n"
|
||||||
|
" <xsl:for-each select='*'>\n"
|
||||||
|
" <xsl:sort lang='de'/>\n"
|
||||||
|
" <xsl:copy-of select='.'/>\n"
|
||||||
|
" </xsl:for-each>\n"
|
||||||
|
" </xsl:template>\n"
|
||||||
|
"</xsl:stylesheet>\n",
|
||||||
|
NULL, NULL, 0
|
||||||
|
);
|
||||||
|
xsltStylesheetPtr style = xsltParseStylesheetDoc(styleDoc);
|
||||||
|
if (style == NULL)
|
||||||
|
xmlFreeDoc(styleDoc);
|
||||||
|
|
||||||
|
xsltTransformContextPtr tctxt = xsltNewTransformContext(style, sourceDoc);
|
||||||
|
xsltSetCtxtLocaleHandlers(tctxt, xsltICUNewLocale, xsltICUFreeLocale,
|
||||||
|
xsltICUGenSortKey);
|
||||||
|
|
||||||
|
xmlDocPtr resultDoc = xsltApplyStylesheetUser(style, sourceDoc, NULL, NULL,
|
||||||
|
NULL, tctxt);
|
||||||
|
|
||||||
|
xsltFreeTransformContext(tctxt);
|
||||||
|
|
||||||
|
xsltSaveResultToFile(stdout, resultDoc, style);
|
||||||
|
|
||||||
|
xmlFreeDoc(resultDoc);
|
||||||
|
xsltFreeStylesheet(style);
|
||||||
|
xmlFreeDoc(sourceDoc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <libxml/xmlIO.h>
|
#include <libxml/xmlIO.h>
|
||||||
#include "xslt.h"
|
#include "xslt.h"
|
||||||
#include "xsltInternals.h"
|
#include "xsltInternals.h"
|
||||||
|
#include "xsltlocale.h"
|
||||||
#include "xsltutils.h"
|
#include "xsltutils.h"
|
||||||
#include "imports.h"
|
#include "imports.h"
|
||||||
#include "extensions.h"
|
#include "extensions.h"
|
||||||
|
@ -392,8 +392,6 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
|
|||||||
break;
|
break;
|
||||||
case XSLT_FUNC_SORT: {
|
case XSLT_FUNC_SORT: {
|
||||||
xsltStyleItemSortPtr item = (xsltStyleItemSortPtr) comp;
|
xsltStyleItemSortPtr item = (xsltStyleItemSortPtr) comp;
|
||||||
if (item->locale != (xsltLocale)0)
|
|
||||||
xsltFreeLocale(item->locale);
|
|
||||||
if (item->comp != NULL)
|
if (item->comp != NULL)
|
||||||
xmlXPathFreeCompExpr(item->comp);
|
xmlXPathFreeCompExpr(item->comp);
|
||||||
}
|
}
|
||||||
@ -496,8 +494,6 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (comp->locale != (xsltLocale)0)
|
|
||||||
xsltFreeLocale(comp->locale);
|
|
||||||
if (comp->comp != NULL)
|
if (comp->comp != NULL)
|
||||||
xmlXPathFreeCompExpr(comp->comp);
|
xmlXPathFreeCompExpr(comp->comp);
|
||||||
if (comp->numdata.countPat != NULL)
|
if (comp->numdata.countPat != NULL)
|
||||||
@ -743,12 +739,6 @@ xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {
|
|||||||
comp->lang = xsltEvalStaticAttrValueTemplate(style, inst,
|
comp->lang = xsltEvalStaticAttrValueTemplate(style, inst,
|
||||||
(const xmlChar *)"lang",
|
(const xmlChar *)"lang",
|
||||||
NULL, &comp->has_lang);
|
NULL, &comp->has_lang);
|
||||||
if (comp->lang != NULL) {
|
|
||||||
comp->locale = xsltNewLocale(comp->lang);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
comp->locale = (xsltLocale)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE);
|
comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE);
|
||||||
if (comp->select == NULL) {
|
if (comp->select == NULL) {
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "xslt.h"
|
#include "xslt.h"
|
||||||
#include "xsltInternals.h"
|
#include "xsltInternals.h"
|
||||||
#include "xsltutils.h"
|
#include "xsltutils.h"
|
||||||
|
#include "xsltlocale.h"
|
||||||
#include "pattern.h"
|
#include "pattern.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
@ -706,6 +707,10 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
|
|||||||
cur->xinclude = xsltGetXIncludeDefault();
|
cur->xinclude = xsltGetXIncludeDefault();
|
||||||
cur->keyInitLevel = 0;
|
cur->keyInitLevel = 0;
|
||||||
|
|
||||||
|
cur->newLocale = xsltNewLocale;
|
||||||
|
cur->freeLocale = xsltFreeLocale;
|
||||||
|
cur->genSortKey = xsltStrxfrm;
|
||||||
|
|
||||||
return(cur);
|
return(cur);
|
||||||
|
|
||||||
internal_err:
|
internal_err:
|
||||||
@ -716,7 +721,7 @@ internal_err:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltFreeTransformContext:
|
* xsltFreeTransformContext:
|
||||||
* @ctxt: an XSLT parser context
|
* @ctxt: an XSLT transform context
|
||||||
*
|
*
|
||||||
* Free up the memory allocated by @ctxt
|
* Free up the memory allocated by @ctxt
|
||||||
*/
|
*/
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include <libxml/xmlstring.h>
|
#include <libxml/xmlstring.h>
|
||||||
#include <libxslt/xslt.h>
|
#include <libxslt/xslt.h>
|
||||||
#include "xsltexports.h"
|
#include "xsltexports.h"
|
||||||
#include "xsltlocale.h"
|
|
||||||
#include "numbersInternals.h"
|
#include "numbersInternals.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -1047,7 +1046,6 @@ struct _xsltStyleItemSort {
|
|||||||
int descending; /* sort */
|
int descending; /* sort */
|
||||||
const xmlChar *lang; /* sort */
|
const xmlChar *lang; /* sort */
|
||||||
int has_lang; /* sort */
|
int has_lang; /* sort */
|
||||||
xsltLocale locale; /* sort */
|
|
||||||
const xmlChar *case_order; /* sort */
|
const xmlChar *case_order; /* sort */
|
||||||
int lower_first; /* sort */
|
int lower_first; /* sort */
|
||||||
|
|
||||||
@ -1377,7 +1375,6 @@ struct _xsltStylePreComp {
|
|||||||
int descending; /* sort */
|
int descending; /* sort */
|
||||||
const xmlChar *lang; /* sort */
|
const xmlChar *lang; /* sort */
|
||||||
int has_lang; /* sort */
|
int has_lang; /* sort */
|
||||||
xsltLocale locale; /* sort */
|
|
||||||
const xmlChar *case_order; /* sort */
|
const xmlChar *case_order; /* sort */
|
||||||
int lower_first; /* sort */
|
int lower_first; /* sort */
|
||||||
|
|
||||||
@ -1663,6 +1660,13 @@ typedef enum {
|
|||||||
XSLT_OUTPUT_TEXT
|
XSLT_OUTPUT_TEXT
|
||||||
} xsltOutputType;
|
} xsltOutputType;
|
||||||
|
|
||||||
|
typedef void *
|
||||||
|
(*xsltNewLocaleFunc)(const xmlChar *lang, int lowerFirst);
|
||||||
|
typedef void
|
||||||
|
(*xsltFreeLocaleFunc)(void *locale);
|
||||||
|
typedef xmlChar *
|
||||||
|
(*xsltGenSortKeFunc)(void *locale, const xmlChar *lang);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
XSLT_STATE_OK = 0,
|
XSLT_STATE_OK = 0,
|
||||||
XSLT_STATE_ERROR,
|
XSLT_STATE_ERROR,
|
||||||
@ -1788,6 +1792,10 @@ struct _xsltTransformContext {
|
|||||||
unsigned long opCount;
|
unsigned long opCount;
|
||||||
int sourceDocDirty;
|
int sourceDocDirty;
|
||||||
unsigned long currentId; /* For generate-id() */
|
unsigned long currentId; /* For generate-id() */
|
||||||
|
|
||||||
|
xsltNewLocaleFunc newLocale;
|
||||||
|
xsltFreeLocaleFunc freeLocale;
|
||||||
|
xsltGenSortKeFunc genSortKey;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +19,30 @@
|
|||||||
#include "xsltlocale.h"
|
#include "xsltlocale.h"
|
||||||
#include "xsltutils.h"
|
#include "xsltutils.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_STRXFRM_L
|
||||||
|
|
||||||
|
#define XSLT_LOCALE_POSIX
|
||||||
|
|
||||||
|
#ifdef HAVE_LOCALE_H
|
||||||
|
#include <locale.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_XLOCALE_H
|
||||||
|
#include <xlocale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
|
||||||
|
#define XSLT_LOCALE_WINAPI
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winnls.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define XSLT_LOCALE_NONE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TOUPPER(c) (c & ~0x20)
|
#define TOUPPER(c) (c & ~0x20)
|
||||||
#define TOLOWER(c) (c | 0x20)
|
#define TOLOWER(c) (c | 0x20)
|
||||||
#define ISALPHA(c) ((unsigned)(TOUPPER(c) - 'A') < 26)
|
#define ISALPHA(c) ((unsigned)(TOUPPER(c) - 'A') < 26)
|
||||||
@ -37,8 +61,7 @@ xmlRMutexPtr xsltLocaleMutex = NULL;
|
|||||||
struct xsltRFC1766Info_s {
|
struct xsltRFC1766Info_s {
|
||||||
/*note typedef unsigned char xmlChar !*/
|
/*note typedef unsigned char xmlChar !*/
|
||||||
xmlChar tag[XSLTMAX_LANGTAGLEN+1];
|
xmlChar tag[XSLTMAX_LANGTAGLEN+1];
|
||||||
/*note typedef LCID xsltLocale !*/
|
LCID lcid;
|
||||||
xsltLocale lcid;
|
|
||||||
};
|
};
|
||||||
typedef struct xsltRFC1766Info_s xsltRFC1766Info;
|
typedef struct xsltRFC1766Info_s xsltRFC1766Info;
|
||||||
|
|
||||||
@ -46,14 +69,15 @@ static int xsltLocaleListSize = 0;
|
|||||||
static xsltRFC1766Info *xsltLocaleList = NULL;
|
static xsltRFC1766Info *xsltLocaleList = NULL;
|
||||||
|
|
||||||
|
|
||||||
static xsltLocale
|
static void *
|
||||||
xslt_locale_WINAPI(const xmlChar *languageTag) {
|
xslt_locale_WINAPI(const xmlChar *languageTag) {
|
||||||
int k;
|
int k;
|
||||||
xsltRFC1766Info *p = xsltLocaleList;
|
xsltRFC1766Info *p = xsltLocaleList;
|
||||||
|
|
||||||
for (k=0; k<xsltLocaleListSize; k++, p++)
|
for (k=0; k<xsltLocaleListSize; k++, p++)
|
||||||
if (xmlStrcmp(p->tag, languageTag) == 0) return p->lcid;
|
if (xmlStrcmp(p->tag, languageTag) == 0)
|
||||||
return((xsltLocale)0);
|
return(&p->lcid);
|
||||||
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xsltEnumSupportedLocales(void);
|
static void xsltEnumSupportedLocales(void);
|
||||||
@ -83,10 +107,10 @@ xsltFreeLocales(void) {
|
|||||||
*
|
*
|
||||||
* Returns the locale or NULL on error or if no matching locale was found
|
* Returns the locale or NULL on error or if no matching locale was found
|
||||||
*/
|
*/
|
||||||
xsltLocale
|
void *
|
||||||
xsltNewLocale(const xmlChar *languageTag) {
|
xsltNewLocale(const xmlChar *languageTag, int lowerFirst ATTRIBUTE_UNUSED) {
|
||||||
#ifdef XSLT_LOCALE_POSIX
|
#ifdef XSLT_LOCALE_POSIX
|
||||||
xsltLocale locale;
|
locale_t locale;
|
||||||
char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */
|
char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */
|
||||||
const xmlChar *p = languageTag;
|
const xmlChar *p = languageTag;
|
||||||
const char *region = NULL;
|
const char *region = NULL;
|
||||||
@ -155,7 +179,7 @@ xsltNewLocale(const xmlChar *languageTag) {
|
|||||||
|
|
||||||
#ifdef XSLT_LOCALE_WINAPI
|
#ifdef XSLT_LOCALE_WINAPI
|
||||||
{
|
{
|
||||||
xsltLocale locale = (xsltLocale)0;
|
void *locale = NULL;
|
||||||
xmlChar localeName[XSLTMAX_LANGTAGLEN+1];
|
xmlChar localeName[XSLTMAX_LANGTAGLEN+1];
|
||||||
xmlChar *q = localeName;
|
xmlChar *q = localeName;
|
||||||
const xmlChar *p = languageTag;
|
const xmlChar *p = languageTag;
|
||||||
@ -344,7 +368,7 @@ xsltDefaultRegion(const xmlChar *localeName) {
|
|||||||
* Frees a locale created with xsltNewLocale
|
* Frees a locale created with xsltNewLocale
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xsltFreeLocale(xsltLocale locale) {
|
xsltFreeLocale(void *locale) {
|
||||||
#ifdef XSLT_LOCALE_POSIX
|
#ifdef XSLT_LOCALE_POSIX
|
||||||
if (locale != NULL)
|
if (locale != NULL)
|
||||||
freelocale(locale);
|
freelocale(locale);
|
||||||
@ -358,58 +382,82 @@ xsltFreeLocale(xsltLocale locale) {
|
|||||||
* @locale: locale created with xsltNewLocale
|
* @locale: locale created with xsltNewLocale
|
||||||
* @string: UTF-8 string to transform
|
* @string: UTF-8 string to transform
|
||||||
*
|
*
|
||||||
* Transforms a string according to locale. The transformed string must then be
|
* Transforms a string according to locale. The transformed string must be
|
||||||
* compared with xsltLocaleStrcmp and freed with xmlFree.
|
* freed with xmlFree.
|
||||||
*
|
*
|
||||||
* Returns the transformed string or NULL on error
|
* Returns the transformed string or NULL on error
|
||||||
*/
|
*/
|
||||||
xsltLocaleChar *
|
xmlChar *
|
||||||
xsltStrxfrm(xsltLocale locale, const xmlChar *string)
|
xsltStrxfrm(void *vlocale, const xmlChar *string)
|
||||||
{
|
{
|
||||||
#ifdef XSLT_LOCALE_NONE
|
#ifdef XSLT_LOCALE_NONE
|
||||||
return(NULL);
|
return(NULL);
|
||||||
#else
|
#else
|
||||||
size_t xstrlen, r;
|
xmlChar *xstr;
|
||||||
xsltLocaleChar *xstr;
|
|
||||||
|
|
||||||
#ifdef XSLT_LOCALE_POSIX
|
#ifdef XSLT_LOCALE_POSIX
|
||||||
xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1;
|
size_t xstrlen, r;
|
||||||
xstr = (xsltLocaleChar *) xmlMalloc(xstrlen);
|
|
||||||
|
xstrlen = strxfrm_l(NULL, (const char *)string, 0, vlocale) + 1;
|
||||||
|
xstr = (xmlChar *) xmlMalloc(xstrlen);
|
||||||
if (xstr == NULL) {
|
if (xstr == NULL) {
|
||||||
xsltTransformError(NULL, NULL, NULL,
|
xsltTransformError(NULL, NULL, NULL,
|
||||||
"xsltStrxfrm : out of memory error\n");
|
"xsltStrxfrm : out of memory error\n");
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, locale);
|
r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, vlocale);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef XSLT_LOCALE_WINAPI
|
|
||||||
(void) locale;
|
|
||||||
xstrlen = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, NULL, 0);
|
|
||||||
if (xstrlen == 0) {
|
|
||||||
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
xstr = (xsltLocaleChar*) xmlMalloc(xstrlen * sizeof(xsltLocaleChar));
|
|
||||||
if (xstr == NULL) {
|
|
||||||
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
r = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, xstr, xstrlen);
|
|
||||||
if (r == 0) {
|
|
||||||
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
|
|
||||||
xmlFree(xstr);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
return(xstr);
|
|
||||||
#endif /* XSLT_LOCALE_WINAPI */
|
|
||||||
|
|
||||||
if (r >= xstrlen) {
|
if (r >= xstrlen) {
|
||||||
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n");
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n");
|
||||||
xmlFree(xstr);
|
xmlFree(xstr);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XSLT_LOCALE_WINAPI
|
||||||
|
int wstrlen, xstrlen, r;
|
||||||
|
wchar_t *wstr;
|
||||||
|
LCID *lcid = vlocale;
|
||||||
|
|
||||||
|
wstrlen = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, NULL, 0);
|
||||||
|
if (wstrlen == 0) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
wstr = (wchar_t *) xmlMalloc(wstrlen * sizeof(wchar_t));
|
||||||
|
if (wstr == NULL) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
r = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, wstr, wstrlen);
|
||||||
|
if (r == 0) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
|
||||||
|
xmlFree(wstr);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
/* This returns the size in bytes. */
|
||||||
|
xstrlen = LCMapStringW(*lcid, LCMAP_SORTKEY, wstr, wstrlen, NULL, 0);
|
||||||
|
if (xstrlen == 0) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : LCMapStringW failed\n");
|
||||||
|
xmlFree(wstr);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
xstr = (xmlChar*) xmlMalloc(xstrlen);
|
||||||
|
if (xstr == NULL) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
|
||||||
|
xmlFree(wstr);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
r = LCMapStringW(*lcid, LCMAP_SORTKEY, wstr, wstrlen, (wchar_t *) xstr,
|
||||||
|
xstrlen);
|
||||||
|
xmlFree(wstr);
|
||||||
|
if (r == 0) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : LCMapStringW failed\n");
|
||||||
|
xmlFree(xstr);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
#endif /* XSLT_LOCALE_WINAPI */
|
||||||
|
|
||||||
return(xstr);
|
return(xstr);
|
||||||
#endif /* XSLT_LOCALE_NONE */
|
#endif /* XSLT_LOCALE_NONE */
|
||||||
@ -417,35 +465,22 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltLocaleStrcmp:
|
* xsltLocaleStrcmp:
|
||||||
* @locale: a locale identifier
|
* @locale: unused
|
||||||
* @str1: a string transformed with xsltStrxfrm
|
* @str1: a string transformed with xsltStrxfrm
|
||||||
* @str2: a string transformed with xsltStrxfrm
|
* @str2: a string transformed with xsltStrxfrm
|
||||||
*
|
*
|
||||||
* Compares two strings transformed with xsltStrxfrm
|
* DEPRECATED: Same as xmlStrcmp.
|
||||||
|
*
|
||||||
|
* Compares two strings transformed with xsltStrxfrm.
|
||||||
*
|
*
|
||||||
* Returns a value < 0 if str1 sorts before str2,
|
* Returns a value < 0 if str1 sorts before str2,
|
||||||
* a value > 0 if str1 sorts after str2,
|
* a value > 0 if str1 sorts after str2,
|
||||||
* 0 if str1 and str2 are equal wrt sorting
|
* 0 if str1 and str2 are equal wrt sorting
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xsltLocaleStrcmp(xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2) {
|
xsltLocaleStrcmp(void *locale, const xmlChar *str1, const xmlChar *str2) {
|
||||||
(void)locale;
|
(void)locale;
|
||||||
#ifdef XSLT_LOCALE_WINAPI
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
if (str1 == str2) return(0);
|
|
||||||
if (str1 == NULL) return(-1);
|
|
||||||
if (str2 == NULL) return(1);
|
|
||||||
ret = CompareStringW(locale, 0, str1, -1, str2, -1);
|
|
||||||
if (ret == 0) {
|
|
||||||
xsltTransformError(NULL, NULL, NULL, "xsltLocaleStrcmp : CompareStringW fail\n");
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
return(ret - 2);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return(xmlStrcmp(str1, str2));
|
return(xmlStrcmp(str1, str2));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XSLT_LOCALE_WINAPI
|
#ifdef XSLT_LOCALE_WINAPI
|
||||||
|
@ -14,63 +14,23 @@
|
|||||||
#include <libxml/xmlstring.h>
|
#include <libxml/xmlstring.h>
|
||||||
#include "xsltexports.h"
|
#include "xsltexports.h"
|
||||||
|
|
||||||
#ifdef HAVE_STRXFRM_L
|
XSLTPUBFUN void * XSLTCALL
|
||||||
|
xsltNewLocale (const xmlChar *langName,
|
||||||
/*
|
int lowerFirst);
|
||||||
* XSLT_LOCALE_POSIX:
|
|
||||||
* Macro indicating to use POSIX locale extensions
|
|
||||||
*/
|
|
||||||
#define XSLT_LOCALE_POSIX
|
|
||||||
|
|
||||||
#ifdef HAVE_LOCALE_H
|
|
||||||
#include <locale.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_XLOCALE_H
|
|
||||||
#include <xlocale.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef locale_t xsltLocale;
|
|
||||||
typedef xmlChar xsltLocaleChar;
|
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XSLT_LOCALE_WINAPI:
|
|
||||||
* Macro indicating to use WinAPI for extended locale support
|
|
||||||
*/
|
|
||||||
#define XSLT_LOCALE_WINAPI
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <winnls.h>
|
|
||||||
|
|
||||||
typedef LCID xsltLocale;
|
|
||||||
typedef wchar_t xsltLocaleChar;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XSLT_LOCALE_NONE:
|
|
||||||
* Macro indicating that there's no extended locale support
|
|
||||||
*/
|
|
||||||
#define XSLT_LOCALE_NONE
|
|
||||||
|
|
||||||
typedef void *xsltLocale;
|
|
||||||
typedef xmlChar xsltLocaleChar;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
XSLTPUBFUN xsltLocale XSLTCALL
|
|
||||||
xsltNewLocale (const xmlChar *langName);
|
|
||||||
XSLTPUBFUN void XSLTCALL
|
XSLTPUBFUN void XSLTCALL
|
||||||
xsltFreeLocale (xsltLocale locale);
|
xsltFreeLocale (void *locale);
|
||||||
XSLTPUBFUN xsltLocaleChar * XSLTCALL
|
XSLTPUBFUN xmlChar * XSLTCALL
|
||||||
xsltStrxfrm (xsltLocale locale,
|
xsltStrxfrm (void *locale,
|
||||||
const xmlChar *string);
|
const xmlChar *string);
|
||||||
XSLTPUBFUN int XSLTCALL
|
|
||||||
xsltLocaleStrcmp (xsltLocale locale,
|
|
||||||
const xsltLocaleChar *str1,
|
|
||||||
const xsltLocaleChar *str2);
|
|
||||||
XSLTPUBFUN void XSLTCALL
|
XSLTPUBFUN void XSLTCALL
|
||||||
xsltFreeLocales (void);
|
xsltFreeLocales (void);
|
||||||
|
|
||||||
|
/* Backward compatibility */
|
||||||
|
typedef void *xsltLocale;
|
||||||
|
typedef xmlChar xsltLocaleChar;
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltLocaleStrcmp (void *locale,
|
||||||
|
const xmlChar *str1,
|
||||||
|
const xmlChar *str2);
|
||||||
|
|
||||||
#endif /* __XML_XSLTLOCALE_H__ */
|
#endif /* __XML_XSLTLOCALE_H__ */
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
#define XSLT_WIN32_PERFORMANCE_COUNTER
|
#define XSLT_WIN32_PERFORMANCE_COUNTER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -960,7 +961,7 @@ xsltDocumentSortFunction(xmlNodeSetPtr list) {
|
|||||||
*/
|
*/
|
||||||
static xmlXPathObjectPtr *
|
static xmlXPathObjectPtr *
|
||||||
xsltComputeSortResultInternal(xsltTransformContextPtr ctxt, xmlNodePtr sort,
|
xsltComputeSortResultInternal(xsltTransformContextPtr ctxt, xmlNodePtr sort,
|
||||||
int number, xsltLocale locale) {
|
int number, void *locale) {
|
||||||
#ifdef XSLT_REFACTORED
|
#ifdef XSLT_REFACTORED
|
||||||
xsltStyleItemSortPtr comp;
|
xsltStyleItemSortPtr comp;
|
||||||
#else
|
#else
|
||||||
@ -1047,10 +1048,17 @@ xsltComputeSortResultInternal(xsltTransformContextPtr ctxt, xmlNodePtr sort,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (res->type == XPATH_STRING) {
|
if (res->type == XPATH_STRING) {
|
||||||
if (locale != (xsltLocale)0) {
|
if (locale != NULL) {
|
||||||
xmlChar *str = res->stringval;
|
xmlChar *str = res->stringval;
|
||||||
res->stringval = (xmlChar *) xsltStrxfrm(locale, str);
|
xmlChar *sortKey = ctxt->genSortKey(locale, str);
|
||||||
xmlFree(str);
|
|
||||||
|
if (sortKey == NULL) {
|
||||||
|
xsltTransformError(ctxt, NULL, sort,
|
||||||
|
"xsltComputeSortResult: sort key is null\n");
|
||||||
|
} else {
|
||||||
|
res->stringval = sortKey;
|
||||||
|
xmlFree(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
results[i] = res;
|
results[i] = res;
|
||||||
@ -1094,7 +1102,8 @@ xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) {
|
|||||||
|
|
||||||
if (comp != NULL)
|
if (comp != NULL)
|
||||||
number = comp->number;
|
number = comp->number;
|
||||||
return xsltComputeSortResultInternal(ctxt, sort, number, /* locale */ 0);
|
return xsltComputeSortResultInternal(ctxt, sort, number,
|
||||||
|
/* locale */ NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1124,7 +1133,7 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
|
|||||||
xmlNodePtr node;
|
xmlNodePtr node;
|
||||||
xmlXPathObjectPtr tmp;
|
xmlXPathObjectPtr tmp;
|
||||||
int number[XSLT_MAX_SORT], desc[XSLT_MAX_SORT];
|
int number[XSLT_MAX_SORT], desc[XSLT_MAX_SORT];
|
||||||
xsltLocale locale[XSLT_MAX_SORT];
|
void *locale[XSLT_MAX_SORT];
|
||||||
|
|
||||||
if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
|
if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
|
||||||
(nbsorts >= XSLT_MAX_SORT))
|
(nbsorts >= XSLT_MAX_SORT))
|
||||||
@ -1140,6 +1149,8 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
|
|||||||
return; /* nothing to do */
|
return; /* nothing to do */
|
||||||
|
|
||||||
for (j = 0; j < nbsorts; j++) {
|
for (j = 0; j < nbsorts; j++) {
|
||||||
|
xmlChar *lang;
|
||||||
|
|
||||||
comp = sorts[j]->psvi;
|
comp = sorts[j]->psvi;
|
||||||
if ((comp->stype == NULL) && (comp->has_stype != 0)) {
|
if ((comp->stype == NULL) && (comp->has_stype != 0)) {
|
||||||
xmlChar *stype =
|
xmlChar *stype =
|
||||||
@ -1181,17 +1192,18 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
|
|||||||
desc[j] = comp->descending;
|
desc[j] = comp->descending;
|
||||||
}
|
}
|
||||||
if ((comp->lang == NULL) && (comp->has_lang != 0)) {
|
if ((comp->lang == NULL) && (comp->has_lang != 0)) {
|
||||||
xmlChar *lang = xsltEvalAttrValueTemplate(ctxt, sorts[j],
|
lang = xsltEvalAttrValueTemplate(ctxt, sorts[j],
|
||||||
(xmlChar *) "lang",
|
(xmlChar *) "lang",
|
||||||
NULL);
|
NULL);
|
||||||
if (lang != NULL) {
|
|
||||||
locale[j] = xsltNewLocale(lang);
|
|
||||||
xmlFree(lang);
|
|
||||||
} else {
|
|
||||||
locale[j] = 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
locale[j] = comp->locale;
|
lang = (xmlChar *) comp->lang;
|
||||||
|
}
|
||||||
|
if (lang != NULL) {
|
||||||
|
locale[j] = ctxt->newLocale(lang, comp->lower_first);
|
||||||
|
if (lang != comp->lang)
|
||||||
|
xmlFree(lang);
|
||||||
|
} else {
|
||||||
|
locale[j] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1236,11 +1248,6 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
|
|||||||
results[j + incr]->floatval)
|
results[j + incr]->floatval)
|
||||||
tst = 1;
|
tst = 1;
|
||||||
else tst = -1;
|
else tst = -1;
|
||||||
} else if(locale[0] != (xsltLocale)0) {
|
|
||||||
tst = xsltLocaleStrcmp(
|
|
||||||
locale[0],
|
|
||||||
(xsltLocaleChar *) results[j]->stringval,
|
|
||||||
(xsltLocaleChar *) results[j + incr]->stringval);
|
|
||||||
} else {
|
} else {
|
||||||
tst = xmlStrcmp(results[j]->stringval,
|
tst = xmlStrcmp(results[j]->stringval,
|
||||||
results[j + incr]->stringval);
|
results[j + incr]->stringval);
|
||||||
@ -1298,11 +1305,6 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
|
|||||||
res[j + incr]->floatval)
|
res[j + incr]->floatval)
|
||||||
tst = 1;
|
tst = 1;
|
||||||
else tst = -1;
|
else tst = -1;
|
||||||
} else if(locale[depth] != (xsltLocale)0) {
|
|
||||||
tst = xsltLocaleStrcmp(
|
|
||||||
locale[depth],
|
|
||||||
(xsltLocaleChar *) res[j]->stringval,
|
|
||||||
(xsltLocaleChar *) res[j + incr]->stringval);
|
|
||||||
} else {
|
} else {
|
||||||
tst = xmlStrcmp(res[j]->stringval,
|
tst = xmlStrcmp(res[j]->stringval,
|
||||||
res[j + incr]->stringval);
|
res[j + incr]->stringval);
|
||||||
@ -1353,8 +1355,8 @@ cleanup:
|
|||||||
for (j = 0; j < nbsorts; j++) {
|
for (j = 0; j < nbsorts; j++) {
|
||||||
comp = sorts[j]->psvi;
|
comp = sorts[j]->psvi;
|
||||||
if ((comp->lang == NULL) && (comp->has_lang != 0)) {
|
if ((comp->lang == NULL) && (comp->has_lang != 0)) {
|
||||||
if (locale[j] != (xsltLocale)0) {
|
if (locale[j] != NULL) {
|
||||||
xsltFreeLocale(locale[j]);
|
ctxt->freeLocale(locale[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (resultsTab[j] != NULL) {
|
if (resultsTab[j] != NULL) {
|
||||||
@ -1396,6 +1398,8 @@ xsltDoSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr * sorts,
|
|||||||
* xsltSetSortFunc:
|
* xsltSetSortFunc:
|
||||||
* @handler: the new handler function
|
* @handler: the new handler function
|
||||||
*
|
*
|
||||||
|
* DEPRECATED: Use xsltSetCtxtLocaleHandlers.
|
||||||
|
*
|
||||||
* Function to reset the global handler for XSLT sorting.
|
* Function to reset the global handler for XSLT sorting.
|
||||||
* If the handler is NULL, the default sort function will be used.
|
* If the handler is NULL, the default sort function will be used.
|
||||||
*/
|
*/
|
||||||
@ -1412,6 +1416,8 @@ xsltSetSortFunc(xsltSortFunc handler) {
|
|||||||
* @ctxt: a XSLT process context
|
* @ctxt: a XSLT process context
|
||||||
* @handler: the new handler function
|
* @handler: the new handler function
|
||||||
*
|
*
|
||||||
|
* DEPRECATED: Use xsltSetCtxtLocaleHandlers.
|
||||||
|
*
|
||||||
* Function to set the handler for XSLT sorting
|
* Function to set the handler for XSLT sorting
|
||||||
* for the specified context.
|
* for the specified context.
|
||||||
* If the handler is NULL, then the global
|
* If the handler is NULL, then the global
|
||||||
@ -1422,6 +1428,28 @@ xsltSetCtxtSortFunc(xsltTransformContextPtr ctxt, xsltSortFunc handler) {
|
|||||||
ctxt->sortfunc = handler;
|
ctxt->sortfunc = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltSetCtxtLocaleHandlers:
|
||||||
|
* @ctxt: an XSLT transform context
|
||||||
|
* @newLocale: locale constructor
|
||||||
|
* @freeLocale: locale destructor
|
||||||
|
* @genSortKey sort key generator
|
||||||
|
*
|
||||||
|
* Set the locale handlers.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltSetCtxtLocaleHandlers(xsltTransformContextPtr ctxt,
|
||||||
|
xsltNewLocaleFunc newLocale,
|
||||||
|
xsltFreeLocaleFunc freeLocale,
|
||||||
|
xsltGenSortKeFunc genSortKey) {
|
||||||
|
if (ctxt == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ctxt->newLocale = newLocale;
|
||||||
|
ctxt->freeLocale = freeLocale;
|
||||||
|
ctxt->genSortKey = genSortKey;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* *
|
* *
|
||||||
* Parsing options *
|
* Parsing options *
|
||||||
|
@ -178,6 +178,11 @@ XSLTPUBFUN void XSLTCALL
|
|||||||
XSLTPUBFUN void XSLTCALL
|
XSLTPUBFUN void XSLTCALL
|
||||||
xsltSetCtxtSortFunc (xsltTransformContextPtr ctxt,
|
xsltSetCtxtSortFunc (xsltTransformContextPtr ctxt,
|
||||||
xsltSortFunc handler);
|
xsltSortFunc handler);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSetCtxtLocaleHandlers (xsltTransformContextPtr ctxt,
|
||||||
|
xsltNewLocaleFunc newLocale,
|
||||||
|
xsltFreeLocaleFunc freeLocale,
|
||||||
|
xsltGenSortKeFunc genSortKey);
|
||||||
XSLTPUBFUN void XSLTCALL
|
XSLTPUBFUN void XSLTCALL
|
||||||
xsltDefaultSortFunction (xsltTransformContextPtr ctxt,
|
xsltDefaultSortFunction (xsltTransformContextPtr ctxt,
|
||||||
xmlNodePtr *sorts,
|
xmlNodePtr *sorts,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "libxml_wrap.h"
|
#include "libxml_wrap.h"
|
||||||
#include <libxslt/xslt.h>
|
#include <libxslt/xslt.h>
|
||||||
#include <libxslt/xsltInternals.h>
|
#include <libxslt/xsltInternals.h>
|
||||||
|
#include <libxslt/xsltlocale.h>
|
||||||
#include <libxslt/xsltutils.h>
|
#include <libxslt/xsltutils.h>
|
||||||
#include <libxslt/attributes.h>
|
#include <libxslt/attributes.h>
|
||||||
#include <libxslt/documents.h>
|
#include <libxslt/documents.h>
|
||||||
|
Reference in New Issue
Block a user