From f414c323517df43989547b52888cf8936ed36987 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Tue, 10 Mar 2009 19:23:57 +0000 Subject: [PATCH] Base template for loops on a single multimap. --- xmltooling/util/TemplateEngine.cpp | 48 +++++++++++++++++++--------------- xmltooling/util/TemplateEngine.h | 51 ++++++++++++++++++++----------------- xmltoolingtest/TemplateEngineTest.h | 3 +++ xmltoolingtest/data/template.in | 4 +++ xmltoolingtest/data/template.out | 6 +++++ 5 files changed, 69 insertions(+), 43 deletions(-) diff --git a/xmltooling/util/TemplateEngine.cpp b/xmltooling/util/TemplateEngine.cpp index 2333c8c..4a165d5 100644 --- a/xmltooling/util/TemplateEngine.cpp +++ b/xmltooling/util/TemplateEngine.cpp @@ -26,6 +26,10 @@ using namespace xmltooling; using namespace std; +namespace { + static const pair emptyPair; +} + void TemplateEngine::setTagPrefix(const char* tagPrefix) { keytag = string("<") + tagPrefix + " "; @@ -94,6 +98,7 @@ void TemplateEngine::process( const char*& lastpos, ostream& os, const TemplateParameters& parameters, + const std::pair& loopentry, const XMLToolingException* e ) const { @@ -120,11 +125,17 @@ void TemplateEngine::process( string key = buf.substr(lastpos-line, thispos-lastpos); trimspace(key); - const char* p = parameters.getParameter(key.c_str()); - if (!p && e) - p = e->getProperty(key.c_str()); - if (p) - html_encode(os,p); + if (key == "$name" && !loopentry.first.empty()) + html_encode(os,loopentry.first.c_str()); + else if (key == "$value" && !loopentry.second.empty()) + html_encode(os,loopentry.second.c_str()); + else { + const char* p = parameters.getParameter(key.c_str()); + if (!p && e) + p = e->getProperty(key.c_str()); + if (p) + html_encode(os,p); + } lastpos = thispos + 2; // strlen("/>") } } @@ -145,7 +156,7 @@ void TemplateEngine::process( if (visible) cond = parameters.getParameter(key.c_str()) || (e && e->getProperty(key.c_str())); lastpos = thispos + 1; // strlen(">") - process(cond, buf, lastpos, os, parameters, e); + process(cond, buf, lastpos, os, parameters, loopentry, e); } } #ifdef HAVE_STRCASECMP @@ -175,7 +186,7 @@ void TemplateEngine::process( if (visible) cond = !(parameters.getParameter(key.c_str()) || (e && e->getProperty(key.c_str()))); lastpos = thispos + 1; // strlen(">") - process(cond, buf, lastpos, os, parameters, e); + process(cond, buf, lastpos, os, parameters, loopentry, e); } } #ifdef HAVE_STRCASECMP @@ -207,20 +218,17 @@ void TemplateEngine::process( lastpos = thispos + 1; // strlen(">") } - const vector& forParams = parameters.getParameterCollection(key.c_str()); - vector::size_type forend = forParams.size(); - if (forend == 0) { // have to go through at least once to match end tags - cond = false; - forend = 1; + const multimap* forParams = parameters.getLoopCollection(key.c_str()); + if (!forParams || forParams->size() == 0) { + process(false, buf, lastpos, os, parameters, emptyPair, e); } - - const char *savlastpos = lastpos; - for (vector::size_type i=0; i0 ? forParams[i] : nullp), e); + else { + const char* savlastpos = lastpos; + for (multimap::const_iterator i=forParams->begin(); i!=forParams->end(); ++i) { + lastpos = savlastpos; + process(cond, buf, lastpos, os, parameters, *i, e); + } } - } #ifdef HAVE_STRCASECMP @@ -252,5 +260,5 @@ void TemplateEngine::run(istream& is, ostream& os, const TemplateParameters& par buf += line + '\n'; const char* pos=buf.c_str(); - process(true, buf, pos, os, parameters, e); + process(true, buf, pos, os, parameters, emptyPair, e); } diff --git a/xmltooling/util/TemplateEngine.h b/xmltooling/util/TemplateEngine.h index 4023b52..eba0689 100644 --- a/xmltooling/util/TemplateEngine.h +++ b/xmltooling/util/TemplateEngine.h @@ -1,6 +1,6 @@ /* * Copyright 2001-2009 Internet2 - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,7 +16,7 @@ /** * @file xmltooling/util/TemplateEngine.h - * + * * Simple template replacement engine. */ @@ -44,8 +44,10 @@ namespace xmltooling { *
  • <mlpif key> stuff </mlpif>
  • *
  • <mlpifnot key> stuff </mlpifnot>
  • *
  • <mlpfor key> stuff </mlpfor>
  • + *
  • <mlp $name/> (in for loop only)
  • + *
  • <mlp $value/> (in for loop only)
  • * - * + * * The default tag prefix is "mlp". This can be overridden for * compatibility. */ @@ -54,18 +56,18 @@ namespace xmltooling { MAKE_NONCOPYABLE(TemplateEngine); public: TemplateEngine() { - setTagPrefix("mlp"); + setTagPrefix("mlp"); } virtual ~TemplateEngine() {} - + /** * Sets the tag name to use when locating template replacement tags. - * + * * @param tagPrefix base prefix for tags */ void setTagPrefix(const char* tagPrefix); - + /** * Interface to parameters to plug into templates. * Allows callers to supply a more dynamic lookup mechanism to supplement a basic map. @@ -75,17 +77,19 @@ namespace xmltooling { public: TemplateParameters() : m_request(NULL) {} virtual ~TemplateParameters() {} - + /** Map of known parameters to supply to template. */ std::map m_map; - std::map > m_collectionMap; - + + /** Map of sub-collections used in for loops. */ + std::map< std::string,std::multimap > m_collectionMap; + /** Request from client that resulted in template being processed. */ const GenericRequest* m_request; - + /** * Returns the value of a parameter to plug into the template. - * + * * @param name name of parameter * @return value of parameter, or NULL */ @@ -95,21 +99,21 @@ namespace xmltooling { } /** - * Returns the collection of parameters to plug into the template. - * - * @param name name of parameter collection - * @return vector of parameters + * Returns a named collection of sub-parameters to pass into a loop. + * + * @param name name of sub-collection + * @return pointer to a multimap of sub-parameters, or NULL */ - virtual const std::vector& getParameterCollection(const char* name) const { - std::map >::const_iterator i=m_collectionMap.find(name); - return (i->second); + virtual const std::multimap* getLoopCollection(const char* name) const { + std::map< std::string,std::multimap >::const_iterator i=m_collectionMap.find(name); + return (i!=m_collectionMap.end() ? &(i->second) : NULL); } }; - + /** * Processes template from an input stream and executes replacements and - * conditional logic based on parameters. - * + * conditional logic based on parameters. + * * @param is input stream providing template * @param os output stream to send results of executing template * @param parameters parameters to plug into template @@ -137,9 +141,10 @@ namespace xmltooling { const char*& lastpos, std::ostream& os, const TemplateParameters& parameters, + const std::pair& loopentry, const XMLToolingException* e ) const; - + std::string keytag,iftag,ifendtag,ifnottag,ifnotendtag,fortag,forendtag; }; }; diff --git a/xmltoolingtest/TemplateEngineTest.h b/xmltoolingtest/TemplateEngineTest.h index ae7c40c..169def6 100644 --- a/xmltoolingtest/TemplateEngineTest.h +++ b/xmltoolingtest/TemplateEngineTest.h @@ -35,6 +35,9 @@ public: p.m_map["foo1"] = "bar1"; p.m_map["foo3"] = "bar3"; p.m_map["encoded"] = "http://www.example.org/foo/bar#foobar"; + multimap& submap = p.m_collectionMap["sub"]; + submap.insert(pair("subfoo1", "subbar1")); + submap.insert(pair("subfoo2", "subbar2")); string path = data_path + "template.in"; ifstream in(path.c_str()); diff --git a/xmltoolingtest/data/template.in b/xmltoolingtest/data/template.in index 793812e..08c86c7 100644 --- a/xmltoolingtest/data/template.in +++ b/xmltoolingtest/data/template.in @@ -13,3 +13,7 @@ This is a template containing tags for substitution by the template engine. + + + + diff --git a/xmltoolingtest/data/template.out b/xmltoolingtest/data/template.out index 2eb8e9f..0929086 100644 --- a/xmltoolingtest/data/template.out +++ b/xmltoolingtest/data/template.out @@ -13,3 +13,9 @@ bar3 http://www.example.org/foo/bar#foobar + + + subfoo1 bar1 subbar1 + + subfoo2 bar1 subbar2 + -- 2.1.4