working on the IdKey match pattern - currently crashes

This commit is contained in:
jez 2009-03-17 21:08:26 +00:00
parent 1a33572c06
commit 83cd0cd15b
4 changed files with 151 additions and 71 deletions

View file

@ -342,14 +342,14 @@ struct xpath_grammar_match : public boost::spirit::grammar<xpath_grammar_match>
// [2] LocationPathPattern ::= '/' RelativePathPattern?
// | IdKeyPattern (('/' | '//') RelativePathPattern)?
// | '//'? RelativePathPattern
LocationPathPattern = !base::SlashSlash >> RelativePathPattern |
base::Slash >> !RelativePathPattern |
IdKeyPattern >> !((base::SlashSlash | base::Slash) >> RelativePathPattern);
LocationPathPattern = IdKeyPattern >> !((base::SlashSlash | base::Slash) >> RelativePathPattern) |
!base::SlashSlash >> RelativePathPattern |
base::Slash >> !RelativePathPattern;
// [3] IdKeyPattern ::= 'id' '(' Literal ')' | 'key' '(' Literal ',' Literal ')'
IdKeyPattern = str_p("id") >> base::LeftBracket >> base::Literal >> base::RightBracket |
str_p("key") >> base::LeftBracket >> base::Literal >> ',' >> base::Literal >> base::RightBracket;
IdKeyPattern = (str_p("id") >> base::LeftBracket >> base::Literal >> base::RightBracket) |
(str_p("key") >> base::LeftBracket >> base::Literal >> ',' >> base::Literal >> base::RightBracket);
// [4] RelativePathPattern ::= StepPattern
// | RelativePathPattern '/' StepPattern

View file

@ -248,6 +248,7 @@ private:
static XPathExpression_impl<string_type, string_adaptor>* createSingleMatchStep(typename impl::types<string_adaptor>::node_iter_t const& i, typename impl::types<string_adaptor>::node_iter_t const& ie, impl::CompilationContext<string_type, string_adaptor>& context);
static XPathExpression_impl<string_type, string_adaptor>* createRelativePathPattern(typename impl::types<string_adaptor>::node_iter_t const& i, typename impl::types<string_adaptor>::node_iter_t const& ie, impl::CompilationContext<string_type, string_adaptor>& context);
static XPathExpression_impl<string_type, string_adaptor>* createAlternatePattern(typename impl::types<string_adaptor>::node_iter_t const& i, typename impl::types<string_adaptor>::node_iter_t const& ie, impl::CompilationContext<string_type, string_adaptor>& context);
static XPathExpression_impl<string_type, string_adaptor>* createIdKeyPattern(typename impl::types<string_adaptor>::node_iter_t const& i, typename impl::types<string_adaptor>::node_iter_t const& ie, impl::CompilationContext<string_type, string_adaptor>& context);
static double defaultPriority(typename impl::types<string_adaptor>::node_iter_t const& i,
typename impl::types<string_adaptor>::node_iter_t const& ie);
@ -349,6 +350,7 @@ private:
factory[impl::LocationPathPattern_id] = createRelativePathPattern;
factory[impl::RelativePathPattern_id] = createRelativePathPattern;
factory[impl::Pattern_id] = createAlternatePattern;
factory[impl::IdKeyPattern_id] = createIdKeyPattern;
return factory;
} // init_matchCreateFunctions
@ -792,6 +794,13 @@ XPathExpression_impl<string_type, string_adaptor>* XPath<string_type, string_ada
return matches;
} // createAlternatePattern
template<class string_type, class string_adaptor>
XPathExpression_impl<string_type, string_adaptor>* XPath<string_type, string_adaptor>::createIdKeyPattern(typename impl::types<string_adaptor>::node_iter_t const& i, typename impl::types<string_adaptor>::node_iter_t const& ie, impl::CompilationContext<string_type, string_adaptor>& context)
{
XPathExpression_impl<string_type, string_adaptor>* fn = createFunction(i, ie, context);
return new impl::MatchExpressionWrapper<string_type, string_adaptor>(fn, defaultPriority(i, ie));
} // createIdKeyPattern
template<class string_type, class string_adaptor>
double XPath<string_type, string_adaptor>::defaultPriority(typename impl::types<string_adaptor>::node_iter_t const& node,
typename impl::types<string_adaptor>::node_iter_t const& end)

