Class THtmlTemplateParser

DescriptionHierarchyFieldsMethodsProperties

Unit

Declaration

type THtmlTemplateParser = class(TObject)

Description

This is the template processor class which can apply a template to one or more html documents.

You can use it by calling the methods parseTemplate and parseHTML. parseTemplate loads a certain template and parseHTML matches the template to a html/xml file.
A template file is just like a html file with special commands. The parser than matches every text and tag of the template to text/tag in the html file, while ignoring every additional data in latter file. If no match is possible an exception is raised.
The template can extract certain values from the html file into variables, and you can access these variables with the property variables and variableChangeLog. Former only contains the final value of the variables, latter records every assignment during the matching of the template.

Getting started

Creating a template to analyze a xml-file/webpage:

  1. First, you should remove all things from the webpage that are uninteresting, dynamically generated or invalid xml (or alternatively start with an empty file as template).

  2. Then, you should replace all parts that you want to extract with <t:s>yourVariableName:=text()</t:s>.
    This will write the value of the text node that contains the t:s tag in the variable yourVariableName.

    Instead of the t:s tag, you can also use the short notation {yourVariableName:=text()}; and instead of text() to read the text node, you can also use @attrib to read an attribute; or an arbitrary complex xpath/xquery-expression

  3. Then the template is finished, at least the trivial things

If you want to read several elements like table rows, you need to surround the matching tags with template:loop, e.g. <template:loop><tr>..</tr></template:loop> and the things between the loop-tags is repeated as long as possible. You can also use the short notation by adding a star like <tr>..</tr>* .

Using the templates from Pascal:

  1. First, create a new THtmlTemplateParser: parser := THtmlTemplateParser.create()

  2. Load the template with parser.parseTemplate('..template..') or parser.parseTemplateFile('template-file')

  3. Process the webpage with parser.parseHTML('..html..') or parser.parseHTMLFile('html-file')

  4. Read the result of variable yourVariableName through parser.variables.values['yourVariableName']

If you used loops, only the last value of the variable is available in the variables property, the previous values can be enumerated through variableChangelog.

Template examples

Example, how to read first <b>-tag:

Html-File: <b>Hello World!</b>
Template: <b>{.}</b>

This will set the default variable _result to "Hello World!"

Example, how to read the first <b>-tag in a explicit named variable:

Html-File: <b>Hello World!</b>
Template: <b>{$test}</b>

This will set the variable test to "Hello World!".
Some alternative forms are <b>{$test := .}</b>, <b><t:s>test := .</t:s></b>, <b><template:s>test := text()</template:s></b> or <b><t:read var="test" source="text()"></b>.

Example, how to read all <b>-tags:

Html-File: <b>Hello </b><b>World!</b>
Template: <b>{.}</b>*

This will change the value of the variable _result twice, to "Hello " and "World!". Both values are available in the variable changelog.
Some alternative forms are: <t:loop><b>{.}</b></t:loop>, <template:loop><b>{.}</b></template:loop>, <template:loop><b>{_result := text()}</b></template:loop>, ...

Example, how to read the first field of every row of a table:

Html-File: <table> <tr> <td> row-cell 1 </td> </tr> <tr> <td> row-cell 2 </td> </tr> ... <tr> <td> row-cell n </td> </tr> </table>
Template: <table> <template:loop> <tr> <td> {$field} </td> </tr> </template:loop> </table>

This will read row after row, and will write each first field to the change log of the variable field.

Example, how to read several fields of every row of a table:

Html-File: <table> <tr> <td> a </td> <td> b </td> <td> c </td> </tr> ... </tr> </table>
Template: <table> <template:loop> <tr> <td> {$field1} </td> <td> {$field2} </td> <td> {$field3} </td> ... </tr> </template:loop> </table>

This will read $field1=a, $field2=b, $field3=c...
If you now want to process multiple pages which have a similar, but slightly different table/data layount, you can create a template for each of them, and the Pascal side of the application is independent of the source pages. Then it is even possible for the user of the application to add new pages.

Example, how to read all elements between two elements:

Html-File:

  <h1>Start</h1>
    <b>Text 1</b>
    <b>Text 2</b>
  <h1>End</h1>


