Templator(GitHub) -- An Advanced text templating engine


CodeExample

This page you are looking at is generated by Templator, please refer to the template as an example, corresponding calling code is here

To use this library:

  • Initialize an instance of Templator Config. customize it if necessary
  • Assign an instance of ILogger to the config object, or leave it default and later use ((TemplatorLogger)config.TemplatorLogger).Errors to retrieve parser errors
  • Initialize an instance of TemplatorParser with the config object
  • Construct a IDictionary<string, object> as input or use TemplatorUtil.ParseJsonDict(string) method to parse a Json object as input
  • Load text/xml template as string or stream
  • var outPut = parser.LoadXmlTemplate(stream, input); or parser.ParseXml, or parser.LoadTextTemplate etc.. will generate the parsed string
  • Check the logger object (((TemplatorLogger)config.TemplatorLogger).Errors by default) for parsing errors
  • parser.Holders will give out the holders defined inside the template

Helper tools:

Get Started

Search for 'Templator' in nuget package manager, current version 1.0.0.5

Philosophy

Try to Create a text processing engine with the ability to produce all kinds of formated text using a unified input structure, with the ability to be fully customized in order to overcome any possible symbol conflicts.

Template Usage

Simply put the a place holder at the position of the text file which you want to output to, put the desired value inside the input dictionary with the name of the holder as Key, further, the usage of the rich keywords will enable programmer to calculated/validate/re-format against the input value

Syntax of a TextHolder

