[libxslt] Make xsl:decimal-format work with namespaces
- From: Nick Wellnhofer <nwellnhof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libxslt] Make xsl:decimal-format work with namespaces
- Date: Tue, 7 Feb 2017 15:11:26 +0000 (UTC)
commit 38d4a907541379e7c3381324776fcb9f0c4324ee
Author: Nick Wellnhofer <wellnhofer aevum de>
Date: Tue Feb 7 15:47:27 2017 +0100
Make xsl:decimal-format work with namespaces
Fixes bug #778170:
https://bugzilla.gnome.org/show_bug.cgi?id=778170
doc/symbols.xml | 1 +
libxslt/functions.c | 23 +++++++++++++--
libxslt/xslt.c | 66 ++++++++++++++++++++++++++++++++++++++++-----
libxslt/xsltInternals.h | 5 +++
tests/docs/bug-202.xml | 1 +
tests/docs/bug-203.xml | 1 +
tests/docs/bug-204.xml | 1 +
tests/docs/bug-205.xml | 1 +
tests/general/bug-202.err | 2 +
tests/general/bug-202.xsl | 5 +++
tests/general/bug-203.err | 1 +
tests/general/bug-203.xsl | 5 +++
tests/general/bug-204.err | 2 +
tests/general/bug-204.xsl | 6 ++++
tests/general/bug-205.out | 2 +
tests/general/bug-205.xsl | 10 +++++++
16 files changed, 122 insertions(+), 10 deletions(-)
---
diff --git a/doc/symbols.xml b/doc/symbols.xml
index 1499909..49d9b0a 100644
--- a/doc/symbols.xml
+++ b/doc/symbols.xml
@@ -316,5 +316,6 @@
</release>
<release version="1.1.30">
<symbol file="xsltInternals">xsltFlagRVTs</symbol>
+ <symbol file="xsltInternals">xsltDecimalFormatGetByQName</symbol>
</release>
</symbols>
diff --git a/libxslt/functions.c b/libxslt/functions.c
index ec22203..5cc9da5 100644
--- a/libxslt/functions.c
+++ b/libxslt/functions.c
@@ -603,12 +603,15 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
xmlXPathObjectPtr formatObj = NULL;
xmlXPathObjectPtr decimalObj = NULL;
xsltStylesheetPtr sheet;
- xsltDecimalFormatPtr formatValues;
+ xsltDecimalFormatPtr formatValues = NULL;
xmlChar *result;
+ const xmlChar *ncname;
+ const xmlChar *prefix = NULL;
+ const xmlChar *nsUri = NULL;
xsltTransformContextPtr tctxt;
tctxt = xsltXPathGetTransformContext(ctxt);
- if (tctxt == NULL)
+ if ((tctxt == NULL) || (tctxt->inst == NULL))
return;
sheet = tctxt->style;
if (sheet == NULL)
@@ -619,7 +622,21 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
case 3:
CAST_TO_STRING;
decimalObj = valuePop(ctxt);
- formatValues = xsltDecimalFormatGetByName(sheet, decimalObj->stringval);
+ ncname = xsltSplitQName(sheet->dict, decimalObj->stringval, &prefix);
+ if (prefix != NULL) {
+ xmlNsPtr ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, prefix);
+ if (ns == NULL) {
+ xsltTransformError(tctxt, NULL, NULL,
+ "format-number : No namespace found for QName '%s:%s'\n",
+ prefix, ncname);
+ sheet->errors++;
+ ncname = NULL;
+ }
+ nsUri = ns->href;
+ }
+ if (ncname != NULL) {
+ formatValues = xsltDecimalFormatGetByQName(sheet, nsUri, ncname);
+ }
if (formatValues == NULL) {
xsltTransformError(tctxt, NULL, NULL,
"format-number() : undeclared decimal format '%s'\n",
diff --git a/libxslt/xslt.c b/libxslt/xslt.c
index d41a98d..b367f9e 100644
--- a/libxslt/xslt.c
+++ b/libxslt/xslt.c
@@ -275,7 +275,7 @@ xsltIsBlank(xmlChar *str) {
* *
************************************************************************/
static xsltDecimalFormatPtr
-xsltNewDecimalFormat(xmlChar *name)
+xsltNewDecimalFormat(const xmlChar *nsUri, xmlChar *name)
{
xsltDecimalFormatPtr self;
/* UTF-8 for 0x2030 */
@@ -284,6 +284,7 @@ xsltNewDecimalFormat(xmlChar *name)
self = xmlMalloc(sizeof(xsltDecimalFormat));
if (self != NULL) {
self->next = NULL;
+ self->nsUri = nsUri;
self->name = name;
/* Default values */
@@ -369,7 +370,39 @@ xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name)
for (result = style->decimalFormat->next;
result != NULL;
result = result->next) {
- if (xmlStrEqual(name, result->name))
+ if ((result->nsUri == NULL) && xmlStrEqual(name, result->name))
+ return result;
+ }
+ style = xsltNextImport(style);
+ }
+ return result;
+}
+
+/**
+ * xsltDecimalFormatGetByQName:
+ * @style: the XSLT stylesheet
+ * @nsUri: the namespace URI of the QName
+ * @name: the local part of the QName
+ *
+ * Find decimal-format by QName
+ *
+ * Returns the xsltDecimalFormatPtr
+ */
+xsltDecimalFormatPtr
+xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri,
+ const xmlChar *name)
+{
+ xsltDecimalFormatPtr result = NULL;
+
+ if (name == NULL)
+ return style->decimalFormat;
+
+ while (style != NULL) {
+ for (result = style->decimalFormat->next;
+ result != NULL;
+ result = result->next) {
+ if (xmlStrEqual(nsUri, result->nsUri) &&
+ xmlStrEqual(name, result->name))
return result;
}
style = xsltNextImport(style);
@@ -747,7 +780,7 @@ xsltNewStylesheet(void) {
ret->omitXmlDeclaration = -1;
ret->standalone = -1;
- ret->decimalFormat = xsltNewDecimalFormat(NULL);
+ ret->decimalFormat = xsltNewDecimalFormat(NULL, NULL);
ret->indent = -1;
ret->errors = 0;
ret->warnings = 0;
@@ -1384,18 +1417,37 @@ xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur)
prop = xmlGetNsProp(cur, BAD_CAST("name"), NULL);
if (prop != NULL) {
- format = xsltDecimalFormatGetByName(style, prop);
+ const xmlChar *nsUri;
+
+ if (xmlValidateQName(prop, 0) != 0) {
+ xsltTransformError(NULL, style, cur,
+ "xsl:decimal-format: Invalid QName '%s'.\n", prop);
+ style->warnings++;
+ xmlFree(prop);
+ return;
+ }
+ /*
+ * TODO: Don't use xsltGetQNameURI().
+ */
+ nsUri = xsltGetQNameURI(cur, &prop);
+ if (prop == NULL) {
+ style->warnings++;
+ return;
+ }
+ format = xsltDecimalFormatGetByQName(style, nsUri, prop);
if (format != NULL) {
xsltTransformError(NULL, style, cur,
"xsltParseStylestyleDecimalFormat: %s already exists\n", prop);
- if (style != NULL) style->warnings++;
+ style->warnings++;
+ xmlFree(prop);
return;
}
- format = xsltNewDecimalFormat(prop);
+ format = xsltNewDecimalFormat(nsUri, prop);
if (format == NULL) {
xsltTransformError(NULL, style, cur,
"xsltParseStylestyleDecimalFormat: failed creating new decimal-format\n");
- if (style != NULL) style->errors++;
+ style->errors++;
+ xmlFree(prop);
return;
}
/* Append new decimal-format structure */
diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
index 5ad1771..47125b3 100644
--- a/libxslt/xsltInternals.h
+++ b/libxslt/xsltInternals.h
@@ -324,6 +324,7 @@ struct _xsltDecimalFormat {
xmlChar *percent;
xmlChar *permille;
xmlChar *zeroDigit;
+ const xmlChar *nsUri;
};
/**
@@ -1854,6 +1855,10 @@ XSLTPUBFUN void XSLTCALL
XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL
xsltDecimalFormatGetByName(xsltStylesheetPtr style,
xmlChar *name);
+XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL
+ xsltDecimalFormatGetByQName(xsltStylesheetPtr style,
+ const xmlChar *nsUri,
+ const xmlChar *name);
XSLTPUBFUN xsltStylesheetPtr XSLTCALL
xsltParseStylesheetProcess(xsltStylesheetPtr ret,
diff --git a/tests/docs/bug-202.xml b/tests/docs/bug-202.xml
new file mode 100644
index 0000000..69d62f2
--- /dev/null
+++ b/tests/docs/bug-202.xml
@@ -0,0 +1 @@
+<doc/>
diff --git a/tests/docs/bug-203.xml b/tests/docs/bug-203.xml
new file mode 100644
index 0000000..69d62f2
--- /dev/null
+++ b/tests/docs/bug-203.xml
@@ -0,0 +1 @@
+<doc/>
diff --git a/tests/docs/bug-204.xml b/tests/docs/bug-204.xml
new file mode 100644
index 0000000..69d62f2
--- /dev/null
+++ b/tests/docs/bug-204.xml
@@ -0,0 +1 @@
+<doc/>
diff --git a/tests/docs/bug-205.xml b/tests/docs/bug-205.xml
new file mode 100644
index 0000000..69d62f2
--- /dev/null
+++ b/tests/docs/bug-205.xml
@@ -0,0 +1 @@
+<doc/>
diff --git a/tests/general/bug-202.err b/tests/general/bug-202.err
new file mode 100644
index 0000000..f640148
--- /dev/null
+++ b/tests/general/bug-202.err
@@ -0,0 +1,2 @@
+compilation error: file ./bug-202.xsl line 3 element decimal-format
+xsl:decimal-format: Invalid QName 'testns:0format'.
diff --git a/tests/general/bug-202.out b/tests/general/bug-202.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/general/bug-202.xsl b/tests/general/bug-202.xsl
new file mode 100644
index 0000000..b8629f8
--- /dev/null
+++ b/tests/general/bug-202.xsl
@@ -0,0 +1,5 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:decimal-format xmlns:testns="urn:test:1" name="testns:0format" decimal-separator=","/>
+
+</xsl:stylesheet>
diff --git a/tests/general/bug-203.err b/tests/general/bug-203.err
new file mode 100644
index 0000000..0b18a5b
--- /dev/null
+++ b/tests/general/bug-203.err
@@ -0,0 +1 @@
+testns:format : no namespace bound to prefix testns
diff --git a/tests/general/bug-203.out b/tests/general/bug-203.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/general/bug-203.xsl b/tests/general/bug-203.xsl
new file mode 100644
index 0000000..f7f1f37
--- /dev/null
+++ b/tests/general/bug-203.xsl
@@ -0,0 +1,5 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:decimal-format name="testns:format" decimal-separator=","/>
+
+</xsl:stylesheet>
diff --git a/tests/general/bug-204.err b/tests/general/bug-204.err
new file mode 100644
index 0000000..dd9f40f
--- /dev/null
+++ b/tests/general/bug-204.err
@@ -0,0 +1,2 @@
+compilation error: file ./bug-204.xsl line 4 element decimal-format
+xsltParseStylestyleDecimalFormat: format already exists
diff --git a/tests/general/bug-204.out b/tests/general/bug-204.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/general/bug-204.xsl b/tests/general/bug-204.xsl
new file mode 100644
index 0000000..792af8a
--- /dev/null
+++ b/tests/general/bug-204.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:decimal-format xmlns:testns="urn:test:1" name="testns:format" decimal-separator=","/>
+<xsl:decimal-format xmlns:newns="urn:test:1" name="newns:format" decimal-separator="."/>
+
+</xsl:stylesheet>
diff --git a/tests/general/bug-205.out b/tests/general/bug-205.out
new file mode 100644
index 0000000..cf63a11
--- /dev/null
+++ b/tests/general/bug-205.out
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+123,00
diff --git a/tests/general/bug-205.xsl b/tests/general/bug-205.xsl
new file mode 100644
index 0000000..fa31965
--- /dev/null
+++ b/tests/general/bug-205.xsl
@@ -0,0 +1,10 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:decimal-format xmlns:testns="urn:test:1" name="testns:format" decimal-separator=","/>
+<xsl:decimal-format xmlns:testns="urn:test:2" name="testns:format" decimal-separator="."/>
+
+<xsl:template match="/" xmlns:newns="urn:test:1">
+ <xsl:value-of select="format-number(123, '0,00', 'newns:format')"/>
+</xsl:template>
+
+</xsl:stylesheet>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]