View file

@ -1,69 +1,69 @@
#ifndef ARABICA_XSLT_OUTPUT_HANDLER_HPP
#define ARABICA_XSLT_OUTPUT_HANDLER_HPP
#include "xslt_value_validation.hpp"
namespace Arabica
{
namespace XSLT
{
class OutputHandler : public SAX::DefaultHandler<std::string>
{
public:
OutputHandler(CompilationContext& context) :
context_(context)
{
} // OutputHandler
virtual void startElement(const std::string& namespaceURI,
const std::string& localName,
const std::string& qName,
const SAX::Attributes<std::string>& atts)
{
if(settings_.empty())
{
static const char* AllowedMethods[] = { "xml", "html", "text", 0 };
static const ValueRule rules[] = { { "method", false, "xml", AllowedMethods },
{ "version", false, "1.0" },
{ "encoding", false, "UTF-8" },
{ "omit-xml-declaration", false, No, AllowedYesNo },
{ "standalone", false, "", AllowedYesNo },
{ "doctype-public", false, ""},
{ "doctype-system", false, ""},
{ "cdata-section-elements", false, ""},
{ "indent", false, No, AllowedYesNo },
{ "media-type", false, "" },
{ 0, false, 0 } };
settings_ = gatherAttributes(qName, atts, rules);
return;
} // if(settings_ == 0)
throw SAX::SAXException(qName + " can not contain elements");
} // startElement
virtual void endElement(const std::string& namespaceURI,
const std::string& localName,
const std::string& qName)
{
context_.stylesheet().output_settings(settings_);
context_.pop();
} // endElement
virtual void characters(const std::string& ch)
{
#ifndef ARABICA_XSLT_OUTPUT_HANDLER_HPP
#define ARABICA_XSLT_OUTPUT_HANDLER_HPP
#include "xslt_value_validation.hpp"
namespace Arabica
{
namespace XSLT
{
class OutputHandler : public SAX::DefaultHandler<std::string>
{
public:
OutputHandler(CompilationContext& context) :
context_(context)
{
} // OutputHandler
virtual void startElement(const std::string& namespaceURI,
const std::string& localName,
const std::string& qName,
const SAX::Attributes<std::string>& atts)
{
if(settings_.empty())
{
static const char* AllowedMethods[] = { "xml", "html", "text", 0 };
static const ValueRule rules[] = { { "method", false, "xml", AllowedMethods },
{ "version", false, "1.0" },
{ "encoding", false, "UTF-8" },
{ "omit-xml-declaration", false, No, AllowedYesNo },
{ "standalone", false, "", AllowedYesNo },
{ "doctype-public", false, ""},
{ "doctype-system", false, ""},
{ "cdata-section-elements", false, ""},
{ "indent", false, No, AllowedYesNo },
{ "media-type", false, "" },
{ 0, false, 0 } };
settings_ = gatherAttributes(qName, atts, rules);
return;
} // if(settings_ == 0)
throw SAX::SAXException(qName + " can not contain elements");
} // startElement
virtual void endElement(const std::string& namespaceURI,
const std::string& localName,
const std::string& qName)
{
context_.stylesheet().output_settings(settings_);
context_.pop();
} // endElement
virtual void characters(const std::string& ch)
{
for(std::string::const_iterator i = ch.begin(), e = ch.end(); i != e; ++i)
if(!Arabica::XML::is_space(*i))
throw SAX::SAXException("xsl:value-of element must be empty");
} // characters
private:
CompilationContext& context_;
Output::Settings settings_;
}; // class OutputHandler
} // namespace XSLT
} // namespace Arabica
#endif
} // characters
private:
CompilationContext& context_;
Output::Settings settings_;
}; // class OutputHandler
} // namespace XSLT
} // namespace Arabica
#endif

View file