With the format of {{HolderName}} or {{Category(HolderName)}} or {{Category(HolderName)[Keyword1(Param1),Keyword2()]}}, simply wrap the holder name with in the begin tag({{) and end tag(}}) will produce a TextHolder, the tags are all customizable in the config object. See examples below:
  • Basic:

    {{HolderName}}
  • Categorized:

    {{Category(HolderName)}}
  • With Parameter:

    {{HolderName[Number(#.##)]}},{{Category(HolderName)[Number(#.##)]}}, see keywords document for details
  • Nested holders:

    Nested holders is to make a block which wraps other TextHolers so that it can be controlled by If conditions
  • Nested Text:

    {{Holder[]FreeTextAfterHolderInput}} or {{(Holder)FreeTextBeforeHolderItSelf[If]}}
  • Nested holders, nested value comes before:

    {{(Holder){{AnotherOne}}[]}} or {{(Holder){{AnotherOne}}}}
  • Nested holders, nested value comes After:

    {{(Holder)[]{{AnotherOne}}}} or {{(Holder)[If(ConditionHolder)]{{AnotherOne}}}}

Build phase validation

Nuget Search for package 'TemplatorSyntaxBuildTask', install it to the project which contains your templates, the task will add a 'TemplatorConfig.xml' into the project and load configurations from it:
  • Path:

    The path which the task will only look into, default 'Templates'
  • Filters:

    The file extension filters, default '.xml,.csv,.txt'
  • Depth:

    The depth inside the directory the task will look into, default 3

Editor SyntaxHighlighting

Beta ready, The project 'TemplatorVsExtension' is providing syntax highlighting in visual studio. based on TemplatorConfig.xml in the project
  • Version:

    beta-0.1.0, now supports vs2013 and vs2015.
  • Strategy:

    In order to get less impact to vs performance in regular work, the extension will only try to parse the active document(xml,csv,txt) if the active project contains a valid 'TemplatorConfig.xml'
  • Multiple Projects:

    Templates contained in multiple projects will be parsed based on each project's 'TemplatorConfig.xml', which enables different format highlighting for different project needs
  • Config changes:

    If the 'TemplatorConfig.xml' is changed inside visual studio, the extension will get the change, and the opened template documents needs to be reopened to get fully renewed.

Extensibility

Implement a TemplatorKeyWord and use AddKeyword method to add it to config object before passing it to the parser(or if after, call PrepareKeywords() to refresh the keywords), See below for the options:
  • Name:

    The identifier of the Keyword
  • Priority:

    Affects the order of the keywords while processing, the order logic is Desending: CalculateInput -> ManipulateInput -> IsValidation && !k.ManipulateOutput -> IsValidation ManipulateOutput -> ascending, Priority
  • HandleNullOrEmpty:

    Indicates if Null or Empty string will be passed in to the OnGetValue or skip
  • IndicatesOptional:

    Indicates this holder is optional if the keyword presents
  • CalculateInput:

    Indicates if the keyword will calculate a value as input, the input will be cached back automatically for it
  • ManipulateInput:

    Indicates if the keyword will change a input value, the changed input will be cached back automatically for it
  • ManipulateOutput:

    Indicates if the keyword will change a output value, the changed value will NOT be cached
  • IsValidation:

    Indicates if the keyword is doing validation
  • PostParse:

    Delegate called after the TextHolder is parsed before trying to get the value
  • Parse:

    Delegate called when a keyword's param is found, if null, the param will be stored as is, to access the param, use holder["keywordname"]
  • OnGetValue:

    Delegate called when the holder is being processed to get value if defined, null/empty values will not get in unless HandleNullOrEmpty is set to true

Configuration

Templator allows to be fully customized through config object, see the following options for details:
  • XmlTemplatorAttributeName:

    The reserved xml attribute to hold Templator used xml manipulation TextHolders such as Collections, this attribute will be removed while processing
  • ReservedKeywordParent:

    When goes deeper level into an Array/Repeat/Collection, the parent input will be stored in the current input with this string as key
  • ReservedKeywordIndex:

    When looping arrays/repeat/collection, retrieve the 1 based index with this name
  • ReservedKeyword0Index:

    When looping arrays/repeat/collection, retrieve the 0 based index with this name
  • EscapePrefix:

    An escape character when parsing template
  • Begin:

    The beginning of a TextHolder, configurable in case of symbol conflict, default '{{'
  • End:

    The ending of a TextHolder, configurable in case of symbol conflict, default '}}'
  • Delimiter:

    The delimiter of keywords, configurable in case of symbol conflict, default ','
  • ParamBegin:

    The beginning of a keyword's param, configurable in case of symbol conflict, default '('
  • ParamEnd:

    The ending of a keyword's param, configurable in case of symbol conflict, default ')'
  • CategorizedNameBegin:

    The beginning of the TextHolders' name if category exists, configurable in case of symbol conflict, default '('
  • CategorizedNameEnd:

    The ending of the TextHolders' name if category exists, configurable in case of symbol conflict, default ')'
  • KeywordsBegin:

    The beginning of the keyword collection, configurable in case of symbol conflict, default '['
  • KeywordsEnd:

    The ending of the keyword collection, configurable in case of symbol conflict, default ']'
  • Logger:

    The TemplatorLogger object used for parser to log errors
  • OnRequireInput:

    An event fired by the parser when no input found in the input dictionary to allow additional logic to find the value
  • OnTokenFound:

    An event fired by the parser when it finds a token while doing syntax parsing.
  • OnHolderFound:

    An event fired by the parser when it finds a TextHolder.
  • Encoding:

    The default text encoding used
  • MaxErrorCount:

    The maximum number of errors found by parser before it stops parsing.
  • DateFormat:

    The DateTime format used by the parser to parse DateTime values
  • LineBreakOption:

    Options to control line breaks in the text file, such as to ensure the file uses windows(CRLF) mode or Unix(LF)
  • IgnoreUnknownKeyword:

    Whether to throw exception when parser finds an unknown keyword
  • IgnoreUnknownParam:

    Whether to throw exception when parser finds an unknown keyword Parameter
  • AllowNested:

    Whether to Allow nested holders
  • EmptyAsNulls:

    Whether to treat empty string as a valid input, default true to treat empty as no input
  • CategoryOptional:

    Whether to make the category property optional of a TextHolder
  • ContinueOnError:

    Set to true if this parse is only for checking syntax of the template
  • CacheCalculatedResults:

    Set to true to allow the parser to cache the result of a TextHolder which contains a keyword which is 'Calculated' into the input dictionary
  • SaveManipulatedResults:

    Set to true to allow the parser to cache the result of a TextHolder which contains a keyword which is 'ManipulateInput' into the input dictionary
  • AllowCachingNullValues:

    Set to true to allow the parser to cache the result(from calculation or 'OnRequireInput' event) of a TextHolder which is null
  • Keywords:

    Contains all the keywords definition, modify this dictionary to make advanced customizations.
  • Enums:

    The Enum types for the parser to use when hitting TextHolder with Enum keyword
  • Regexes:

    Pre-defined regular expressions (stored with a key of its name) for the parser to use, the parser will try to find a match with param string as name in this dictionary and pull the value otherwise use the param string as the regex
  • XmlFieldElementName:

    The TextHolder Element name when parsing xml format input
  • XmlValueNodeName:

    The TextHolder Value Element name when parsing xml format input
  • XmlNameNodeName:

    The TextHolder Name Element name when parsing xml format input
  • XmlCollectionNodeName:

    The TextHolder Child collection Element name when parsing xml format input
  • KeyHolders:

    The key used by the parser to store pre-parsed Holder definitions when using 2-pass passing, which allows logics inside OnRequireInput event to be able to find unreached TaxHolder's definition
  • CustomKeywordNames:

    List of custom added keyword names to let syntax check task and highlight extension pass the validation
  • AvailableCategories:

    List of category names to enable syntax check task and highlight extension do validation, remove to skip verifying categories
  • CustomOptions:

    Custom option entries to allow other libs to load config from TemplatorConfig file. the example ships is the syntax checking build task configuration

Keywords

  • Collection

    Indicates an Array/Collection/Repeat, corresponding input should be an array : IDictionary<string,object>[], templator will repeat the template starting from this Holder till the matching 'CollectionEnd'(in plain text) or the close tag of the element(in xml).

  • CollectionBegin

    Indicates beginning position of an Array/Repeat/Collection (or beginning xml element in xml), must match with 'CollectionEnd', it functions the same as Collection in plain text format

    Parameters:
    Group
    To control the repeat behavior of repeating a group of XElement, e.g: double '<a/><b/>' -> '<a/><b/><a/><b/>' instead of '<a/><a/><b/><b/>'
  • CollectionEnd

    Indicates then end position (end element in xml) of Array/Collection/Repeat

    Parameters:
    Group
    To control the repeat behavior of repeating a group of XElement, e.g: double '<a/><b/>' with <c/> -> '<a/><b/><a/><b/><c/>' instead of '<a/><b/><c/><a/><b/>'
  • Nested

    If a TextHolder's input value contains Templator syntax, mark the holder with this Keyword to enable the template in the value string to be processed with the same context

  • NestedXml

    Allow a xml Template's input value provided for a TextHolder marked with this keyword to be processed

  • Inherited

    Allow the parser to seek upper level of the input when current context is inside a child array/repeat/collection loop

    Parameters:
    Number value
    Indicates the number of levels that allowed to seek upwards
  • MathMax

    Aggregate the max value of given Holder names

    Parameters:
    HolderNames separated by ';', or hierarchy separated by '.'
    Something like: 'Holder1;Holder2;Collection.ChildName'
  • MathMin

    Aggregate the min value of given Holder names

    Parameters:
    HolderNames separated by ';', or hierarchy separated by '.'
    Something like: 'Holder1;Holder2;Collection.ChildName'
  • Sum

    Aggregate the sum value of given Holder names

    Parameters:
    HolderNames separated by ';', or hierarchy separated by '.'
    Something like: 'Holder1;Holder2;Collection.ChildName'
  • Avg

    Aggregate the average value of given Holder names

    Parameters:
    HolderNames separated by ';', or hierarchy separated by '.'
    Something like: 'Holder1;Holder2;Collection.ChildName'
  • Count

    Aggregate the count of given Holder which is an Array/Repeat/Collection

    Parameters:
    HolderNames separated by ';', or hierarchy separated by '.'
    Something like: 'CollectionName1;CollectionName2.ChildCollectionName'
  • Multi

    Aggregate the multiplied value of given Holder names

    Parameters:
    HolderNames separated by ';', or hierarchy separated by '.'
    Something like: 'Holder1;Holder2;Collection.ChildName'
  • Refer

    Retrieve another 'referred' TextHolder's value as the value

    Parameters:
    The referred Holder's Name
  • Even

    Specify the method of rounding a decimal as 'Even', only works with keyword 'Number'

  • AwayZero

    Specify the method of rounding a decimal as 'AwayFromZero', only works with keyword 'Number'

  • Default

    Provide a default INPUT value of the TextHolder if no value found from input

    Parameters:
    The default value, none as String.Empty
  • Optional

    Provide a default OUTPUT value of the TextHolder if no value found from input

    Parameters:
    The default value, none as String.Empty
  • RegExp

    Validate the input with specified regular expression, this keyword will try to find a preset regex in config using the given string as key. if not found will use the given string as the expression

    Parameters:
    The name/key of the expressions in config object, or the regular expression string
  • Length

    Validate input strings' length, or fix the output length if current TextHolder indicates an Array/Repeat/Collection

    Parameters:
    The valid length values
    E.g.: '3', '1;3;5', '1-7'
  • Min

    Validate the min value of the value when it is a Number

    Parameters:
    The numeric value
  • Max

    Validate the max value of the value when it is a Number

    Parameters:
    The numeric value
  • Bool

    Indicates the value is functioning as 'Bit', referred by 'If', has value means 'true', null indicates 'false'

  • Enum

    Indicates the value of this holder is an Enum listed in config object.Enums, with the Enum name as key

    Parameters:
    The Enum type name as key in the config object
  • Number

    Indicates and validate that the input value is a Number

    Parameters:
    None or the output format of the number
    E.g.: Number(0.00) with value 0.1 -> 0.10
  • DateTime

    Indicates and validate that the input value is a DateTime, parsing with the 'DateFormat' in config

    Parameters:
    None or the format of the output of the DateTime value
    E.g.: DateTime(yyyy) with value 07/07/2015 -> 2015
  • Format

    Use String.Format to put the value into param string's '{0}' position

    Parameters:
    The string pattern
    E.g.: 'hello {0}' with value 'world' -> 'hello world'
  • Map

    Map/replace output with the pair provided in the param to transform input

    Parameters:
    Pairs(separated by ';') of values(separated by ':') to map with input value
    E.g.: a:1;b:2 with value a -> 1 and b -> 2
  • Replace

    Replace specific string with another value in the output

    Parameters:
    Pair of values(separated by ';')
    E.g.: a;1 with value abc -> 1bc
  • Transform

    Transform the output based on parameter options

    Parameters:
    Lower/Upper
    Support only to upper or to lower for now
  • Upper

    Transform the output string to upper case

  • Lower

    Transform the output string to lower case

  • Trim

    Trim the output string

    Parameters:
    'Begin'/'End' or none
    Trim Begin or End or no param for both
  • Csv

    Transform the output string to encode for used as a csv cell

  • Base32

    Transform the output string to encode with base32

  • Base64

    Transform the output string to encode with base64

  • Url

    Transform the output string to encode with url encode

  • Html

    Transform the output string to encode with html encode

  • Encode

    Transform the output string to encode with the options in Parameter

    Parameters:
    The encode method
    Base32/Base64/Html/Csv/Url
  • Decode

    Decode the output string with the options in Parameter

    Parameters:
    The decode method
    Base32/Base64/Html/Csv/Url
  • RemoveChar

    Remove a specific character from the output

    Parameters:
    The char to remove
    E.g.: RemoveChar(.) with input 1.00 -> 100
  • FixedLength

    Ensure the output length is fixed by the number specified in Param, truncate if too long or fill with the Char provides by keyword 'Fill', default is white space

    Parameters:
    Length needed
    E.g.: FixedLength(3) with input 'a' -> 'a '
  • Select

    Perform a logic '?:' operator

    Parameters:
    3 Params delimited by ';', 3rd one optional. leave blank means using the field name itself as condition.
    if the condition is true (condition accepts '!' operator), output 1st param, else output the 2nd one
  • Join

    Apply logic as String.Join to an collection/array, e.g. insert specific string before each item except the first one

  • Wrap

    Wrap the collection with begin/end tags if the collection (itself or another field name if supplied in the third parameter) is not empty, condition accepts '!' operator

    Parameters:
    If specified at a non-collection item : The begin tag + ';' + end tag + ';' + optional conditional holder name
    E.g.: Wrap([) or Wrap([;]) or Wrap(;]) or Wrap([;];AnotherHolder)
    The begin tag at collectionBegin or the end tag at the collectionEnd
    E.g.: Collection,Wrap([) or CollectionEnd,Wrap(])
    Optional field Name used to determine if to wrap instead of the collection itself
    E.g.: Collection,Wrap([;AnotherHolder) or CollectionEnd,Wrap(];AnotherHolder)
  • Holder

    Indicates this TextHolder only required input but will not output anything

  • Ifnot

    If the given value is null or not provided, remove the xml element based on the xpath specified in param, default removing current element

    Parameters:
    An xpath based on current element
  • EnumElement

    Validate the input with the enum and put the enum value as the name of current xml element

    Parameters:
    The Enum type name in the config object
  • AsXml

    Output the value of this field as an xml Element into the xml template, only working in xml template

  • ElementName

    Use the value as current xml element name instead of value

  • AttributeIf

    Only keep current xml attribute when value is provided and is not null, the value used is from another TextHolder specified in the param or the current Holder's value if no param specified

    Parameters:
    No Params or another TextHolder's name
    Condition accepts '!' operator
  • AttributeName

    Use the value as current attribute's name instead of value

  • If

    Only keep current xml attribute when value is provided and is not null, the value used is from another TextHolder specified in the param or the current Holder's value if no param specified

    Parameters:
    No Params or another TextHolder's name
    condition accepts '!' operator
  • Tips

    Put a comment of the TextHolder in the parsed result holder list

    Parameters:
    The comment string
  • DisplayName

    A display name for the TextHolder

    Parameters:
    The display name string
  • Truncate

    If a value string's length is longer than the max value of keyword 'Length' and this keyword exists, the string will be truncated to that length without producing an error

  • Fill

    Specifies a character used to append to the output if keyword 'FixedLength' is specified and the length is less than the fixed-length.

    Parameters:
    The char used to fill
  • Prepend

    Specifies a character used to fill the output if keyword 'FixedLength' is specified and the length is less than the fixed-length, this will pre-fill the string instead of append

    Parameters:
    The char used to fill
  • AlignCount

    If multiple arrays/repeat/collections are provided in the input and this option exists, the output will make sure every array/repeat/collection's length is the same as the max length of the input, the empty part will be filled with null values without producing errors

    Parameters:
    The holder name of the parent array/repeat/collection