mirror of
https://github.com/jezhiggins/arabica
synced 2024-12-26 21:58:39 +01:00
Got the new attribute validation going
now to plug it in everywhere
This commit is contained in:
parent
47383b55b9
commit
5043f5bd4d
3 changed files with 165 additions and 15 deletions
|
@ -9,16 +9,80 @@ namespace XSLT
|
||||||
template<class string_type, class string_adaptor> class AttributeValidatorsBuilder;
|
template<class string_type, class string_adaptor> class AttributeValidatorsBuilder;
|
||||||
template<class string_type, class string_adaptor> class AttributeValidators;
|
template<class string_type, class string_adaptor> class AttributeValidators;
|
||||||
|
|
||||||
|
template<class string_type>
|
||||||
|
class AllowedValues
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AllowedValues()
|
||||||
|
{
|
||||||
|
} // AllowedValues
|
||||||
|
|
||||||
|
AllowedValues(const string_type& v1, const string_type& v2)
|
||||||
|
{
|
||||||
|
allowed_.insert(v1);
|
||||||
|
allowed_.insert(v2);
|
||||||
|
} // AllowedValues
|
||||||
|
|
||||||
|
AllowedValues(const AllowedValues& rhs) :
|
||||||
|
allowed_(rhs.allowed_)
|
||||||
|
{
|
||||||
|
} // AllowedValues
|
||||||
|
|
||||||
|
bool is_allowed(const string_type& v) const
|
||||||
|
{
|
||||||
|
if(allowed_.size() == 0)
|
||||||
|
return true;
|
||||||
|
return allowed_.find(v) != allowed_.end();
|
||||||
|
} // is_allowed
|
||||||
|
|
||||||
|
AllowedValues& operator=(const AllowedValues& rhs)
|
||||||
|
{
|
||||||
|
allowed_ = rhs.allowed_;
|
||||||
|
return *this;
|
||||||
|
} // operator=
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::set<string_type> allowed_;
|
||||||
|
}; // AllowedValues
|
||||||
|
|
||||||
template<class string_type, class string_adaptor>
|
template<class string_type, class string_adaptor>
|
||||||
class AttributeValidator
|
class AttributeValidator
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
AttributeValidator() :
|
||||||
|
required_(false)
|
||||||
|
{
|
||||||
|
} // AttributeValidator
|
||||||
|
|
||||||
|
bool mandatory() const { return required_; }
|
||||||
|
bool has_default() const { return !def_.empty(); }
|
||||||
|
const string_type& default_value() const { return def_; }
|
||||||
|
bool is_allowed(const string_type& v) const { return allowed_.is_allowed(v); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit AttributeValidator(bool required) :
|
explicit AttributeValidator(bool required) :
|
||||||
required_(required)
|
required_(required)
|
||||||
{
|
{
|
||||||
} // AttributeValidator
|
} // AttributeValidator
|
||||||
|
|
||||||
|
AttributeValidator(bool required, const string_type& def, const AllowedValues<string_type> allowed) :
|
||||||
|
required_(required),
|
||||||
|
def_(def),
|
||||||
|
allowed_(allowed)
|
||||||
|
{
|
||||||
|
} // AttributeValidator
|
||||||
|
|
||||||
bool required_;
|
bool required_;
|
||||||
|
string_type def_;
|
||||||
|
AllowedValues<string_type> allowed_;
|
||||||
|
|
||||||
|
AttributeValidator& operator=(const AttributeValidator& rhs)
|
||||||
|
{
|
||||||
|
required_ = rhs.required_;
|
||||||
|
def_ = rhs.def_;
|
||||||
|
allowed_ = rhs.allowed_;
|
||||||
|
return *this;
|
||||||
|
} // operator=
|
||||||
|
|
||||||
friend class AttributeValidators<string_type, string_adaptor>;
|
friend class AttributeValidators<string_type, string_adaptor>;
|
||||||
}; // class AttributeValidator
|
}; // class AttributeValidator
|
||||||
|
@ -26,28 +90,113 @@ private:
|
||||||
template<class string_type, class string_adaptor>
|
template<class string_type, class string_adaptor>
|
||||||
class AttributeValidators
|
class AttributeValidators
|
||||||
{
|
{
|
||||||
|
typedef StylesheetConstant<string_type, string_adaptor> SC;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static AttributeValidatorsBuilder rule(const string_type& name, bool required);
|
static AttributeValidatorsBuilder<string_type, string_adaptor> rule(const string_type& name, bool required);
|
||||||
|
|
||||||
|
std::map<string_type, string_type> gather(const string_type& parentElement,
|
||||||
|
const SAX::Attributes<string_type, string_adaptor>& atts) const
|
||||||
|
{
|
||||||
|
typedef StylesheetConstant<string_type, string_adaptor> SC;
|
||||||
|
|
||||||
|
std::map<string_type, string_type> results;
|
||||||
|
|
||||||
|
for(ValidatorMapIterator r = rules_.begin(); r != rules_.end(); ++r)
|
||||||
|
{
|
||||||
|
const string_type& name = r->first;
|
||||||
|
const AttributeValidator<string_type, string_adaptor>& av = r->second;
|
||||||
|
if((av.mandatory()) && (atts.getValue(name).empty()))
|
||||||
|
throw SAX::SAXException(string_adaptor::asStdString(parentElement) + ": Attribute " + string_adaptor::asStdString(name) + " must be specified");
|
||||||
|
if(av.has_default())
|
||||||
|
results[name] = av.default_value();
|
||||||
|
} // for ...
|
||||||
|
|
||||||
|
for(int a = 0; a < atts.getLength(); ++a)
|
||||||
|
{
|
||||||
|
const string_type& name = atts.getLocalName(a);
|
||||||
|
if(name == string_adaptor::empty_string())
|
||||||
|
continue; // namespace decl
|
||||||
|
|
||||||
|
const string_type& uri = atts.getURI(a);
|
||||||
|
const string_type& value = atts.getValue(a);
|
||||||
|
|
||||||
|
results[name] = value;
|
||||||
|
|
||||||
|
if(uri == string_adaptor::empty_string())
|
||||||
|
validateAttribute(parentElement, name, value);
|
||||||
|
else if(uri == SC::xml_uri)
|
||||||
|
validateXmlAttribute(parentElement, name, value); // special xml: attributes
|
||||||
|
} // for ...
|
||||||
|
|
||||||
|
return results;
|
||||||
|
} // gather
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void validateXmlAttribute(const string_type& parentElement,
|
||||||
|
const string_type& name,
|
||||||
|
const string_type& value) const
|
||||||
|
{
|
||||||
|
if(name == SC::space)
|
||||||
|
validateValues(parentElement, name, value, XMLSpaceValidator);
|
||||||
|
} // validateXmlAttribute
|
||||||
|
|
||||||
|
void validateAttribute(const string_type& parentElement,
|
||||||
|
const string_type& name,
|
||||||
|
const string_type& value) const
|
||||||
|
{
|
||||||
|
ValidatorMapIterator r = rules_.find(name);
|
||||||
|
|
||||||
|
if(r == rules_.end())
|
||||||
|
throw SAX::SAXException(string_adaptor::asStdString(parentElement) + ": Illegal attribute " + string_adaptor::asStdString(name));
|
||||||
|
|
||||||
|
validateValues(parentElement, name, value, r->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void validateValues(const string_type& parentElement,
|
||||||
|
const string_type& name,
|
||||||
|
const string_type& value,
|
||||||
|
const AttributeValidator<string_type, string_adaptor>& rule) const
|
||||||
|
{
|
||||||
|
if(rule.is_allowed(value))
|
||||||
|
return;
|
||||||
|
|
||||||
|
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, bool required)
|
||||||
{
|
{
|
||||||
rules_[name] = AttributeValidate(required);
|
rules_[name] = AttributeValidator<string_type, string_adaptor>(required);
|
||||||
} // put
|
} // put
|
||||||
|
|
||||||
AttributeValidators() { }
|
AttributeValidators() { }
|
||||||
|
|
||||||
typedef std::map<string_type, AttributeValidator<string_type, string_adaptor> > ValidatorMap;
|
typedef std::map<string_type, AttributeValidator<string_type, string_adaptor> > ValidatorMap;
|
||||||
typedef typename std::map<string_type, AttributeValidator<string_type, string_adaptor> >::const_iterator ValidatorMapIterator;
|
typedef typename ValidatorMap::const_iterator ValidatorMapIterator;
|
||||||
|
|
||||||
ValidatorMap rules_;
|
ValidatorMap rules_;
|
||||||
};
|
|
||||||
|
static const AttributeValidator<string_type, string_adaptor> XMLSpaceValidator;
|
||||||
|
|
||||||
|
friend class AttributeValidatorsBuilder<string_type, string_adaptor>;
|
||||||
|
}; // class AttributeValidators
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
const AttributeValidator<string_type, string_adaptor>
|
||||||
|
AttributeValidators<string_type, string_adaptor>::XMLSpaceValidator(false,
|
||||||
|
string_adaptor::empty_string(),
|
||||||
|
AllowedValues<string_type>(string_adaptor::construct_from_utf8("default"),
|
||||||
|
string_adaptor::construct_from_utf8("preserve")));
|
||||||
|
|
||||||
template<class string_type, class string_adaptor>
|
template<class string_type, class string_adaptor>
|
||||||
class AttributeValidatorsBuilder
|
class AttributeValidatorsBuilder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
operator AttributeValidator<string_type, string_adaptor>&() { return validators_; }
|
operator AttributeValidators<string_type, string_adaptor>&() { return validators_; }
|
||||||
|
|
||||||
AttributeValidatorsBuilder& rule(const string_type& name, bool required)
|
AttributeValidatorsBuilder& rule(const string_type& name, bool required)
|
||||||
{
|
{
|
||||||
|
@ -58,11 +207,11 @@ public:
|
||||||
private:
|
private:
|
||||||
AttributeValidatorsBuilder() { }
|
AttributeValidatorsBuilder() { }
|
||||||
AttributeValidatorsBuilder(const AttributeValidatorsBuilder& rhs) :
|
AttributeValidatorsBuilder(const AttributeValidatorsBuilder& rhs) :
|
||||||
validators_(validators)
|
validators_(rhs.validators_)
|
||||||
{
|
{
|
||||||
} // AttributeValidatorsBuilder
|
} // AttributeValidatorsBuilder
|
||||||
|
|
||||||
AttributeValidator<string_type, string_adaptor> validators_;
|
AttributeValidators<string_type, string_adaptor> validators_;
|
||||||
|
|
||||||
friend class AttributeValidators<string_type, string_adaptor>;
|
friend class AttributeValidators<string_type, string_adaptor>;
|
||||||
}; // class AttributeValidatorsBuilder
|
}; // class AttributeValidatorsBuilder
|
||||||
|
|
|
@ -25,6 +25,7 @@ template<class string_type, class string_adaptor>
|
||||||
class StylesheetHandler : public SAX::DefaultHandler<string_type, string_adaptor>
|
class StylesheetHandler : public SAX::DefaultHandler<string_type, string_adaptor>
|
||||||
{
|
{
|
||||||
typedef StylesheetConstant<string_type, string_adaptor> SC;
|
typedef StylesheetConstant<string_type, string_adaptor> SC;
|
||||||
|
typedef AttributeValidators<string_type, string_adaptor> AV;
|
||||||
public:
|
public:
|
||||||
typedef string_type stringT;
|
typedef string_type stringT;
|
||||||
typedef string_adaptor string_adaptorT;
|
typedef string_adaptor string_adaptorT;
|
||||||
|
@ -94,12 +95,12 @@ private:
|
||||||
if(localName != SC::stylesheet && localName != SC::transform)
|
if(localName != SC::stylesheet && localName != SC::transform)
|
||||||
throw SAX::SAXException("Top-level element must be 'stylesheet' or 'transform'.");
|
throw SAX::SAXException("Top-level element must be 'stylesheet' or 'transform'.");
|
||||||
|
|
||||||
static const ValueRule<string_type> rules[] = { { SC::version, true },
|
static const AV rules = AV::rule(SC::version, true)
|
||||||
{ SC::extension_element_prefixes, false },
|
.rule(SC::extension_element_prefixes, false)
|
||||||
{ SC::exclude_result_prefixes, false },
|
.rule(SC::exclude_result_prefixes, false)
|
||||||
{ SC::id, false },
|
.rule(SC::id, false);
|
||||||
{ string_adaptor::empty_string(), false } };
|
|
||||||
std::map<string_type, string_type> attributes = gatherAttributes(qName, atts, rules);
|
std::map<string_type, string_type> attributes = rules.gather(qName, atts);
|
||||||
if(attributes[SC::version] != SC::Version)
|
if(attributes[SC::version] != SC::Version)
|
||||||
throw SAX::SAXException("I'm only a poor version 1.0 XSLT Transformer.");
|
throw SAX::SAXException("I'm only a poor version 1.0 XSLT Transformer.");
|
||||||
if(!attributes[SC::extension_element_prefixes].empty())
|
if(!attributes[SC::extension_element_prefixes].empty())
|
||||||
|
|
|
@ -51,8 +51,8 @@ int main(int argc, const char* argv[])
|
||||||
|
|
||||||
Loader loader;
|
Loader loader;
|
||||||
|
|
||||||
add_tests(runner, loader, tests_to_run, xalan_tests);
|
//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, msft_tests);
|
||||||
add_arabica_tests(runner, loader, tests_to_run, arabica_tests);
|
add_arabica_tests(runner, loader, tests_to_run, arabica_tests);
|
||||||
|
|
||||||
runner.run(argc, argv);
|
runner.run(argc, argv);
|
||||||
|
|
Loading…
Reference in a new issue