Template:

  <h1>Start</h1>
    <b>{.}</b>*
  <h1>End</h1>


This will read all b elements between the two headers.

Example, how to read the first list item starting with an unary prime number:

Html-File: ... <li>1111: this is 4</li><li>1:1 is no prime</li><li>1111111: here is 7</li><li>11111111: 8</li> ...
Template: <li template:condition="filter(text(), '1*:') != filter(text(), 'ˆ1?:|ˆ(11+?)\1+:')">{$prime}</li>

This will return "1111111: here is 7", because 1111111 is the first prime in that list.

See the unit tests in tests/extendedhtmlparser_tests.pas for more examples.

Why not XPath/CSS-Selectors?

You might wonder, why you should use templates, if you already know XPath or CSS Selectors.

The answer is that, although XPath/CSS works fine for single values, it is not powerful enough to read multiple values or data from multiple sources, because:

  • XPath/CSS expressions are not able to return multiple values.

    Each expression can only return a single node set, so if you need to read m different values from n different pages, you need O(m * n) expressions, while you only need O(n) templates.
    For example, if you need to read a table listing objects and 2 values for each of them, like in this table:
    <table><tr><td>name</td><td>value 1</td><td>value 2</td></tr></table>
    you can use this template:
    <table><tr><td>{$name}</td><td>{$value1}</td><td>{$value2}</td></tr>*</table>
    and get three arrays with the needed values.
    With XPath you would need three expressions:
    names := ... //table/tr/td[1] ...;
    values1 := ... //table/tr/td[2] ...;
    values2 := ... //table/tr/td[3] ...;

    Or CSS:
    names := ... table tr td:nth-child(1) ...;
    values1 := ... table tr td:nth-child(2) ...;
    values2 := ... table tr td:nth-child(3) ...;

  • XPath is not suited to process html.

    XPath was made to process xml not html, so there are some important functions missing.
    One of the most common actions of web scraping is to select (e.g. div) elements based on their classes. Novices think this can be written as //div[@class = "foobar"], but this is wrong, because the class attribute can list multiple classes. And the correct XPath expression //div[contains(concat(" ", @class, " "), " foobar ")] is very ugly.
    Templates know the semantic meaning of attributes, so you can just use <div class="foobar"></div>.
    Normal XPath is also case-sensitive, while html is case-insensitive, so if the expression works at all, depends on the parser changing the case of all tags.

    You might see this as a reason to use CSS selectors, but:

  • CSS Selectors are not able to process the data

    CSS only selects the elements and cannot change their values.
    E.g. if you need to parse numbers from two pages, one of them using the Amercian format 123,456.00 and the other one the European format 123.456,00, you cannot use CSS selectors to parse them both without changing something in the host language.
    With templates you can use {.} and {translate(., ".,", ",.")} and are done.

  • Templates can be written much faster.

    Because you do not need to write them at all and instead just copy them from the input page.
    E.g. in the example above to create a template for the webpage <table><tr><td>name</td><td>value 1</td><td>value 2</td></tr></table> you just need to insert some {}* and get the complete template <table><tr><td>{$name}</td><td>{$value1}</td><td>{$value2}</td></tr>*</table>.
    To get the XPath-expressions /table/tr/td[1,2,3] you actually need to look at the structure of the page.

    Of course the table example is trivial, only on more complex examples you can see how powerful the templates actually are:

    Let us assume the data is not nicely packed in a table, but contained in a formatted text, like:

    <b>name a</b>: value-a1, value-a2<br>
    <b>name b</b>: value-b1, value-b2<br> ...

    The template is a little bit more complex, since you need to split the values:

    <t:loop><b>{$name}</b>: <t:s>value1 := extract(text(), ":(.+),", 1), value2 := extract(text(), ":(.+),(.+)", 2)</t:s><br/></t:loop>


    However, if you want to solve this task with XPath 1.0 or CSS, you will discover that it is impossible. CSS can not select the text nodes at all, and XPath 1 cannot split them.
    The best you can manage is to select the values with XPath and then split them in the host language, but then you cannot parse multiple different sources by swapping the expressions.
    And although XPath 2 or 3 can split the values, it becomes rather ugly:

    names := //b,
    values1 := //b/substring-after(following-sibling::text()[1], ":")
    values2 := //b/substring-after(following-sibling::text()[1], ",")

    Another example is if you just need the data from a part of the page, e.g. between two headers like here.

      not needed
      ...
      <h1>Header 1</h1>
    
        <b>name a</b>: value-a1, value-a2<br>
        <b>name b</b>: value-b1, value-b2<br>
    
      <h1>Header 2</h1>
      ...
      not needed
    

    The template change is trivial, you just add both headers to the template:

    <h1>Header 1</h1>
    <t:loop><b>{$name}</b>: <t:s>value1 := extract(text(), ":(.+),", 1), value2 := extract(text(), ":(.+),(.+)", 2)</t:s><br></t:loop>
    <h1>Header 2</h1>

    How to do it in XPath? (in XPath 2, it is of course still impossible with XPath 1)

    Well, it gets just crazy:

    names := //h1[. = "Header 1"]/following-sibling::b[following-sibling::h1[1] = "Header 2"],
    values1 := //h1[. = "Header 1"]/following-sibling::b[following-sibling::h1[1] = "Header 2"]/substring-after(following-sibling::text()[1], ":")
    values2 := //h1[. = "Header 1"]/following-sibling::b[following-sibling::h1[1] = "Header 2"]/substring-after(following-sibling::text()[1], ",")

  • Multiple XPath/CSS expressions are not adaptable to changes

    If the page layout changes, you need to rewrite all the expressions. With templates, you just need to apply the local change.

    E.g. if you want to get multiple data from the last div on this page:

    <div id="foobar">
       ...
       <div class="abc">...</div>
       <div>
         <b> .. data 1 .. </b>
         <i> .. data 2 .. </i>
       </div>
    </div>
    

    The template would be

    <div id="foobar">
       <div class="abc"/>
       <div>
         <b>{$data1}</b>
         <i>{$data2}</i>
       </div>
    </div>
                 

    If you do it with XPath, you have two expressions:

    data1 := ... //div[@id="foobar"]/div[@class = "abc"]/following-sibling::div/b ...
    data2 := ... //div[@id="foobar"]/div[@class = "abc"]/following-sibling::div/i ...

    Now, if the page layout is changed to e.g.

    <div id="foobar">
       ...
       <div class="def">...</div>
       <div>
         ...
       </div>
    </div>
    

    You get a diff

    - <div class="abc">...</div>
    + <div class="abc">...</div>

    Which can basically be applied directly to the template and leads to:

    <div id="foobar"> <div class="def"/> <div> <b>{$data1}</b> <i>{$data2}</i> </div> </div>

    But using XPath expressions, you need to change multiple expressions and you have to look at each expression to find the correct div class to change:

    data1 := ... //div[@id="foobar"]/div[@class = "def"]/following-sibling::div/b ...
    data2 := ... //div[@id="foobar"]/div[@class = "def"]/following-sibling::div/i ...
    .

  • XPath/CSS cannot handle errors

    XPath/CSS do not provide any information in case the query fails.

    E.g. if you use //table[@id="foobar"]/tr to get all rows of a table, and it returns 0 rows, you do not know, if the table was actually empty, or if the page layout changed and the table does not exist anymore, or if you use a new html parser, which inserts (correctly) a tbody element between the table and tr.

    But if you use a template <table id="foobar"><tr>{.}*</tr></table> and it returns anything, it is guaranteed that the table exists, since it raises an exception in case it is missing.

  • Metapher: XPath/CSS are like string functions, templates are like regular expressions

    If you write XPath/CSS expressions you give an explicit list of instructions, i.e. you write /foo to get all foo-children, you write [bar] to filter all elements that have a bar child, you write .. to get the parent, you write [position() <= 10] to take the first ten elements...

    This is exactly the same concept, as if you write e.g. copy(s, pos(s, 'foo'), 10) to find the 'foo' substring and then take the next 10 characters.

    But you would never do that nowadays, if you can use a regular expression like 'foo(.{1})'.

    Such a regular expression now implicitely selects the characters after foo, just like a template <foo/>{text()} selects the text after a foo-element.

