diff --git a/include/XSLT/impl/handler/xslt_apply_templates_handler.hpp b/include/XSLT/impl/handler/xslt_apply_templates_handler.hpp index 4e36000f..297136ef 100644 --- a/include/XSLT/impl/handler/xslt_apply_templates_handler.hpp +++ b/include/XSLT/impl/handler/xslt_apply_templates_handler.hpp @@ -14,6 +14,7 @@ template class ApplyTemplatesHandler : public SAX::DefaultHandler { typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: typedef stringT string_type; @@ -32,10 +33,10 @@ public: { if(applyTemplates_ == 0) { - static const ValueRule rules[] = { { SC::select, false, 0, 0 }, - { SC::mode, false, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0} }; - std::map attrs = gatherAttributes(qName, atts, rules); + static const AV rules = AV::rule(SC::select, false) + .rule(SC::mode, false); + + std::map attrs = rules.gather(qName, atts); const string_type& select = attrs[SC::select]; Arabica::XPath::XPathExpressionPtr xpath; diff --git a/include/XSLT/impl/handler/xslt_attribute_handler.hpp b/include/XSLT/impl/handler/xslt_attribute_handler.hpp index ddb4a48d..d6621fab 100644 --- a/include/XSLT/impl/handler/xslt_attribute_handler.hpp +++ b/include/XSLT/impl/handler/xslt_attribute_handler.hpp @@ -14,6 +14,7 @@ class AttributeHandler : public ItemContainerHandler > baseT; typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: AttributeHandler(CompilationContext& context) : baseT(context) @@ -26,11 +27,10 @@ protected: const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::name, true, 0, 0 }, - { SC::namespace_, false, string_adaptor::empty_string(), 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; + static const AV rules = AV::rule(SC::name, true) + .rule(SC::namespace_, false, string_adaptor::empty_string()); - std::map attrs = gatherAttributes(qName, atts, rules); + std::map attrs = rules.gather(qName, atts); Arabica::XPath::XPathExpressionPtr name = baseT::context().xpath_attribute_value_template(attrs[SC::name]); diff --git a/include/XSLT/impl/handler/xslt_call_template_handler.hpp b/include/XSLT/impl/handler/xslt_call_template_handler.hpp index c2286cde..0d817f27 100644 --- a/include/XSLT/impl/handler/xslt_call_template_handler.hpp +++ b/include/XSLT/impl/handler/xslt_call_template_handler.hpp @@ -13,6 +13,7 @@ template class CallTemplateHandler : public SAX::DefaultHandler { typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: typedef stringT string_type; typedef adaptorT string_adaptor; @@ -30,10 +31,9 @@ public: { if(callTemplate_ == 0) { - static const ValueRule rules[] = { { SC::name, true, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; - - std::map attrs = gatherAttributes(qName, atts, rules); + static const AV rules = AV::rule(SC::name, true); + + std::map attrs = rules.gather(qName, atts); string_type name = context_.processInternalQName(attrs[SC::name]).clarkName(); diff --git a/include/XSLT/impl/handler/xslt_choose_handler.hpp b/include/XSLT/impl/handler/xslt_choose_handler.hpp index 0c1e37f1..928700e6 100644 --- a/include/XSLT/impl/handler/xslt_choose_handler.hpp +++ b/include/XSLT/impl/handler/xslt_choose_handler.hpp @@ -18,7 +18,7 @@ public: private: typedef ItemContainerHandler > baseT; typedef StylesheetConstant SC; - + typedef AttributeValidators AV; public: WhenHandler(Choose* choose, CompilationContext& context) : @@ -32,9 +32,8 @@ public: const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::test, true, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; - string_type test = gatherAttributes(qName, atts, rules)[SC::test]; + static const AV rules = AV::rule(SC::test, true); + string_type test = rules.gather(qName, atts)[SC::test]; return new When(baseT::context().xpath_expression(test)); } // startElement diff --git a/include/XSLT/impl/handler/xslt_copy_handler.hpp b/include/XSLT/impl/handler/xslt_copy_handler.hpp index 16043529..a4ebf504 100644 --- a/include/XSLT/impl/handler/xslt_copy_handler.hpp +++ b/include/XSLT/impl/handler/xslt_copy_handler.hpp @@ -12,6 +12,7 @@ template class CopyHandler : public ItemContainerHandler > { typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: CopyHandler(CompilationContext& context) : ItemContainerHandler >(context) @@ -23,9 +24,8 @@ public: const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::use_attribute_sets, false, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; - string_type sets = gatherAttributes(qName, atts, rules)[SC::use_attribute_sets]; + static const AV rules = AV::rule(SC::use_attribute_sets, false); + string_type sets = rules.gather(qName, atts)[SC::use_attribute_sets]; return new Copy(sets); } // createContainer @@ -35,6 +35,7 @@ template class CopyOfHandler : public SAX::DefaultHandler { typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: CopyOfHandler(CompilationContext& context) : context_(context), @@ -49,9 +50,8 @@ public: { if(copyOf_ == 0) { - static const ValueRule rules[] = { { SC::select, true, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; - string_type select = gatherAttributes(qName, atts, rules)[SC::select]; + static const AV rules = AV::rule(SC::select, true); + string_type select = rules.gather(qName, atts)[SC::select]; copyOf_ = new CopyOf(context_.xpath_expression(select)); diff --git a/include/XSLT/impl/handler/xslt_element_handler.hpp b/include/XSLT/impl/handler/xslt_element_handler.hpp index bc583d28..08a7aad6 100644 --- a/include/XSLT/impl/handler/xslt_element_handler.hpp +++ b/include/XSLT/impl/handler/xslt_element_handler.hpp @@ -14,6 +14,7 @@ class ElementHandler : public ItemContainerHandler > baseT; typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: ElementHandler(CompilationContext& context) : ItemContainerHandler >(context) @@ -26,12 +27,11 @@ protected: const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::name, true, 0, 0 }, - { SC::namespace_, false, string_adaptor::empty_string(), 0 }, - { SC::use_attribute_sets, false, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; + static const AV rules = AV::rule(SC::name, true) + .rule(SC::namespace_, false, string_adaptor::empty_string()) + .rule(SC::use_attribute_sets, false); - std::map attrs = gatherAttributes(qName, atts, rules); + std::map attrs = rules.gather(qName, atts); Arabica::XPath::XPathExpressionPtr name = baseT::context().xpath_attribute_value_template(attrs[SC::name]); diff --git a/include/XSLT/impl/handler/xslt_for_each_handler.hpp b/include/XSLT/impl/handler/xslt_for_each_handler.hpp index ace30d2b..45ed637c 100644 --- a/include/XSLT/impl/handler/xslt_for_each_handler.hpp +++ b/include/XSLT/impl/handler/xslt_for_each_handler.hpp @@ -14,6 +14,7 @@ template class ForEachHandler : public ItemContainerHandler > { typedef StylesheetConstant SC; + typedef AttributeValidators AV; typedef ItemContainerHandler > baseT; public: @@ -29,9 +30,8 @@ protected: const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::select, true, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; - string_type select = gatherAttributes(qName, atts, rules)[SC::select]; + static const AV rules = AV::rule(SC::select, true); + string_type select = rules.gather(qName, atts)[SC::select]; return new ForEach(baseT::context().xpath_expression(select)); } // createContainer diff --git a/include/XSLT/impl/handler/xslt_if_handler.hpp b/include/XSLT/impl/handler/xslt_if_handler.hpp index 600fdce0..f8757ee2 100644 --- a/include/XSLT/impl/handler/xslt_if_handler.hpp +++ b/include/XSLT/impl/handler/xslt_if_handler.hpp @@ -13,6 +13,7 @@ template class IfHandler : public ItemContainerHandler > { typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: IfHandler(CompilationContext& context) : ItemContainerHandler >(context) @@ -24,9 +25,8 @@ public: const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::test, true, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; - string_type test = gatherAttributes(qName, atts, rules)[SC::test]; + static const AV rules = AV::rule(SC::test, true); + string_type test = rules.gather(qName, atts)[SC::test]; return new If(ItemContainerHandler >::context().xpath_expression(test)); } // startElement diff --git a/include/XSLT/impl/handler/xslt_include_handler.hpp b/include/XSLT/impl/handler/xslt_include_handler.hpp index 2afebda3..82b949c6 100644 --- a/include/XSLT/impl/handler/xslt_include_handler.hpp +++ b/include/XSLT/impl/handler/xslt_include_handler.hpp @@ -15,6 +15,7 @@ class IncludeHandler : public SAX::DefaultHandler { struct ImportHref; typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: IncludeHandler() : @@ -122,9 +123,8 @@ public: private: string_type validate_href(const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::href, true, 0, 0 }, - { 0, false, 0, 0 } }; - string_type href = gatherAttributes(qName, atts, rules)[SC::href]; + static const AV rules = AV::rule(SC::href, true); + string_type href = rules.gather(qName, atts)[SC::href]; no_content_ = true; // std::cout << "Base : " << context_->currentBase() << ", href : " << href << "\n"; return context_->makeAbsolute(href); diff --git a/include/XSLT/impl/handler/xslt_key_handler.hpp b/include/XSLT/impl/handler/xslt_key_handler.hpp index 54a0eff7..7287974e 100644 --- a/include/XSLT/impl/handler/xslt_key_handler.hpp +++ b/include/XSLT/impl/handler/xslt_key_handler.hpp @@ -13,6 +13,7 @@ template class KeyHandler : public SAX::DefaultHandler { typedef StylesheetConstant SC; + typedef AttributeValidators AV; typedef typename Key::MatchExprList MatchExprList; public: KeyHandler(CompilationContext& context) : @@ -29,12 +30,11 @@ public: if(key_ != 0) throw SAX::SAXException(string_adaptor::asStdString(qName) + " can not contain elements"); - static const ValueRule rules[] = { { SC::name, true, 0, 0 }, - { SC::match, true, 0, 0 }, - { SC::use, true, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; + static const AV rules = AV::rule(SC::name, true) + .rule(SC::match, true) + .rule(SC::use, true); - std::map attrs = gatherAttributes(qName, atts, rules); + std::map attrs = rules.gather(qName, atts); name_ = context_.processInternalQName(attrs[SC::name]).clarkName(); try { diff --git a/include/XSLT/impl/handler/xslt_message_handler.hpp b/include/XSLT/impl/handler/xslt_message_handler.hpp index 10de76c7..bf0e86cf 100644 --- a/include/XSLT/impl/handler/xslt_message_handler.hpp +++ b/include/XSLT/impl/handler/xslt_message_handler.hpp @@ -14,6 +14,7 @@ class MessageHandler : public ItemContainerHandler > baseT; typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: MessageHandler(CompilationContext& context) : baseT(context) @@ -26,9 +27,8 @@ protected: const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::terminate, false, SC::no, SC::AllowedYesNo }, - { string_adaptor::empty_string(), false, 0, 0 } }; - return new Message(gatherAttributes(qName, atts, rules)[SC::terminate] == SC::yes); + static const AV rules = AV::rule(SC::terminate, false, SC::no, AllowedValues(SC::yes, SC::no)); + return new Message(rules.gather(qName, atts)[SC::terminate] == SC::yes); } // createContainer }; // class MessageHandler diff --git a/include/XSLT/impl/handler/xslt_namespace_alias_handler.hpp b/include/XSLT/impl/handler/xslt_namespace_alias_handler.hpp index b54ed669..cd4ed4a2 100644 --- a/include/XSLT/impl/handler/xslt_namespace_alias_handler.hpp +++ b/include/XSLT/impl/handler/xslt_namespace_alias_handler.hpp @@ -14,6 +14,7 @@ template class NamespaceAliasHandler : public SAX::DefaultHandler { typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: NamespaceAliasHandler(CompilationContext& context) : @@ -29,11 +30,10 @@ public: { if(!done_) { - static const ValueRule rules[] = { { SC::stylesheet_prefix, true, 0, 0 }, - { SC::result_prefix, true, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; + static const AV rules = AV::rule(SC::stylesheet_prefix, true) + .rule(SC::result_prefix, true); - std::map attrs = gatherAttributes(qName, atts, rules); + std::map attrs = rules.gather(qName, atts); string_type stylesheet_prefix = attrs[SC::stylesheet_prefix]; string_type result_prefix = attrs[SC::result_prefix]; diff --git a/include/XSLT/impl/handler/xslt_output_handler.hpp b/include/XSLT/impl/handler/xslt_output_handler.hpp index 008745ac..652780a7 100644 --- a/include/XSLT/impl/handler/xslt_output_handler.hpp +++ b/include/XSLT/impl/handler/xslt_output_handler.hpp @@ -10,6 +10,7 @@ template class OutputHandler : public SAX::DefaultHandler { typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: OutputHandler(CompilationContext& context) : @@ -24,20 +25,18 @@ public: { if(settings_.empty()) { - static string_type AllowedMethods[] = { SC::xml, SC::html, SC::text, string_adaptor::empty_string() }; - static const ValueRule rules[] = - { { SC::method, false, SC::xml, AllowedMethods }, - { SC::version, false, SC::Version, 0 }, - { SC::encoding, false, SC::utf8, 0 }, - { SC::omit_xml_declaration, false, SC::no, SC::AllowedYesNo }, - { SC::standalone, false, string_adaptor::empty_string(), SC::AllowedYesNo }, - { SC::doctype_public, false, string_adaptor::empty_string(), 0 }, - { SC::doctype_system, false, string_adaptor::empty_string(), 0 }, - { SC::cdata_section_elements, false, string_adaptor::empty_string(), 0 }, - { SC::indent, false, SC::no, SC::AllowedYesNo }, - { SC::media_type, false, string_adaptor::empty_string(), 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; - settings_ = gatherAttributes(qName, atts, rules); + static const AV rules = AV::rule(SC::method, false, SC::xml, AllowedValues(SC::xml, SC::html, SC::text)) + .rule(SC::version, false, SC::Version) + .rule(SC::encoding, false, SC::utf8) + .rule(SC::omit_xml_declaration, false, SC::no, AllowedValues(SC::yes, SC::no)) + .rule(SC::standalone, false, string_adaptor::empty_string(), AllowedValues(SC::yes, SC::no)) + .rule(SC::doctype_public, false, string_adaptor::empty_string()) + .rule(SC::doctype_system, false, string_adaptor::empty_string()) + .rule(SC::cdata_section_elements, false, string_adaptor::empty_string()) + .rule(SC::indent, false, SC::no, AllowedValues(SC::yes, SC::no)) + .rule(SC::media_type, false, string_adaptor::empty_string()); + + settings_ = rules.gather(qName, atts); cdataElements_ = extractCDATAElements(settings_[SC::cdata_section_elements]); return; diff --git a/include/XSLT/impl/handler/xslt_processing_instruction_handler.hpp b/include/XSLT/impl/handler/xslt_processing_instruction_handler.hpp index 818f69b2..e708bad7 100644 --- a/include/XSLT/impl/handler/xslt_processing_instruction_handler.hpp +++ b/include/XSLT/impl/handler/xslt_processing_instruction_handler.hpp @@ -14,6 +14,7 @@ class ProcessingInstructionHandler : public ItemContainerHandler > baseT; typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: ProcessingInstructionHandler(CompilationContext& context) : @@ -26,9 +27,8 @@ public: const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::name, true, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0} }; - string_type name = gatherAttributes(qName, atts, rules)[SC::name]; + static const AV rules = AV::rule(SC::name, true); + string_type name = rules.gather(qName, atts)[SC::name]; return new ProcessingInstruction(baseT::context().xpath_attribute_value_template(name)); } // createContainer diff --git a/include/XSLT/impl/handler/xslt_sort_handler.hpp b/include/XSLT/impl/handler/xslt_sort_handler.hpp index cc69317b..e9fa82c6 100644 --- a/include/XSLT/impl/handler/xslt_sort_handler.hpp +++ b/include/XSLT/impl/handler/xslt_sort_handler.hpp @@ -12,7 +12,7 @@ template class SortHandler : public SAX::DefaultHandler { typedef StylesheetConstant SC; - + typedef AttributeValidators AV; public: SortHandler(CompilationContext& context, Sortable& sortee) : @@ -29,14 +29,13 @@ public: { if(sort_ == 0) { - static const ValueRule rules[] = { { SC::select, false, SC::current_xpath, 0 }, - { SC::lang, false, 0, 0 }, - { SC::data_type, false, SC::text, 0 }, - { SC::order, false, SC::ascending, 0 }, - { SC::case_order, false, SC::upper_first, 0 }, - { 0, false, 0, 0 } }; + static const AV rules = AV::rule(SC::select, false, SC::current_xpath) + .rule(SC::lang, false) + .rule(SC::data_type, false, SC::text) + .rule(SC::order, false, SC::ascending) + .rule(SC::case_order, false, SC::upper_first); - std::map attr = gatherAttributes(qName, atts, rules); + std::map attr = rules.gather(qName, atts); Arabica::XPath::XPathExpressionPtr select, lang, datatype, order, caseorder; select = context_.xpath_expression(attr[SC::select]); diff --git a/include/XSLT/impl/handler/xslt_template_handler.hpp b/include/XSLT/impl/handler/xslt_template_handler.hpp index 35d2ec72..4b997d9a 100644 --- a/include/XSLT/impl/handler/xslt_template_handler.hpp +++ b/include/XSLT/impl/handler/xslt_template_handler.hpp @@ -14,6 +14,7 @@ class TemplateHandler : public ItemContainerHandler > baseT; typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: TemplateHandler(CompilationContext& context) : baseT(context), @@ -42,12 +43,11 @@ protected: const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::match, false, 0, 0 }, - { SC::mode, false, 0, 0 }, - { SC::name, false, 0, 0 }, - { SC::priority, false, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; - std::map attributes = gatherAttributes(qName, atts, rules); + static const AV rules = AV::rule(SC::match, false) + .rule(SC::mode, false) + .rule(SC::name, false) + .rule(SC::priority, false); + std::map attributes = rules.gather(qName, atts); const string_type& match = attributes[SC::match]; if((match == string_adaptor::empty_string()) && (attributes[SC::name] == string_adaptor::empty_string())) diff --git a/include/XSLT/impl/handler/xslt_text_handler.hpp b/include/XSLT/impl/handler/xslt_text_handler.hpp index f9c20a61..3d69d270 100644 --- a/include/XSLT/impl/handler/xslt_text_handler.hpp +++ b/include/XSLT/impl/handler/xslt_text_handler.hpp @@ -12,7 +12,7 @@ template class TextHandler : public SAX::DefaultHandler { typedef StylesheetConstant SC; - + typedef AttributeValidators AV; public: TextHandler(CompilationContext& context) : context_(context), @@ -27,9 +27,8 @@ public: { if(text_ == 0) { - static const ValueRule rules[] = { { SC::disable_output_escaping, false, SC::no, SC::AllowedYesNo }, - { string_adaptor::empty_string(), false, 0, 0 } }; - text_ = new Text(gatherAttributes(qName, atts, rules)[SC::disable_output_escaping] == SC::yes); + static const AV rules = AV::rule(SC::disable_output_escaping, false, SC::no, AllowedValues(SC::yes, SC::no)); + text_ = new Text(rules.gather(qName, atts)[SC::disable_output_escaping] == SC::yes); return; } // if(text_ == 0) diff --git a/include/XSLT/impl/handler/xslt_value_of_handler.hpp b/include/XSLT/impl/handler/xslt_value_of_handler.hpp index 76c7dfaa..4f974a67 100644 --- a/include/XSLT/impl/handler/xslt_value_of_handler.hpp +++ b/include/XSLT/impl/handler/xslt_value_of_handler.hpp @@ -13,6 +13,7 @@ template class ValueOfHandler : public SAX::DefaultHandler { typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: ValueOfHandler(CompilationContext& context) : context_(context), @@ -27,11 +28,10 @@ public: { if(valueOf_ == 0) { - static const ValueRule rules[] = { { SC::select, true, 0, 0 }, - { SC::disable_output_escaping, false, SC::no, SC::AllowedYesNo }, - { 0, false, 0, 0 } }; + static const AV rules = AV::rule(SC::select, true) + .rule(SC::disable_output_escaping, false, SC::no, AllowedValues(SC::yes, SC::no)); - std::map attrs = gatherAttributes(qName, atts, rules); + std::map attrs = rules.gather(qName, atts); valueOf_ = new ValueOf(context_.xpath_expression(attrs[SC::select]), attrs[SC::disable_output_escaping] == SC::yes); return; diff --git a/include/XSLT/impl/handler/xslt_value_validation.hpp b/include/XSLT/impl/handler/xslt_value_validation.hpp index b7c9bccf..c059e012 100644 --- a/include/XSLT/impl/handler/xslt_value_validation.hpp +++ b/include/XSLT/impl/handler/xslt_value_validation.hpp @@ -23,6 +23,13 @@ public: allowed_.insert(v2); } // AllowedValues + AllowedValues(const string_type& v1, const string_type& v2, const string_type& v3) + { + allowed_.insert(v1); + allowed_.insert(v2); + allowed_.insert(v3); + } // AllowedValues + AllowedValues(const AllowedValues& rhs) : allowed_(rhs.allowed_) { @@ -45,46 +52,70 @@ private: std::set allowed_; }; // AllowedValues +template +AllowedValues makeAllowedValues(const string_type& a1, const string_type& a2) +{ + return AllowedValues(a1, a2); +} // makeAllowedValues +template +AllowedValues makeAllowedValues(const string_type& a1, const string_type& a2, const string_type& a3) +{ + return AllowedValues(a1, a2, a3); +} // makeAllowedValues + template class AttributeValidator { public: AttributeValidator() : - required_(false) + required_(false), + has_def_(false) { } // AttributeValidator bool mandatory() const { return required_; } - bool has_default() const { return !def_.empty(); } + bool has_default() const { return has_def_; } const string_type& default_value() const { return def_; } bool is_allowed(const string_type& v) const { return allowed_.is_allowed(v); } private: explicit AttributeValidator(bool required) : - required_(required) + required_(required), + has_def_(false) + { + } // AttributeValidator + + AttributeValidator(bool required, const string_type& def) : + required_(required), + def_(def), + has_def_(true) { } // AttributeValidator AttributeValidator(bool required, const string_type& def, const AllowedValues allowed) : required_(required), def_(def), + has_def_(true), allowed_(allowed) { } // AttributeValidator bool required_; + bool has_def_; string_type def_; AllowedValues allowed_; AttributeValidator& operator=(const AttributeValidator& rhs) { required_ = rhs.required_; + has_def_ = rhs.has_def_; def_ = rhs.def_; allowed_ = rhs.allowed_; return *this; } // operator= friend class AttributeValidators; + friend class AttributeValidatorsBuilder; }; // class AttributeValidator template @@ -94,6 +125,13 @@ class AttributeValidators public: static AttributeValidatorsBuilder rule(const string_type& name, bool required); + static AttributeValidatorsBuilder rule(const string_type& name, + bool required, + const string_type& def); + static AttributeValidatorsBuilder rule(const string_type& name, + bool required, + const string_type& def, + const AllowedValues& allowed); std::map gather(const string_type& parentElement, const SAX::Attributes& atts) const @@ -164,13 +202,13 @@ private: throw SAX::SAXException(string_adaptor::asStdString(value) + " is not an allowed value for " + string_adaptor::asStdString(parentElement) + - "/@ " + + "/@" + string_adaptor::asStdString(name)); } // validateValues - void put(const string_type& name, bool required) + void put(const string_type& name, const AttributeValidator& av) { - rules_[name] = AttributeValidator(required); + rules_[name] = av; } // put AttributeValidators() { } @@ -200,7 +238,17 @@ public: AttributeValidatorsBuilder& rule(const string_type& name, bool required) { - validators_.put(name, required); + validators_.put(name, AttributeValidator(required)); + return *this; + } // rule + AttributeValidatorsBuilder& rule(const string_type& name, bool required, const string_type& def) + { + validators_.put(name, AttributeValidator(required, def)); + return *this; + } // rule + AttributeValidatorsBuilder& rule(const string_type& name, bool required, const string_type& def, const AllowedValues& av) + { + validators_.put(name, AttributeValidator(required, def, av)); return *this; } // rule @@ -225,99 +273,28 @@ AttributeValidatorsBuilder return builder; } // AttributeValidator::rule -//// - -template -struct ValueRule +template +AttributeValidatorsBuilder + AttributeValidators::rule(const string_type& name, + bool required, + const string_type& def) { - const string_type name; - bool mandatory; - const string_type default_value; - const string_type* allowed; -}; // struct ValueRule + AttributeValidatorsBuilder builder; + builder.rule(name, required, def); + return builder; +} // AttributeValidator::rule template -void validateValues(const string_type& parentElement, - const string_type& name, - const string_type& value, - const string_type allowed[]) +AttributeValidatorsBuilder + AttributeValidators::rule(const string_type& name, + bool required, + const string_type& def, + const AllowedValues& allowed) { - for(const string_type* a = allowed; *a != string_adaptor::empty_string(); ++a) - if(value == *a) - return; - - std::ostringstream os; - os << string_adaptor::asStdString(parentElement) + ": " + string_adaptor::asStdString(name) + " may be one of "; - while(*allowed != string_adaptor::empty_string()) - os << '\'' << string_adaptor::asStdString(*allowed++) << "' "; - throw SAX::SAXException(os.str()); -} // validateValues - -template -void validateXmlAttribute(const string_type& parentElement, - const string_type& name, - const string_type& value, - std::map& results) -{ - typedef StylesheetConstant SC; - - results[name] = value; - - if(name == SC::space) - validateValues(parentElement, name, value, SC::DefaultPreserve); -} // validateXmlAttribute - -template -void validateAttribute(const string_type& parentElement, - const string_type& name, - const string_type& value, - const ValueRule* rules, - std::map& results) -{ - while((rules->name != string_adaptor::empty_string()) && (name != rules->name)) - ++rules; - - if(rules->name == string_adaptor::empty_string()) - throw SAX::SAXException(string_adaptor::asStdString(parentElement) + ": Illegal attribute " + string_adaptor::asStdString(name)); - - results[name] = value; - - if(rules->allowed != 0) - validateValues(parentElement, name, value, rules->allowed); -} // validateAttribute - -template -std::map gatherAttributes(const string_type& parentElement, - const SAX::Attributes& atts, - const ValueRule* rules) -{ - typedef StylesheetConstant SC; - - std::map results; - - for(const ValueRule* r = rules ; r->name != string_adaptor::empty_string(); ++r) - { - if((r->mandatory) && (atts.getValue(r->name).empty())) - throw SAX::SAXException(string_adaptor::asStdString(parentElement) + ": Attribute " + string_adaptor::asStdString(r->name) + " must be specified"); - if(r->default_value != string_adaptor::empty_string()) - results[r->name] = r->default_value; - } // - - for(int a = 0; a < atts.getLength(); ++a) - { - if(atts.getLocalName(a) == string_adaptor::empty_string()) - continue; // namespace decl - if(atts.getURI(a) == SC::xml_uri) - { - validateXmlAttribute(parentElement, atts.getLocalName(a), atts.getValue(a), results); // special xml: attributes - continue; - } - if(atts.getURI(a) == string_adaptor::empty_string()) - validateAttribute(parentElement, atts.getLocalName(a), atts.getValue(a), rules, results); - } - - return results; -} // validateAttributes + AttributeValidatorsBuilder builder; + builder.rule(name, required, def, allowed); + return builder; +} // AttributeValidator::rule template void verifyNoCharacterData(const string_type& ch, diff --git a/include/XSLT/impl/handler/xslt_variable_handler.hpp b/include/XSLT/impl/handler/xslt_variable_handler.hpp index 57599551..0af46cd0 100644 --- a/include/XSLT/impl/handler/xslt_variable_handler.hpp +++ b/include/XSLT/impl/handler/xslt_variable_handler.hpp @@ -14,6 +14,7 @@ template class VariableHandler : public ItemContainerHandler { typedef StylesheetConstant SC; + typedef AttributeValidators AV; public: typedef typename VType::string_type string_type; typedef typename VType::string_adaptor string_adaptor; @@ -39,12 +40,10 @@ protected: const string_type& qName, const SAX::Attributes& atts) { - static const ValueRule rules[] = { { SC::name, true, 0, 0 }, - { SC::select, false, 0, 0 }, - { string_adaptor::empty_string(), false, 0, 0 } }; - + static const AV rules = AV::rule(SC::name, true) + .rule(SC::select, false); - std::map attrs = gatherAttributes(qName, atts, rules); + std::map attrs = rules.gather(qName, atts); const string_type& select = atts.getValue(SC::select); Arabica::XPath::XPathExpressionPtr xpath; diff --git a/include/XSLT/impl/xslt_sort.hpp b/include/XSLT/impl/xslt_sort.hpp index 7e4fdb47..b02aa777 100644 --- a/include/XSLT/impl/xslt_sort.hpp +++ b/include/XSLT/impl/xslt_sort.hpp @@ -42,12 +42,12 @@ public: const string_type order = order_->evaluateAsString(node, context_->xpathContext()); const string_type caseorder = caseorder_->evaluateAsString(node, context_->xpathContext()); - static string_type allowed_datatypes[] = { SC::text, SC::number, string_adaptor::empty_string() }; - static string_type allowed_orders[] = { SC::ascending, SC::descending, string_adaptor::empty_string() }; - static string_type allowed_case_orders[] = { SC::upper_first, SC::lower_first, string_adaptor::empty_string() }; - validateValues(SC::sort, SC::data_type, datatype, allowed_datatypes); - validateValues(SC::sort, SC::order, order, allowed_orders); - validateValues(SC::sort, SC::case_order, caseorder, allowed_case_orders); + static AllowedValues allowed_datatypes = makeAllowedValues(SC::text, SC::number); + static AllowedValues allowed_orders = makeAllowedValues(SC::ascending, SC::descending); + static AllowedValues allowed_case_orders = makeAllowedValues(SC::upper_first, SC::lower_first); + validate(SC::data_type, allowed_datatypes, datatype); + validate(SC::order, allowed_orders, order); + validate(SC::case_order, allowed_case_orders, caseorder); if(datatype == SC::number) if(order == SC::ascending) @@ -78,6 +78,17 @@ public: } // add_sub_sort private: + void validate(const string_type& name, const AllowedValues& allowed, const string_type& value) + { + if(allowed.is_allowed(value)) + return; + + throw SAX::SAXException(string_adaptor::asStdString(value) + + " is not an allowed value for xsl:sort/@" + + string_adaptor::asStdString(name)); + + } // validate + typedef bool(Sort::*sortFn)(const DOMNode& n1, const DOMNode& n2) const; bool numberAscending(const DOMNode& n1, const DOMNode& n2) const { diff --git a/tests/XSLT/main.cpp b/tests/XSLT/main.cpp index d9ad40cb..6733f7fe 100755 --- a/tests/XSLT/main.cpp +++ b/tests/XSLT/main.cpp @@ -51,8 +51,8 @@ int main(int argc, const char* argv[]) Loader loader; - //add_tests(runner, loader, tests_to_run, xalan_tests); - //add_tests(runner, loader, tests_to_run, msft_tests); + add_tests(runner, loader, tests_to_run, xalan_tests); + add_tests(runner, loader, tests_to_run, msft_tests); add_arabica_tests(runner, loader, tests_to_run, arabica_tests); runner.run(argc, argv);