Implement format-number() and <xsl:decimal-format>

b=65983 r=Pike sr=jst
This commit is contained in:
sicking%bigfoot.com 2001-10-15 12:33:54 +00:00
Родитель 4078291d09
Коммит 13c9b8bd52
17 изменённых файлов: 256 добавлений и 20 удалений

Просмотреть файл

@ -133,8 +133,9 @@ LOBJS =../source/base/ArrayList.$(OBJ_SUFFIX) \
../source/xslt/functions/ElementAvailableFnCall.$(OBJ_SUFFIX) \
../source/xslt/functions/FunctionAvailableFnCall.$(OBJ_SUFFIX) \
../source/xslt/functions/GenerateIdFunctionCall.$(OBJ_SUFFIX) \
../source/xslt/functions/txKeyFunctionCall.$(OBJ_SUFFIX) \
../source/xslt/functions/SystemPropertyFunctionCall.$(OBJ_SUFFIX) \
../source/xslt/functions/txFormatNumberFunctionCall.$(OBJ_SUFFIX) \
../source/xslt/functions/txKeyFunctionCall.$(OBJ_SUFFIX) \
../source/xslt/util/NodeStack.$(OBJ_SUFFIX) \
../source/xslt/util/txNodeSorter.$(OBJ_SUFFIX) \
../source/xslt/util/txXPathResultComparator.$(OBJ_SUFFIX) \

Просмотреть файл

@ -124,8 +124,9 @@ CPP_OBJS= \
..\source\xslt\functions\$(OBJDIR)\ElementAvailableFnCall.obj \
..\source\xslt\functions\$(OBJDIR)\FunctionAvailableFnCall.obj \
..\source\xslt\functions\$(OBJDIR)\GenerateIdFunctionCall.obj \
..\source\xslt\functions\$(OBJDIR)\txKeyFunctionCall.obj \
..\source\xslt\functions\$(OBJDIR)\SystemPropertyFunctionCall.obj \
..\source\xslt\functions\$(OBJDIR)\txFormatNumberFunctionCall.obj \
..\source\xslt\functions\$(OBJDIR)\txKeyFunctionCall.obj \
..\source\xslt\util\$(OBJDIR)\NodeStack.obj \
..\source\xslt\util\$(OBJDIR)\txNodeSorter.obj \
..\source\xslt\util\$(OBJDIR)\txXPathResultComparator.obj \

Просмотреть файл

@ -116,8 +116,9 @@ OBJS =../base/ArrayList.$(OBJ_SUFFIX) \
../xslt/functions/ElementAvailableFnCall.$(OBJ_SUFFIX) \
../xslt/functions/FunctionAvailableFnCall.$(OBJ_SUFFIX) \
../xslt/functions/GenerateIdFunctionCall.$(OBJ_SUFFIX) \
../xslt/functions/txKeyFunctionCall.$(OBJ_SUFFIX) \
../xslt/functions/SystemPropertyFunctionCall.$(OBJ_SUFFIX) \
../xslt/functions/txFormatNumberFunctionCall.$(OBJ_SUFFIX) \
../xslt/functions/txKeyFunctionCall.$(OBJ_SUFFIX) \
../xslt/util/NodeStack.$(OBJ_SUFFIX) \
../xslt/util/txNodeSorter.$(OBJ_SUFFIX) \
../xslt/util/txXPathResultComparator.$(OBJ_SUFFIX) \

Просмотреть файл

@ -110,8 +110,9 @@ CPP_OBJS= \
../xslt/functions/$(OBJDIR)/ElementAvailableFnCall.obj \
../xslt/functions/$(OBJDIR)/FunctionAvailableFnCall.obj \
../xslt/functions/$(OBJDIR)/GenerateIdFunctionCall.obj \
../xslt/functions/$(OBJDIR)/txKeyFunctionCall.obj \
../xslt/functions/$(OBJDIR)/SystemPropertyFunctionCall.obj \
../xslt/functions/$(OBJDIR)/txFormatNumberFunctionCall.obj \
../xslt/functions/$(OBJDIR)/txKeyFunctionCall.obj \
../xslt/util/$(OBJDIR)/NodeStack.obj \
../xslt/util/$(OBJDIR)/txNodeSorter.obj \
../xslt/util/$(OBJDIR)/txXPathResultComparator.obj \

Просмотреть файл