That said, it is obviously also possible to use XPath or CSS with the templates:

<html>{//your/xpath/expression}</html> or <html>{css("your.css#expression")}</html>

In fact there exists no other modern XPath/CSS interpreter for FreePascal.

Template reference

Basically the template file is a html file, and the parser tries to match the structure of the template html file to the html file.
A tag of the html file is considered as equal to a tag of the template file, if the tag names are equal, all attributes are the same (regardless of their order) and every child node of the tag in the template is also equal to a child node of the tag in the html file (in the same order and nesting).
Text nodes are considered as equal, if the text in the html file starts with the whitespace trimmed text of the template file. All comparisons are performed case insensitive.
The matching occurs with backtracking, so it will always find the first and longest match.

The following template commands can be used:

  • <template:read var="??" source="??" [regex="??" [submatch="??"]]/>
    The XPath-expression in source is evaluated and stored in variable of var.
    If a regex is given, only the matching part is saved. If submatch is given, only the submatch-th match of the regex is returned. (e.g. b will be the 2nd match of "(a)(b)(c)") (However, you should use the xq-function extract instead of the regex/submatch attributes, because former is more elegant)

  • <template:s>var:=source</template:s>
    Short form of template:read. The expression in source is evaluated and assigned to the variable s.
    You can also set several variables like a:=1,b:=2,c:=3 (Remark: The := is actually part of the expression syntax, so you can use much more complex expressions.)

  • <template:if test="??"/> .. </template:if>
    Everything inside this tag is only used iff the XPath-expression in test equals to true

  • <template:else [test="??"]/> .. </template:else>
    Everything inside this tag is only used iff the immediate previous if/else block was not executed.
    You can chain several else blocks that have test attributes together after an starting if, to create an ifelse chain, in which only one if or else block is used.
    E.g.: <template:if test="$condition">..</template:if><template:else test="$condition2">..</template:else><template:else>..</template:else>

  • <template:loop [min="?"] [max="?"]> .. </template:loop>
    Everything inside this tag is repeated between [min,max] times. (default min=0, max=infinity)
    E.g. if you write <template:loop> X </template:loop> , it has the same effect as XXXXX with the largest possible count of X <= max for a given html file.
    If min=0 and there is no possible match for the loop interior the loop is completely ignored.
    If there are more possible matches than max, they are ignored.

  • <template:switch [value="??"]> ... </template:switch> This command can be used to match only one of several possibilities. It has two different forms:

    1. Case 1: All direct child elements are template commands:
      Then the switch statement will choose the first child command, whose attribute test evaluates to true.
      Additionally, if one of the child elements has an attributes value, the expressions of the switch and the child value attribute are evaluated, and the command is only choosen, if both expressions are equal.
      An element that has neither a value nor a test attribute is always choosen (if no element before it is choosen).
      If no child can be choosen at the current position in the html file, the complete switch statement will skipped.

    2. Case 2: All direct child elements are normal html tags:

      This tag is matched to an html tag, iff one of its direct children can be matched to that html tag.
      For example <template:switch><a>..</a> <b>..</b></template:switch> will match either <a>..</a> or <b>..</b>, but not both. If there is an <a> and a <b> tag in the html file, only the first one will be matched (if there is no loop around the switch tag). These switch-constructs are mainly used within a loop to collect the values of different tags, or to combine to different templates.
      If no child can be matched at the current position in the html file, the matching will be tried again at the next position (different to case 1).

  • <template:switch prioritized="true"> ... </template:switch> Another version of a case 2 switch statement that only may contain normal html tags.
    The switch-prioritized prefers earlier child element to later child elements, while the normal switch match alls child elements equally. So a normal switch containing <a> and <b>, will match <a> or <b>, whichever appears first in the html file. The switch-prioritized contrastingly would match <a>, if there is any <a>, and <b> only iff there is no <a> in the html file.
    Therefore <template:switch-prioritized [value="??"]> <a>..</a> <b>..</b> .. </template:switch-prioritized> is identical to <a template:optional="true">..<t:s>found:=true()</t:s></a> <b template:optional="true" template:test="not($found)">..<t:s>found:=true()</t:s></b> ....
    (this used to be called <template:switch-prioritized>, which is still supported, but will be removed in future versions)

  • <template:match-text [matches=".."] [starts-with=".."] [ends-with=".."] [contains=".."] [eq=".."] [case-sensitive=".."] [list-contains=".."]/>
    Matches a text node and is more versatile than just including the text in the template.
    matches matches an arbitrary regular expression against the text node.
    starts-with/ends-with/contains/eq check the text verbatim against the text node, in the obvious way.
    list-contains treats the text of the node as a comma separated list and tests if that list contains the attribute value .
    case-sensitive enables case-sensitive comparisons.
    (older versions used regex/is instead matches/eq, which is now deprecated and will be removed in future versions)

  • <template:meta [text-matching="??"] [case-sensitive="??"] [attribute-text-matching="??"] [attribute-case-sensitive="??"]/>
    Specifies meta information to change the template semantic:
    text-matching: specifies how text node in the template are matched against html text nodes. You can set it to the allowed attributes of match-text. (default is "starts-with")
    text-case-sensitive: specifies if text nodes are matched case sensitive.
    attribute-matching: like text-matching for the values of attribute nodes (note that is currently affecting all attributes in the template. future versions will only change it for following elements)
    attribute-case-sensitive: like text-case-sensitive for the values of attribute nodes (note that is currently affecting all attributes in the template. future versions will only change it for following elements)

  • <template:meta-attribute [name="??"] [text-matching="??"] [case-sensitive="??"]
    Like meta for all attributes with a certain name.


These template attributes can be used on any template element:

  • template:test="xpath condition"
    The element (and its children) is ignored if the condition does not evaluate to true (so <template:tag test="{condition}">..</template:tag> is a short hand for <template:if test="{condition}"><template:tag>..</template:tag></template:if>).

  • template:ignore-self-test="xpath condition"
    The element (and NOT its children) is ignored if the condition does not evaluate to true.


On html/matching tags also these matching modifying attributes can be used:

  • template:optional="true"
    if this is set the file is read successesfully even if the tag doesn't exist.
    You should never have an optional element as direct children of a loop, because the loop has lower priority as the optional element, so the parser will skip loop iterations if it can find a later match for the optional element. But it is fine to use optional tags that have an non-optional parent tag within the loop.

  • template:condition="xpath"
    if this is given, a tag is only accepted as matching, iff the given xpath-expression returns true (powerful, but slow)
    (condition is not the same as test: if test evaluates to false, the template tag is ignored; if condition evaluates to false, the html tag is not found)

The default prefixes for template commands are "template:" and "t:", you can change that with the templateNamespace-property or by defining a new namespace in the template like xmlns:yournamespace="http://www.benibela.de/2011/templateparser" . (only the xmlns:prefix form is supported, not xmlns without prefix)

Short notation

Commonly used commands can be abbreviated as textual symbols instead of xml tags. To avoid conflicts with text node matching, this short notation is only allowed at the beginning of template text nodes.

The short read tag <t:s>foo:=..</t:s> to read something in variable foo can be abbreviated as {foo:=..}. Similarly {} can be written within attributes to read the attribute, e.g. <a href="{$dest := .}"/>.
Also the trailing := . can be omitted, if only one variable assignment occurs, e.g. as {$foo} is equivalent to foo := . and $foo := ..

Optional and repeated elements can be marked with ?, *, +, {min, max}; like <a>?...</a> or, equivalent, <a>..</a>?.
An element marked with ? becomes optional, which has the same effect as adding the template:optional="true" attribute.
An element marked with * can be repeated any times, which has the same effect as surrounding it with a template:loop element.
An element marked with + has to be repeated at least once, which has the same effect as surrounding it with a template:loop element with attribute min=1.
An element marked with {min,max} has to be repeated at least min-times and at most max-times (just like in a t:loop) (remember that additional data/elements are always ignored).
An element marked with {count} has to be repeated exactly count-times (just like in a t:loop) (remember that additional data/elements are always ignored).

Breaking changes from previous versions:

  • As was announced in planned changes, the meaning of {$x} and {6} was changed

  • As was announced in planned changes, the meaning of <x value="{$x}"/> was changed

  • Adding the short notation breaks all templates that match text nodes starting with *, +, ? or {

  • The default template prefix was changed to template: (from htmlparser:). You can add the old prefix to the templateNamespace-property, if you want to continue to use it

  • All changes mentioned in pseudoxpath.

  • Also text() doesn't match the next text element anymore, but the next text element of the current node. Use .//text() for the old behaviour

  • All variable names in the pxp are now case-sensitive in the default mode. You can set variableChangeLog.caseSensitive to change it to the old behaviour (however, variables defined with in the expression by for/some/every (but not by := ) remain case sensitive)

  • There was always some confusion, if the old variable changelog should be deleted or merged with the new one, if you process several html documents. Therefore the old merging option was removed and replaced by the KeepPreviousVariables property.

Planned breaking changes:

  • Avoid unmatched parenthesis and pipes within text nodes:
    Currently is no short notation to read alternatives with the template:switch command, like <template:switch><a>..</a><b>..</b><c>..</c></template:switch>.
    In future this might be the same as (<a>..</a>|<b>..</b>|<c>..</c>).

Hierarchy

  • TObject
  • THtmlTemplateParser

Overview

Methods

Public procedure parseHTMLSimple(html, uri, contenttype: string);
Public function matchLastTrees: Boolean;
Public constructor create;
Public destructor destroy; override;
Public procedure parseTemplate(template: string; templateName: string = '<unknown>');
Public procedure parseTemplateFile(templatefilename: string);
Public function parseHTML(html: string; htmlFileName: string = ''; contentType: string = ''):boolean;
Public function parseHTMLFile(htmlfilename: string):boolean;
Public function replaceVarsOld(s:string;customReplace: TReplaceFunction=nil):string; deprecated;
Public function replaceEnclosedExpressions(str:string):string;
Public function debugMatchings(const width: integer): string;
Public function debugMatchings(const width: integer; includeText: boolean; includeAttributes: array of string): string;
Public function parseQuery(const expression: string): IXQuery;

Properties

Public property variables: TXQVariableChangeLog read GetVariables;
Public property variableChangeLog: TXQVariableChangeLog read FVariableLog;
Public property oldVariableChangeLog: TXQVariableChangeLog read FOldVariableLog;
Public property VariableChangeLogCondensed: TXQVariableChangeLog read GetVariableLogCondensed;
Public property templateNamespaces: TNamespaceList read GetTemplateNamespace;
Public property ParsingExceptions: boolean read FParsingExceptions write FParsingExceptions;
Public property OutputEncoding: TEncoding read FOutputEncoding write FOutputEncoding;
Public property KeepPreviousVariables: TKeepPreviousVariables read FKeepOldVariables write FKeepOldVariables;
Public property trimTextNodes: TTrimTextNodes read FTrimTextNodes write FTrimTextNodes;
Public property UnnamedVariableName: string read FUnnamedVariableName write FUnnamedVariableName;
Public property AllowVeryShortNotation: boolean read FVeryShortNotation write FVeryShortNotation;
Public property SingleQueryModule: boolean read FSingleQueryModule write FSingleQueryModule;
Public property hasRealVariableDefinitions: boolean read GetTemplateHasRealVariableDefinitions;
Public property TemplateTree: TTreeNode read getTemplateTree;
Public property HTMLTree: TTreeNode read getHTMLTree;
Public property TemplateParser: TTreeParser read FTemplate;
Public property HTMLParser: TTreeParser read FHTML;
Public property QueryEngine: TXQueryEngine read FQueryEngine;
Public property QueryContext: TXQEvaluationContext read FQueryContext;

Description

Methods

Public procedure parseHTMLSimple(html, uri, contenttype: string);

Parses a HTML file without performing matching. For internal use,

Public function matchLastTrees: Boolean;
 
Public constructor create;
 
Public destructor destroy; override;
 
Public procedure parseTemplate(template: string; templateName: string = '<unknown>');

loads the given template, stores templateName for debugging issues

Public procedure parseTemplateFile(templatefilename: string);

loads a template from a file

Public function parseHTML(html: string; htmlFileName: string = ''; contentType: string = ''):boolean;

parses the given data by applying a previously loaded template. htmlFileName is just for debugging issues

Public function parseHTMLFile(htmlfilename: string):boolean;

parses the given file by applying a previously loaded template.

Public function replaceVarsOld(s:string;customReplace: TReplaceFunction=nil):string; deprecated;

Warning: this symbol is deprecated.

This replaces every $variable; in s with variables.values['variable'] or the value returned by customReplace (should not be used anymore)

Public function replaceEnclosedExpressions(str:string):string;

This treats str as extended string and evaluates the pxquery expression x"str"

Public function debugMatchings(const width: integer): string;
 
Public function debugMatchings(const width: integer; includeText: boolean; includeAttributes: array of string): string;
 
Public function parseQuery(const expression: string): IXQuery;

Returns a IXQuery that accesses the variable storage of the template engine. Mostly intended for internal use, but you might find it useful to evaluate external XPath expressions which are not part of the template

Properties

Public property variables: TXQVariableChangeLog read GetVariables;

List of all variables (variableChangeLog is usually faster)

Public property variableChangeLog: TXQVariableChangeLog read FVariableLog;

All assignments to a variables during the matching of the template. You can use TStrings.GetNameValue to get the variable/value in a certain line

Public property oldVariableChangeLog: TXQVariableChangeLog read FOldVariableLog;

All assignments to a variable during the matching of previous templates. (see TKeepPreviousVariables)

Public property VariableChangeLogCondensed: TXQVariableChangeLog read GetVariableLogCondensed;

VariableChangeLog with duplicated objects removed (i.e. if you have obj := object(), obj.a := 1, obj.b := 2, obj := object(); the normal change log will contain 4 objects (like {}, {a:1}, {a:1,b:2}, {}), but the condensed log only two {a:1,b:2}, {})

Public property templateNamespaces: TNamespaceList read GetTemplateNamespace;

Global namespaces to set the commands that will be recognized as template commands. Default prefixes are template: and t:
Namespaces can also be defined in a template with the xmlns: notation and the namespace url 'http://www.benibela.de/2011/templateparser'

Public property ParsingExceptions: boolean read FParsingExceptions write FParsingExceptions;

If this is true (default) it will raise an exception if the matching fails.

Public property OutputEncoding: TEncoding read FOutputEncoding write FOutputEncoding;

Output encoding, i.e. the encoding of the read variables. Html document and template are automatically converted to it

Public property KeepPreviousVariables: TKeepPreviousVariables read FKeepOldVariables write FKeepOldVariables;

Controls if old variables are deleted when processing a new document (see TKeepPreviousVariables)

Public property trimTextNodes: TTrimTextNodes read FTrimTextNodes write FTrimTextNodes;

How to trim text nodes (default ttnAfterReading). There is also pseudoxpath.XQGlobalTrimNodes which controls, how the values are returned.

Public property UnnamedVariableName: string read FUnnamedVariableName write FUnnamedVariableName;

Default variable name. If a something is read from the document, but not assigned to a variable, it is assigned to this one. (Default: _result)

Public property AllowVeryShortNotation: boolean read FVeryShortNotation write FVeryShortNotation;

Enables the the very short notation (e.g. {a:=text()}, <a>*) (default: true)

Public property SingleQueryModule: boolean read FSingleQueryModule write FSingleQueryModule;

If all XPath/XQuery expressions in the templates are kept in the same module. Only if true, XQuery variables/functions declared are accessible in other read commands. (declarations must be preceded by xquery version "1.0"; and followed by an expression, if only ()) Global variables, declared with a simple $x := value, are always everywhere accessible. (default true)

Public property hasRealVariableDefinitions: boolean read GetTemplateHasRealVariableDefinitions;

If the currently loaded template contains := variable definitions (contrary to assign values to the default variable with {.} ) (CAN ONLY BE USED AFTER the template has been applied!)

Public property TemplateTree: TTreeNode read getTemplateTree;

A tree representation of the current template

Public property HTMLTree: TTreeNode read getHTMLTree;

A tree representation of the processed html file

Public property TemplateParser: TTreeParser read FTemplate;

X/HTML parser used to read the templates (public so you can change the parsing behaviour, if you really need it)

Public property HTMLParser: TTreeParser read FHTML;

X/HTML parser used to read the pages (public so you can change the parsing behaviour, if you really need it)

Public property QueryEngine: TXQueryEngine read FQueryEngine;

XQuery engine used for evaluating query expressions contained in the template

Public property QueryContext: TXQEvaluationContext read FQueryContext;

Context used to evaluate XQuery expressions. For internal use.


Generated by PasDoc 0.14.0.