@ -9,11 +9,66 @@
#include <DOM/SAX2DOM/SAX2DOM.hpp>
#include <SAX/helpers/CatchErrorHandler.hpp>
template<class string_type, class string_adaptor>
class TestIdFunction : public Arabica::XPath::XPathFunction<string_type, string_adaptor>
{
public:
TestIdFunction(const std::vector<Arabica::XPath::XPathExpression<string_type, string_adaptor> >& args) :
Arabica::XPath::XPathFunction<string_type, string_adaptor>(1, 1, args) { }
virtual Arabica::XPath::ValueType type() const { return Arabica::XPath::STRING; }
virtual Arabica::XPath::XPathValue_impl<string_type, string_adaptor>* evaluate(const Arabica::DOM::Node<string_type, string_adaptor>& context,
const Arabica::XPath::ExecutionContext<string_type, string_adaptor>& executionContext) const
{
string_type name = string_adaptor::construct_from_utf8("test-");
string_adaptor::append(name, context.getLocalName());
return new Arabica::XPath::StringValue<string_type, string_adaptor>(name);
} // evaluate
}; // TestIdFunction
template<class string_type, class string_adaptor>
class TestKeyFunction : public Arabica::XPath::XPathFunction<string_type, string_adaptor>
{
public:
TestKeyFunction(const std::vector<Arabica::XPath::XPathExpression<string_type, string_adaptor> >& args) :
Arabica::XPath::XPathFunction<string_type, string_adaptor>(2, 2, args) { }
virtual Arabica::XPath::ValueType type() const { return Arabica::XPath::STRING; }
virtual Arabica::XPath::XPathValue_impl<string_type, string_adaptor>* evaluate(const Arabica::DOM::Node<string_type, string_adaptor>& context,
const Arabica::XPath::ExecutionContext<string_type, string_adaptor>& executionContext) const
{
string_type name = string_adaptor::construct_from_utf8("test-");
string_adaptor::append(name, context.getLocalName());
return new Arabica::XPath::StringValue<string_type, string_adaptor>(name);
} // evaluate
}; // TestKeyFunction
template<class string_type, class string_adaptor>
class TestIdKeyFunctionResolver : public Arabica::XPath::FunctionResolver<string_type, string_adaptor>
{
//typedef string_adaptorstring_adaptor;
public:
virtual Arabica::XPath::XPathFunction<string_type, string_adaptor>* resolveFunction(
const string_type& namespace_uri,
const string_type& name,
const std::vector<Arabica::XPath::XPathExpression<string_type, string_adaptor> >& argExprs) const
{
if(name == string_adaptor::construct_from_utf8("id"))
return new TestIdFunction<string_type, string_adaptor>(argExprs);
if(name == string_adaptor::construct_from_utf8("key"))
return new TestKeyFunction<string_type, string_adaptor>(argExprs);
return 0;
} // resolveFunction
}; // class TestFunctionResolver
template<class string_type, class string_adaptor>
class MatchTest : public TestCase
{
Arabica::XPath::XPath<string_type, string_adaptor> parser;
TestIdKeyFunctionResolver<string_type, string_adaptor> tfr;
typedef string_adaptor SA;
public:
@ -23,6 +78,7 @@ public:
void setUp()
{
parser.setFunctionResolver(tfr);
} // setUp
void testParse()
@ -337,6 +393,19 @@ public:
assertEquals(0, matchPriority("foo"), 0);
} // testPriority4
void testIdKey()
{
assertTrue(compileThis("id('nob')"));
assertTrue(compileThis("id( 'nob' )"));
assertFalse(compileThis("id(nob)"));
} // testIdKey
void testIdKey2()
{
assertTrue(compileThis("key('a', 'b')"));
assertFalse(compileThis("key(a, b)"));
} // testIdKey2
bool dontCompileThis(const char* path)
{
try {
@ -437,6 +506,8 @@ TestSuite* MatchTest_suite()
suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testPriority2", &MatchTest<string_type, string_adaptor>::testPriority2));
suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testPriority3", &MatchTest<string_type, string_adaptor>::testPriority3));
suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testPriority4", &MatchTest<string_type, string_adaptor>::testPriority4));
suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testIdKey", &MatchTest<string_type, string_adaptor>::testIdKey));
suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testIdKey2", &MatchTest<string_type, string_adaptor>::testIdKey2));
return suiteOfTests;
} // MatchTest_suite