@ -152,6 +152,7 @@ class FunctionCall : public Expr {
public:
static const String INVALID_PARAM_COUNT;
static const String INVALID_PARAM_VALUE;
virtual ~FunctionCall();

Просмотреть файл

@ -32,6 +32,9 @@
const String FunctionCall::INVALID_PARAM_COUNT =
"invalid number of parameters for function: ";
const String FunctionCall::INVALID_PARAM_VALUE =
"invalid parameter value for function: ";
//- Constructors -/
/**

Просмотреть файл

@ -55,6 +55,7 @@ const String CHOOSE = "choose";
const String COMMENT = "comment";
const String COPY = "copy";
const String COPY_OF = "copy-of";
const String DECIMAL_FORMAT = "decimal-format";
const String ELEMENT = "element";
const String FOR_EACH = "for-each";
const String IF = "if";
@ -82,7 +83,9 @@ const String CASE_ORDER_ATTR = "case-order";
const String CDATA_ELEMENTS_ATTR = "cdata-section-elements";
const String COUNT_ATTR = "count";
const String DATA_TYPE_ATTR = "data-type";
const String DECIMAL_SEPARATOR_ATTR = "decimal-separator";
const String DEFAULT_SPACE_ATTR = "default-space";
const String DIGIT_ATTR = "digit";
const String DOCTYPE_PUBLIC_ATTR = "doctype-public";
const String DOCTYPE_SYSTEM_ATTR = "doctype-system";
const String ELEMENTS_ATTR = "elements";
@ -90,18 +93,25 @@ const String ENCODING_ATTR = "encoding";
const String EXPR_ATTR = "expr";
const String FORMAT_ATTR = "format";
const String FROM_ATTR = "from";
const String GROUPING_SEPARATOR_ATTR = "grouping-separator";
const String HREF_ATTR = "href";
const String INDENT_ATTR = "indent";
const String INFINITY_ATTR = "infinity";
const String LANG_ATTR = "lang";
const String LEVEL_ATTR = "level";
const String MATCH_ATTR = "match";
const String METHOD_ATTR = "method";
const String MEDIA_TYPE_ATTR = "media-type";
const String MINUS_SIGN_ATTR = "minus-sign";
const String MODE_ATTR = "mode";
const String NAME_ATTR = "name";
const String NAMESPACE_ATTR = "namespace";
const String NAN_ATTR = "NaN";
const String OMIT_XMLDECL_ATTR = "omit-xml-declaration";
const String ORDER_ATTR = "order";
const String PATTERN_SEPARATOR_ATTR = "pattern-separator";
const String PER_MILLE_ATTR = "per-mille";
const String PERCENT_ATTR = "percent";
const String PRIORITY_ATTR = "priority";
const String SELECT_ATTR = "select";
const String STANDALONE = "standalone";
@ -111,6 +121,7 @@ const String USE_ATTRIBUTE_SETS_ATTR = "use-attribute-sets";
const String VALUE_ATTR = "value";
const String VERSION_ATTR = "version";
const String XML_LANG_ATTR = "xml:lang";
const String ZERO_DIGIT_ATTR = "zero-digit";
//-- Attribute Values
const String ANY_VALUE = "any";

Просмотреть файл

@ -53,6 +53,7 @@ extern const String CHOOSE;
extern const String COMMENT;
extern const String COPY;
extern const String COPY_OF;
extern const String DECIMAL_FORMAT;
extern const String ELEMENT;
extern const String FOR_EACH;
extern const String IF;
@ -81,7 +82,9 @@ extern const String CASE_ORDER_ATTR;
extern const String CDATA_ELEMENTS;
extern const String COUNT_ATTR;
extern const String DATA_TYPE_ATTR;
extern const String DECIMAL_SEPARATOR_ATTR;
extern const String DEFAULT_SPACE_ATTR;
extern const String DIGIT_ATTR;
extern const String DOCTYPE_PUBLIC_ATTR;
extern const String DOCTYPE_SYSTEM_ATTR;
extern const String ELEMENTS_ATTR;
@ -89,18 +92,25 @@ extern const String ENCODING_ATTR;
extern const String EXPR_ATTR;
extern const String FORMAT_ATTR;
extern const String FROM_ATTR;
extern const String GROUPING_SEPARATOR_ATTR;
extern const String HREF_ATTR;
extern const String INDENT_ATTR;
extern const String INFINITY_ATTR;
extern const String LANG_ATTR;
extern const String LEVEL_ATTR;
extern const String MATCH_ATTR;
extern const String MEDIA_TYPE_ATTR;
extern const String METHOD_ATTR;
extern const String MINUS_SIGN_ATTR;
extern const String MODE_ATTR;
extern const String NAME_ATTR;
extern const String NAMESPACE_ATTR;
extern const String NAN_ATTR;
extern const String OMIT_XMLDECL_ATTR;
extern const String ORDER_ATTR;
extern const String PATTERN_SEPARATOR_ATTR;
extern const String PER_MILLE_ATTR;
extern const String PERCENT_ATTR;
extern const String PRIORITY_ATTR;
extern const String SELECT_ATTR;
extern const String STANDALONE;
@ -110,6 +120,7 @@ extern const String USE_ATTRIBUTE_SETS_ATTR;
extern const String VALUE_ATTR;
extern const String VERSION_ATTR;
extern const String XML_LANG_ATTR;
extern const String ZERO_DIGIT_ATTR;
//-- Attribute Values
extern const String ANY_VALUE;

Просмотреть файл

@ -797,6 +797,116 @@ txXSLKey* ProcessorState::getKey(String& keyName) {
return (txXSLKey*)xslKeys.get(keyName);
}
/*
* Adds a decimal format. Returns false if the format already exists
* but dosn't contain the exact same parametervalues
*/
MBool ProcessorState::addDecimalFormat(Element* element)
{
// build new DecimalFormat structure
MBool success = MB_TRUE;
txDecimalFormat* format = new txDecimalFormat;
if (!format)
return MB_FALSE;
String attValue = element->getAttribute(NAME_ATTR);
String formatName = attValue;
attValue = element->getAttribute(DECIMAL_SEPARATOR_ATTR);
if (attValue.length() == 1)
format->mDecimalSeparator = attValue.charAt(0);
else if (attValue.length() > 1)
success = MB_FALSE;
attValue = element->getAttribute(GROUPING_SEPARATOR_ATTR);
if (attValue.length() == 1)
format->mGroupingSeparator = attValue.charAt(0);
else if (attValue.length() > 1)
success = MB_FALSE;
attValue = element->getAttribute(INFINITY_ATTR);
if (attValue.length() > 0)
format->mInfinity=attValue;
attValue = element->getAttribute(MINUS_SIGN_ATTR);
if (attValue.length() == 1)
format->mMinusSign = attValue.charAt(0);
else if (attValue.length() > 1)
success = MB_FALSE;
attValue = element->getAttribute(NAN_ATTR);
if (attValue.length() > 0)
format->mNaN=attValue;
attValue = element->getAttribute(PERCENT_ATTR);
if (attValue.length() == 1)
format->mPercent = attValue.charAt(0);
else if (attValue.length() > 1)
success = MB_FALSE;
attValue = element->getAttribute(PER_MILLE_ATTR);
if (attValue.length() == 1)
format->mPerMille = attValue.charAt(0);
else if (attValue.length() > 1)
success = MB_FALSE;
attValue = element->getAttribute(ZERO_DIGIT_ATTR);
if (attValue.length() == 1)
format->mZeroDigit = attValue.charAt(0);
else if (attValue.length() > 1)
success = MB_FALSE;
attValue = element->getAttribute(DIGIT_ATTR);
if (attValue.length() == 1)
format->mDigit = attValue.charAt(0);
else if (attValue.length() > 1)
success = MB_FALSE;
attValue = element->getAttribute(PATTERN_SEPARATOR_ATTR);
if (attValue.length() == 1)
format->mPatternSeparator = attValue.charAt(0);
else if (attValue.length() > 1)
success = MB_FALSE;
if (!success) {
delete format;
return MB_FALSE;
}
// Does an existing format with that name exist?
// (name="" means default format)
txDecimalFormat* existing = NULL;
if (defaultDecimalFormatSet || formatName.length() > 0) {
existing = (txDecimalFormat*)decimalFormats.get(formatName);
}
else {
// We are overriding the predefined default format which is always
// allowed
delete decimalFormats.remove(formatName);
defaultDecimalFormatSet = MB_TRUE;
}
if (existing) {
success = existing->isEqual(format);
delete format;
}
else {
decimalFormats.put(formatName, format);
}
return success;
}
/*
* Returns a decimal format or NULL if no such format exists.
*/
txDecimalFormat* ProcessorState::getDecimalFormat(String& name)
{
return (txDecimalFormat*)decimalFormats.get(name);
}
//--------------------------------------------------/
//- Virtual Methods from derived from ContextState -/
//--------------------------------------------------/
@ -915,8 +1025,7 @@ FunctionCall* ProcessorState::resolveFunctionCall(const String& name) {
return new txKeyFunctionCall(this);
}
else if (FORMAT_NUMBER_FN.isEqual(name)) {
err = "function not yet implemented: ";
err.append(name);
return new txFormatNumberFunctionCall(this);
}
else if (CURRENT_FN.isEqual(name)) {
return new CurrentFunctionCall(this);
@ -1118,6 +1227,11 @@ void ProcessorState::initialize() {
//-- Make sure all loaded documents get deleted
loadedDocuments.setObjectDeletion(MB_TRUE);
//-- add predefined default decimal format
defaultDecimalFormatSet = MB_FALSE;
decimalFormats.put("", new txDecimalFormat);
decimalFormats.setObjectDeletion(MB_TRUE);
}
ProcessorState::ImportFrame::ImportFrame()

Просмотреть файл

@ -40,6 +40,7 @@
#include "OutputFormat.h"
class txXSLKey;
class txDecimalFormat;
/**
* Class used for keeping the current state of the XSL Processor
@ -213,6 +214,12 @@ public:
**/
List* getImportFrames();
/**
* Finds a template for the given Node. Only templates without
* a mode attribute will be searched.
**/
Element* findTemplate(Node* node, Node* context);
/*
* Finds a template for the given Node. Only templates with
* a mode attribute equal to the given mode will be searched.
@ -294,6 +301,17 @@ public:
**/
txXSLKey* getKey(String& keyName);
/*
* Adds a decimal format. Returns false if the format already exists
* but dosn't contain the exact same parametervalues
*/
MBool addDecimalFormat(Element* element);
/**
* Returns a decimal format or NULL if no such format exists.
**/
txDecimalFormat* getDecimalFormat(String& name);
//-------------------------------------/
//- Virtual Methods from ContextState -/
//-------------------------------------/
@ -395,6 +413,11 @@ private:
/**
* List of import containers. Sorted by ascending import precedence
**/
List importFrames;
/**
* A map for named attribute sets
**/
List mImportFrames;
/**
@ -424,6 +447,17 @@ private:
**/
NamedMap xslKeys;
/*
* A list of all avalible decimalformats
*/
NamedMap decimalFormats;
/*
* bool indicating if the default decimal format has been explicitly set
* by the stylesheet
*/
MBool defaultDecimalFormatSet;
XSLTAction* currentAction;
Stack nodeSetStack;

Просмотреть файл

@ -105,6 +105,7 @@ XSLTProcessor::XSLTProcessor() {
xslTypes.put(COMMENT, new XSLType(XSLType::COMMENT));
xslTypes.put(COPY, new XSLType(XSLType::COPY));
xslTypes.put(COPY_OF, new XSLType(XSLType::COPY_OF));
xslTypes.put(DECIMAL_FORMAT, new XSLType(XSLType::DECIMAL_FORMAT));
xslTypes.put(ELEMENT, new XSLType(XSLType::ELEMENT));
xslTypes.put(FOR_EACH, new XSLType(XSLType::FOR_EACH));
xslTypes.put(IF, new XSLType(XSLType::IF));
@ -471,6 +472,24 @@ void XSLTProcessor::processTopLevel(Document* aSource,
case XSLType::ATTRIBUTE_SET:
aPs->addAttributeSet(element, currentFrame);
break;
case XSLType::DECIMAL_FORMAT :
{
if (!aPs->addDecimalFormat(element)) {
// Add error to ErrorObserver
String fName = element->getAttribute(NAME_ATTR);
String err("unable to add ");
if (fName.length() == 0)
err.append("default");
else {
err.append("\"");
err.append(fName);
err.append("\"");
}
err.append(" decimal format for xsl:decimal-format");
notifyError(err);
}
break;
}
case XSLType::PARAM :
{
String name = element->getAttribute(NAME_ATTR);
@ -2109,6 +2128,3 @@ XSLType::XSLType(const XSLType& xslType) {
XSLType::XSLType(short type) {
this->type = type;
} //-- XSLType

Просмотреть файл

@ -381,6 +381,7 @@ public:
COMMENT,
COPY,
COPY_OF,
DECIMAL_FORMAT,
ELEMENT,
IF,
IMPORT,
@ -413,5 +414,3 @@ public:
};
#endif

Просмотреть файл

@ -90,6 +90,7 @@ ExprResult* ElementAvailableFunctionCall::evaluate(Node* context, ContextState*
localName.isEqual(COMMENT) ||
localName.isEqual(COPY) ||
localName.isEqual(COPY_OF) ||
localName.isEqual(DECIMAL_FORMAT) ||
localName.isEqual(ELEMENT) ||
localName.isEqual(FOR_EACH) ||
localName.isEqual(IF) ||

Просмотреть файл

@ -106,7 +106,7 @@ ExprResult* FunctionAvailableFunctionCall::evaluate(Node* context, ContextState*
property.isEqual(XPathNames::FLOOR_FN) ||
property.isEqual(DOCUMENT_FN) ||
property.isEqual(KEY_FN) ||
// property.isEqual(FORMAT_NUMBER_FN) ||
property.isEqual(FORMAT_NUMBER_FN) ||
property.isEqual(CURRENT_FN) ||
// property.isEqual(UNPARSED_ENTITY_URI_FN) ||
property.isEqual(GENERATE_ID_FN) ||

Просмотреть файл

@ -42,8 +42,9 @@ CPPSRCS = CurrentFunctionCall.cpp \
ElementAvailableFnCall.cpp \
FunctionAvailableFnCall.cpp \
GenerateIdFunctionCall.cpp \
txKeyFunctionCall.cpp \
SystemPropertyFunctionCall.cpp
SystemPropertyFunctionCall.cpp \
txFormatNumberFunctionCall.cpp \
txKeyFunctionCall.cpp
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -182,26 +182,65 @@ private:
/**
* The definition for the XSLT format-number() function
**/
class FormatNumberFunctionCall : public FunctionCall {
class txFormatNumberFunctionCall : public FunctionCall {
public:
/**
* Creates a new format-number() function call
**/
FormatNumberFunctionCall();
txFormatNumberFunctionCall(ProcessorState* aPs);
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param cs the ContextState containing the stack information needed
* @param aContext the context node for evaluation of this Expr
* @param aCs the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
* @see FunctionCall.h
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual ExprResult* evaluate(Node* aContext, ContextState* aCs);
private:
static const UNICODE_CHAR FORMAT_QUOTE;
enum FormatParseState {
Prefix,
IntDigit,
IntZero,
FracZero,
FracDigit,
Suffix,
Finished
};
ProcessorState* mPs;
};
/**
* DecimalFormat
* A representation of the XSLT element <xsl:decimal-format>
*/
class txDecimalFormat : public TxObject {
public:
/*
* Creates a new decimal format and initilizes all properties with
* default values
*/
txDecimalFormat();
MBool isEqual(txDecimalFormat* other);
UNICODE_CHAR mDecimalSeparator;
UNICODE_CHAR mGroupingSeparator;
String mInfinity;
UNICODE_CHAR mMinusSign;
String mNaN;
UNICODE_CHAR mPercent;
UNICODE_CHAR mPerMille;
UNICODE_CHAR mZeroDigit;
UNICODE_CHAR mDigit;
UNICODE_CHAR mPatternSeparator;
};
/**

Просмотреть файл

@ -40,14 +40,16 @@ CPPSRCS= \
ElementAvailableFnCall.cpp \
FunctionAvailableFnCall.cpp \
GenerateIDFunctionCall.cpp \
SystemPropertyFunctionCall.cpp \
txFormatNumberFunctionCall.cpp \
txKeyFunctionCall.cpp \
SystemPropertyFunctionCall.cpp \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\CurrentFunctionCall.obj \
.\$(OBJDIR)\DocumentFunctionCall.obj \
.\$(OBJDIR)\ElementAvailableFnCall.obj \
.\$(OBJDIR)\txFormatNumberFunctionCall.obj \
.\$(OBJDIR)\FunctionAvailableFnCall.obj \
.\$(OBJDIR)\GenerateIDFunctionCall.obj \
.\$(OBJDIR)\txKeyFunctionCall.obj \