| <!doctype html> |
| <!-- Generated by FreeMarker/Docgen from DocBook --> |
| <html lang="en" class="page-type-section"> |
| <head prefix="og: http://ogp.me/ns#"> |
| <meta charset="utf-8"> |
| <title>Basics - Apache FreeMarker Manual</title> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <meta name="format-detection" content="telephone=no"> |
| <meta property="og:site_name" content="Apache FreeMarker Manual"> |
| <meta property="og:title" content="Basics"> |
| <meta property="og:locale" content="en_US"> |
| <meta property="og:url" content="https://freemarker.apache.org/docs/xgui_imperative_learn.html"> |
| <link rel="canonical" href="https://freemarker.apache.org/docs/xgui_imperative_learn.html"> |
| <link rel="icon" href="favicon.png" type="image/png"> |
| <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:500,700,400,300|Droid+Sans+Mono"> |
| <link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css?1707770044859"> |
| <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/cookie-bar/cookiebar-latest.min.js"></script> |
| </head> |
| <body itemscope itemtype="https://schema.org/Code"> |
| <meta itemprop="url" content="https://freemarker.apache.org/docs/"> |
| <meta itemprop="name" content="Apache FreeMarker Manual"> |
| |
| <!--[if lte IE 9]> |
| <div class="oldBrowserWarning" style="display: block"> |
| Unsupported web browser - Use a modern browser to view this website! |
| </div> |
| <![endif]--> <div class="oldBrowserWarning"> |
| Unsupported web browser - Use a modern browser to view this website! |
| </div> |
| <div class="header-top-bg"><div class="site-width header-top"><div id="hamburger-menu" role="button"></div> <div class="logo"> |
| <a href="https://freemarker.apache.org" role="banner"><img itemprop="image" src="logo.png" alt="FreeMarker"></a> </div> |
| <ul class="tabs"><li><a href="https://freemarker.apache.org/">Home</a></li><li class="current"><a href="index.html">Manual</a></li><li><a class="external" href="api/index.html">Java API</a></li></ul><ul class="secondary-tabs"><li><a class="tab icon-heart" href="https://freemarker.apache.org/contribute.html" title="Contribute"><span>Contribute</span></a></li><li><a class="tab icon-bug" href="https://issues.apache.org/jira/projects/FREEMARKER" title="Report a Bug"><span>Report a Bug</span></a></li><li><a class="tab icon-download" href="https://freemarker.apache.org/freemarkerdownload.html" title="Download"><span>Download</span></a></li></ul></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="index.html" class="navigation-header">Manual</a><div class="navigation-header"></div><form method="get" class="search-form" action="search-results.html"><fieldset><legend class="sr-only">Search form</legend><label for="search-field" class="sr-only">Search query</label><input id="search-field" name="q" type="search" class="search-input" placeholder="Search" spellcheck="false" autocorrect="off" autocomplete="off"><button type="submit" class="search-btn"><span class="sr-only">Search</span></button></fieldset></form></div><div class="site-width breadcrumb-row"> <div class="breadcrumbs"> |
| <ul class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"><li class="step-0" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="index.html"><span itemprop="name">Apache FreeMarker Manual</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="xgui.html"><span itemprop="name">XML Processing Guide</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="xgui_imperative.html"><span itemprop="name">Imperative XML processing</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="xgui_imperative_learn.html"><span itemprop="name">Basics</span></a></li></ul> </div> |
| <div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul><li><a href="alphaidx.html">Alpha. index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions</a></li><li><a href="ref_builtins_alphaidx.html">?builtins</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_specvar.html">.spec_vars</a></li><li><a href="app_faq.html">FAQ</a></li></ul></div></div></div> <div class="main-content site-width"> |
| <div class="content-wrapper"> |
| <div id="table-of-contents-wrapper" class="col-left"> |
| <script>var breadcrumb = ["Apache FreeMarker Manual","XML Processing Guide","Imperative XML processing","Basics"];</script> |
| <script src="toc.js?1707770044859"></script> |
| <script src="docgen-resources/main.min.js?1707770044859"></script> |
| </div> |
| <div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="xgui_imperative.html"><span>Previous</span></a><a class="paging-arrow next" href="xgui_imperative_formal.html"><span>Next</span></a></div><div class="title-wrapper"> |
| <h1 class="content-header header-section1" id="xgui_imperative_learn" itemprop="headline">Basics</h1> |
| </div></div><div class="page-menu"> |
| <div class="page-menu-title">Page Contents</div> |
| <ul><li><a class="page-menu-link" href="#autoid_141" data-menu-target="autoid_141">Accessing elements by name</a></li><li><a class="page-menu-link" href="#autoid_142" data-menu-target="autoid_142">Accessing attributes</a></li><li><a class="page-menu-link" href="#autoid_143" data-menu-target="autoid_143">Exploring the tree</a></li><li><a class="page-menu-link" href="#xgui_imperative_learn_xpath" data-menu-target="xgui_imperative_learn_xpath">Using XPath expressions</a></li><li><a class="page-menu-link" href="#autoid_144" data-menu-target="autoid_144">XML namespaces</a></li><li><a class="page-menu-link" href="#autoid_145" data-menu-target="autoid_145">Don't forget escaping!</a></li></ul> </div> <div class="callout note"> |
| <strong class="callout-label">Note:</strong> |
| |
| <p>This section uses the DOM tree and the variable made in the |
| <a href="xgui_expose.html">previous chapter</a>.</p> |
| </div> |
| <p>Assume that the programmer has put the XML document into the |
| data-model as variable <code class="inline-code">doc</code>. This variable |
| corresponds to the root of the <a href="xgui_expose_dom.html">DOM |
| tree</a>, the "document". The actual variable |
| structure behind <code class="inline-code">doc</code> is wily enough, and only |
| roughly resembles the DOM tree. So instead of getting lost in the |
| details, let's see how to use it by example.</p> |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_141">Accessing elements by name</h2> |
| |
| |
| <p>This FTL prints the title of the book:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><h1>${doc.book.title}</h1></pre> </div> |
| |
| |
| <p>The output will be:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body"><h1>Test Book</h1></pre> </div> |
| |
| |
| <p>As you see, both <code class="inline-code">doc</code> and |
| <code class="inline-code">book</code> can be used as hashes; you get their child |
| nodes as sub variables. Basically, you describe the path by which |
| you reach the target (element <code class="inline-code">title</code>) in the DOM |
| tree. You may notice that there was some swindle above: with |
| <code class="inline-code">${doc.book.title}</code>, it seems that we instruct |
| FreeMarker to print the <code class="inline-code">title</code> element itself, but |
| we should print its child text node (check the <a href="xgui_expose_dom.html">DOM tree</a>). It still works, because |
| elements are not only hash variables, but string variables as well. |
| The scalar value of an element node is the string resulting from the |
| concatenation of all its text child nodes. However, trying to use an |
| element as scalar will cause error if the element has child |
| elements. For example <code class="inline-code">${doc.book}</code> would stop with |
| error.</p> |
| |
| <p>This FTL prints the titles of the two chapters:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><h2>${doc.book.chapter[0].title}</h2> |
| <h2>${doc.book.chapter[1].title}</h2></pre> </div> |
| |
| |
| <p>Here, as <code class="inline-code">book</code> has 2 |
| <code class="inline-code">chapter</code> element children, |
| <code class="inline-code">doc.book.chapter</code> is a sequence that stores the |
| two element nodes. Thus, we can generalize the above FTL, so it |
| works with any number of chapters:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#list doc.book.chapter as ch> |
| <h2>${ch.title}</h2> |
| </#list></pre> </div> |
| |
| |
| <p>But what's if there is only one chapter? Actually, when you |
| access an element as hash subvariable, it is |
| <em>always</em> a sequence as well (not only hash and |
| string), but if the sequence contains exactly 1 item, then the |
| variable also acts as that item itself. So, returning to the first |
| example, this would print the book title as well:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><h1>${doc.book[0].title[0]}</h1></pre> </div> |
| |
| |
| <p>But you know that there is exactly 1 <code class="inline-code">book</code> |
| element, and that a book has exactly 1 title, so you can omit the |
| <code class="inline-code">[0]</code>-s. |
| <code class="inline-code">${doc.book.chapter.title}</code> would work too, if the |
| book happen to have only 1 <code class="inline-code">chapter</code>-s (otherwise |
| it is ambiguous: how is it to know if the <code class="inline-code">title</code> |
| of which <code class="inline-code">chapter</code> you want? So it stops with an |
| error.). But since a book can have multiple chapters, you don't use |
| this form. If the element <code class="inline-code">book</code> has no |
| <code class="inline-code">chapter</code> child, then |
| <code class="inline-code">doc.book.chapter</code> will be a 0 length sequence, so |
| the FTL with <code class="inline-code"><#list ...></code> will still |
| work.</p> |
| |
| <p>It is important to realize the consequence that, for example, |
| if <code class="inline-code">book</code> has no <code class="inline-code">chapter</code>-s then |
| <code class="inline-code">book.chapter</code> is an empty sequence, so |
| <code class="inline-code">doc.book.chapter??</code> will <em>not</em> |
| be <code class="inline-code">false</code>, it will be always |
| <code class="inline-code">true</code>! Similarly, |
| <code class="inline-code">doc.book.somethingTotallyNonsense??</code> will not be |
| <code class="inline-code">false</code> either. To check if there was no children |
| found, use <code class="inline-code">doc.book.chapter[0]??</code> (or |
| <code class="inline-code">doc.book.chapter?size == 0</code>). Of course you can |
| use similarly all the <a href="dgui_template_exp.html#dgui_template_exp_missing">missing value handler |
| operators</a> (e.g. |
| <code class="inline-code">doc.book.author[0]!"Anonymous"</code>), just don't |
| forget that <code class="inline-code">[0]</code>.</p> |
| |
| <div class="callout note"> |
| <strong class="callout-label">Note:</strong> |
| |
| <p>The rule with sequences of size 1 is a convenience feature |
| of the XML wrapper (implemented via multi-type FTL variables). It |
| will not work with other sequences in general.</p> |
| </div> |
| |
| |
| <p>Now we finish the example by printing all the |
| <code class="inline-code">para</code>-s of each chapter:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><h1>${doc.book.title}</h1> |
| <#list doc.book.chapter as ch> |
| <h2>${ch.title}</h2> |
| <#list ch.para as p> |
| <p>${p} |
| </#list> |
| </#list></pre> </div> |
| |
| |
| <p>this will print:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body"><h1>Test</h1> |
| <h2>Ch1</h2> |
| <p>p1.1 |
| <p>p1.2 |
| <p>p1.3 |
| <h2>Ch2</h2> |
| <p>p2.1 |
| <p>p2.2</pre> </div> |
| |
| |
| <p>The above FTL could be written more nicely as:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#assign book = doc.book> |
| <h1>${book.title}</h1> |
| <#list book.chapter as ch> |
| <h2>${ch.title}</h2> |
| <#list ch.para as p> |
| <p>${p} |
| </#list> |
| </#list></pre> </div> |
| |
| |
| <p>Finally, a generalized usage of the child selector mechanism: |
| this template lists all <code class="inline-code">para</code>-s of the example XML |
| document:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#list doc.book.chapter.para as p> |
| <p>${p} |
| </#list></pre> </div> |
| |
| |
| <p>The output will be:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body"> <p>p1.1 |
| <p>p1.2 |
| <p>p1.3 |
| <p>p2.1 |
| <p>p2.2 |
| </pre> </div> |
| |
| |
| <p>This example shows that hash sub variables select the children |
| of a sequence of notes (just in the earlier examples that sequence |
| happened to be of size 1). In this concrete case, subvariable |
| <code class="inline-code">chapter</code> returns a sequence of size 2 (since there |
| are two <code class="inline-code">chapter</code>-s), and then subvariable |
| <code class="inline-code">para</code> selects the <code class="inline-code">para</code> child |
| nodes of all nodes in that sequence.</p> |
| |
| <p>A negative consequence of this mechanism is that things like |
| <code class="inline-code">doc.somethingNonsense.otherNonsesne.totalNonsense</code> |
| will just evaluate to an empty sequence, and you don't get any error |
| messages.</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_142">Accessing attributes</h2> |
| |
| |
| <p>This XML is the same as the original, except that it uses |
| attributes for the titles, instead of elements:</p> |
| |
| |
| |
| <div class="code-block role-unspecified"> |
| <pre class="code-block-body"><!-- THIS XML IS USED FOR THE "Accessing attributes" CHAPTER ONLY! --> |
| <!-- Outside this chapter examples use the XML from earlier. --> |
| |
| <book title="Test"> |
| <chapter title="Ch1"> |
| <para>p1.1</para> |
| <para>p1.2</para> |
| <para>p1.3</para> |
| </chapter> |
| <chapter title="Ch2"> |
| <para>p2.1</para> |
| <para>p2.2</para> |
| </chapter> |
| </book></pre> </div> |
| |
| |
| <p>The attributes of an element can be accessed in the same way |
| as the child elements of the element, except that you put an at-sign |
| (@) before the name of the attribute:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#assign book = doc.book> |
| <h1>${book.@title}</h1> |
| <#list book.chapter as ch> |
| <h2>${ch.@title}</h2> |
| <#list ch.para as p> |
| <p>${p} |
| </#list> |
| </#list></pre> </div> |
| |
| |
| <p>This will print exactly the same as the previous |
| example.</p> |
| |
| <p>Getting attributes follows the same logic as getting child |
| elements, so the result of <code class="inline-code">ch.@title</code> above is a |
| sequence of size 1. If there were no <code class="inline-code">title</code> |
| attribute, then the result would be a sequence of size 0. So be |
| ware, using existence built-ins is tricky here too: if you are |
| curious if <code class="inline-code">foo</code> has attribute |
| <code class="inline-code">bar</code> then you have to write |
| <code class="inline-code">foo.@bar[0]??</code>. (<code class="inline-code">foo.@bar??</code> is |
| wrong, because it always returns <code class="inline-code">true</code>.) |
| Similarly, if you want a default value for the |
| <code class="inline-code">bar</code> attribute, then you have to write |
| <code class="inline-code">foo.@bar[0]!"theDefaultValue"</code>.</p> |
| |
| <p>As with child elements, you can select the attributes of |
| multiple nodes. For example, this template prints the titles of all |
| chapters:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#list doc.book.chapter.@title as t> |
| ${t} |
| </#list></pre> </div> |
| |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_143">Exploring the tree</h2> |
| |
| |
| <p>This FTL will enumerate all child nodes of the book |
| element:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#list doc.book?children as c> |
| - ${c?node_type} <#if c?node_type == 'element'>${c?node_name}</#if> |
| </#list></pre> </div> |
| |
| |
| <p>this will print:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body">- text |
| - element title |
| - text |
| - element chapter |
| - text |
| - element chapter |
| - text</pre> </div> |
| |
| |
| <p>The meaning of <code class="inline-code">?node_type</code> is probably clear |
| without explanation. There are several node types that can occur in |
| a DOM tree, such as <code class="inline-code">"element"</code>, |
| <code class="inline-code">"text"</code>, <code class="inline-code">"comment"</code>, |
| <code class="inline-code">"pi"</code>, ...etc.</p> |
| |
| <p>The <code class="inline-code">?node_name</code> returns the name of element |
| for element nodes. For other node types, it also returns something, |
| but that's mainly useful for declarative XML processing, which will |
| be discussed in a <a href="xgui_declarative.html">later |
| chapter</a>.</p> |
| |
| <p>If the book element had attributes, they would |
| <em>not</em> appear in the above list, for practical |
| reasons. But you can get a list that contains all attributes of the |
| element, with subvariable <code class="inline-code">@@</code> of the element |
| variable. If you modify the first line of the XML to this:</p> |
| |
| |
| |
| <div class="code-block role-unspecified"> |
| <pre class="code-block-body"><book foo="Foo" bar="Bar" baaz="Baaz"></pre> </div> |
| |
| |
| <p>and run this FTL:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#list doc.book.@@ as attr> |
| - ${attr?node_name} = ${attr} |
| </#list></pre> </div> |
| |
| |
| <p>then you get this output (or something similar):</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body">- baaz = Baaz |
| - bar = Bar |
| - foo = Foo</pre> </div> |
| |
| |
| <p>Returning to the listing of children, there is a convenience |
| subvariable to list only the element children of an element:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#list doc.book.* as c> |
| - ${c?node_name} |
| </#list></pre> </div> |
| |
| |
| <p>This will print:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body">- title |
| - chapter |
| - chapter</pre> </div> |
| |
| |
| <p>You get the parent of an element with the |
| <code class="inline-code">parent</code> built-in:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#assign e = doc.book.chapter[0].para[0]> |
| <#-- Now e is the first para of the first chapter --> |
| ${e?node_name} |
| ${e?parent?node_name} |
| ${e?parent?parent?node_name} |
| ${e?parent?parent?parent?node_name}</pre> </div> |
| |
| |
| <p>This will print:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body">para |
| chapter |
| book |
| @document</pre> </div> |
| |
| |
| <p>In the last line you have reached the root of the DOM tree, |
| the document node. It's not an element, and this is why it has that |
| strange name; don't deal with it now. Obviously, the document node |
| has no parent.</p> |
| |
| <p>You can quickly go back to the document node using the |
| <code class="inline-code">root</code> built-in:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#assign e = doc.book.chapter[0].para[0]> |
| ${e?root?node_name} |
| ${e?root.book.title}</pre> </div> |
| |
| |
| <p>This will print:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body">@document |
| Test Book</pre> </div> |
| |
| |
| <p>For the complete list of built-ins you can use to navigate in |
| the DOM tree, read the <a href="ref_builtins_node.html">reference |
| of node built-ins</a>.</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="xgui_imperative_learn_xpath">Using XPath expressions</h2> |
| |
| |
| <div class="callout note"> |
| <strong class="callout-label">Note:</strong> |
| |
| <p>XPath expressions work only if <a href="http://xml.apache.org/xalan/">Apache Xalan</a> or |
| <a href="http://jaxen.org/">Jaxen</a> (at least 1.1) |
| classes are available. However, up to Java 1.8 you don't need any |
| additional dependencies, as Apache Xalan is included in Java with |
| changed package names, which FreeMarker will automatically use |
| (unless plain Apache Xalan is also present). This internal Xalan |
| isn't available anymore on OpenJDK 9, but is still available on |
| Oracle JDK/JRE 9 (at least on official stable release "build |
| 9+181").</p> |
| </div> |
| |
| |
| <div class="callout note"> |
| <strong class="callout-label">Note:</strong> |
| |
| <p>Don't use the sample XML from the previous section, where |
| <code class="inline-code">title</code> is an attribute; that applies only to |
| that section.</p> |
| </div> |
| |
| |
| <p>If a hash key used with a node variable can't be interpreted |
| otherwise (see the <a href="xgui_imperative_formal.html">next |
| section</a> for the precise definition), then it will by |
| interpreted as an XPath expression. For more information on XPath, |
| please visit <a href="http://www.w3.org/TR/xpath">http://www.w3.org/TR/xpath</a>.</p> |
| |
| <p>For example, here we list the <code class="inline-code">para</code> elements |
| of the chapter with <code class="inline-code">title</code> element (not |
| attribute!) content "Ch1'':</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#list doc["book/chapter[title='Ch1']/para"] as p> |
| <p>${p} |
| </#list></pre> </div> |
| |
| |
| <p>It will print:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body"> <p>p1.1 |
| <p>p1.2 |
| <p>p1.3</pre> </div> |
| |
| |
| <p>The rule with sequences of length 1 (explained in earlier |
| sections) stands for XPath results as well. That is, if the |
| resulting sequence contains exactly 1 node, it also acts as the node |
| itself. For example, print the first paragraph of chapter |
| "Ch1":</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body">${doc["book/chapter[title='Ch1']/para[1]"]}</pre> </div> |
| |
| |
| <p>which prints the same as:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body">${doc["book/chapter[title='Ch1']/para[1]"][0]}</pre> </div> |
| |
| |
| <p>The context node of the XPath expression is the node (or |
| sequence of nodes) whose hash subvariable is used to issue the XPath |
| expression. Thus, this prints the same as the previous |
| example:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body">${doc.book["chapter[title='Ch1']/para[1]"]}</pre> </div> |
| |
| |
| <p>Note that currently you can use a sequence of 0 or multiple |
| (more than 1) nodes as context only if the programmer has set up |
| FreeMarker to use Jaxen instead of Xalan.</p> |
| |
| <p>Also note that XPath indexes sequence items from 1, while FTL |
| indexes sequence items from 0. Thus, to select the first chapter, |
| the XPath expression is <code class="inline-code">"/book/chapter[1]"</code>, while |
| the FTL expression is <code class="inline-code">book.chapter[0]</code>.</p> |
| |
| <p>If the programmer has set up FreeMarker to use Jaxen instead |
| of Xalan, then FreeMarker variables are visible with XPath variable |
| references:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#assign <strong>currentTitle</strong> = "Ch1"> |
| <#list doc["book/chapter[title=<strong>$currentTitle</strong>]/para"] as p> |
| <em>...</em></pre> </div> |
| |
| |
| <p>Note that <code class="inline-code">$currentTitle</code> is not a FreeMarker |
| interpolation, as there are no <code class="inline-code">{</code> and |
| <code class="inline-code">}</code> there. That's an XPath expression.</p> |
| |
| <p>The result of some XPath expressions is not a node-set, but a |
| string, a number, or a boolean. For those XPath expressions, the |
| result is an FTL string, number, or boolean variable respectively. |
| For example, the following will count the total number of |
| <code class="inline-code">para</code> elements in the XML document, so the result |
| is a number:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body">${x["count(//para)"]}</pre> </div> |
| |
| |
| <p>The output will be:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body">5</pre> </div> |
| |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_144">XML namespaces</h2> |
| |
| |
| |
| |
| <p>Be default, when you write something like |
| <code class="inline-code">doc.book</code>, then it will select the element with |
| name <code class="inline-code">book</code> that does not belongs to any XML |
| namespace (similarly to XPath). If you want to select an element |
| that is inside an XML namespace, you must register a prefix and use |
| that. For example, if element <code class="inline-code">book</code> is in XML |
| namespace <code class="inline-code">http://example.com/ebook</code>, then you have |
| to associate a prefix with it at the top of the template with the |
| <code class="inline-code">ns_prefixes</code> parameter of the <a href="ref_directive_ftl.html#ref.directive.ftl"><code>ftl</code> |
| directive</a>:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#ftl ns_prefixes={"e":"http://example.com/ebook"}></pre> </div> |
| |
| |
| <p>And now you can write expressions as |
| <code class="inline-code">doc["e:book"]</code>. (The usage of square bracket |
| syntax was required because the colon would confuse FreeMarker |
| otherwise.)</p> |
| |
| <p>As the value of <code class="inline-code">ns_prefixes</code> is a hash, you |
| can register multiple prefixes:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#ftl ns_prefixes={ |
| "e":"http://example.com/ebook", |
| "f":"http://example.com/form", |
| "vg":"http://example.com/vectorGraphics"} |
| ></pre> </div> |
| |
| |
| <p>The <code class="inline-code">ns_prefixes</code> parameter affects the whole |
| <a href="dgui_misc_namespace.html">FTL namespace</a>. This means |
| in practice that the prefixes you have registered in the main page |
| template will be visible in all <code class="inline-code"><#include |
| ...></code>-d templates, but not in <code class="inline-code"><#imported |
| ...></code>-d templates (often referred as FTL libraries). Or |
| from another point of view, an FTL library can register XML |
| namespace prefixes for it's own use, without interfering with the |
| prefix registrations of the main template and other |
| libraries.</p> |
| |
| <p>Note that, if an input document is dominated by a given XML |
| namespace, you can set that as the default namespace for |
| convenience. This means that if you don't use prefix, as in |
| <code class="inline-code">doc.book</code>, then it selects element that belongs to |
| the default namespace. The setting of the default namespace happens |
| with reserved prefix <code class="inline-code">D</code>, for example:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><#ftl ns_prefixes={"D":"http://example.com/ebook"}></pre> </div> |
| |
| |
| <p>Now expression <code class="inline-code">doc.book</code> select the |
| <code class="inline-code">book</code> element that belongs to XML namespace |
| <code class="inline-code">http://example.com/ebook</code>. Unfortunately, XPath |
| does not support this idea of a default namespace. Thus, in XPath |
| expressions, element names without prefixes always select the |
| elements that does not belong to any XML namespace. However, to |
| access elements in the default namespace you can directly use prefix |
| <code class="inline-code">D</code>, for example: |
| <code class="inline-code">doc["D:book/D:chapter[title='Ch1']"]</code>.</p> |
| |
| <p>Note that when you use a default namespace, then you can |
| select elements that does not belong to any node namespace with |
| reserved prefix <code class="inline-code">N</code>, for example |
| <code class="inline-code">doc.book["N:foo"]</code>. It doesn't go for XPath |
| expressions, where the above can be witten as |
| <code class="inline-code">doc["D:book/foo"]</code>.</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_145">Don't forget escaping!</h2> |
| |
| |
| <p>As we generate output of HTML format in these examples, and |
| HTML format reserves characters as <code class="inline-code"><</code>, |
| <code class="inline-code">&</code>, etc., we have to ensure that those will be |
| escaped. For that, either FreeMarker has to be <a href="pgui_config_outputformatsautoesc.html">properly |
| configured</a>, or add <code class="inline-code">output_format="HTML"</code> in |
| the template to the <code class="inline-code">ftl</code> directive calls.</p> |
| |
| <p>So if the book title is "Romeo & Juliet", the resulting |
| HTML output will be correctly:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body"><em>...</em> |
| <h1>Romeo &amp; Juliet</h1> |
| <em>...</em></pre> </div> |
| |
| <div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="xgui_imperative.html"><span>Previous</span></a><a class="paging-arrow next" href="xgui_imperative_formal.html"><span>Next</span></a></div></div></div></div> </div> |
| </div> |
| <div class="site-footer"><div class="site-width"><div class="footer-top"><div class="col-left sitemap"><div class="column"><h3 class="column-header">Overview</h3><ul><li><a href="https://freemarker.apache.org/">What is FreeMarker?</a></li><li><a href="https://freemarker.apache.org/freemarkerdownload.html">Download</a></li><li><a href="app_versions.html">Version history</a></li><li><a href="app_faq.html">FAQ</a></li><li><a itemprop="license" href="app_license.html">License</a></li><li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy policy</a></li></ul></div><div class="column"><h3 class="column-header">Often used / Reference</h3><ul><li><a href="https://try.freemarker.apache.org/">Try template online</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions cheatsheet</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_builtins_alphaidx.html">?built_ins</a></li><li><a href="ref_specvar.html">.special_vars</a></li><li><a href="api/freemarker/core/Configurable.html#setSetting-java.lang.String-java.lang.String-">Configuration settings</a></li></ul></div><div class="column"><h3 class="column-header">Community</h3><ul><li><a href="https://github.com/apache/freemarker">Github project page</a></li><li><a href="https://issues.apache.org/jira/projects/FREEMARKER">Report a bug</a></li><li><a href="https://freemarker.apache.org/report-security-vulnerabilities.html">Report security vulnerability</a></li><li><a href="https://stackoverflow.com/questions/ask?tags=freemarker">Get help on StackOverflow</a></li><li><a href="https://twitter.com/freemarker">Announcements on Twitter</a></li><li><a href="https://freemarker.apache.org/mailing-lists.html">Discuss on mailing lists</a></li></ul></div></div><div class="col-right"><ul class="social-icons"><li><a class="github" href="https://github.com/apache/freemarker">Github</a></li><li><a class="twitter" href="https://twitter.com/freemarker">Twitter</a></li><li><a class="stack-overflow" href="https://stackoverflow.com/questions/ask?tags=freemarker">Stack Overflow</a></li></ul><a class="xxe" href="http://www.xmlmind.com/xmleditor/" rel="nofollow" title="Edited with XMLMind XML Editor"><span>Edited with XMLMind XML Editor</span></a></div></div><div class="footer-bottom"> <p class="last-generated"> |
| Last generated: |
| <time itemprop="dateModified" datetime="2024-02-12T20:34:04Z" title="Monday, February 12, 2024 at 8:34:04 PM Greenwich Mean Time">2024-02-12 20:34:04 GMT</time>, for Freemarker 2.3.32 </p> |
| <p class="copyright"> |
| © <span itemprop="copyrightYear">1999</span>–2024 |
| <a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="https://apache.org/">The Apache Software Foundation</a>. Apache FreeMarker, FreeMarker, Apache Incubator, Apache, the Apache FreeMarker logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners. </p> |
| </div></div></div></body> |
| </html> |