Study guide
3.2 HTL (HTML Template Language) Block Statements & Context-Aware Escaping
Adobe Certified Professional - AEM Sites Developer AD0-E128
Track your progress as you read
Finished sections get a check mark.
1 Chapter 1: Dispatcher Farm & Multi-Site Configuration
1.1 AEM Dispatcher Configuration & Caching Fundamentals 1.2 Multi-Site Management (MSM) & Blueprint/Live Copy Architecture 1.3 OSGi Configuration Management & Run Modes (.cfg.json)
2 Chapter 2: Oak Indexing & Custom Logging
2.1 Custom Oak Index Definitions & Lucene Query Optimization 2.2 AEM Custom Logging, Logback Configurations & Request Tracing
3 Chapter 3: Component Architecture, HTL & Client Libraries
3.1 Core Components & Proxy Component Pattern 3.2 HTL (HTML Template Language) Block Statements & Context-Aware Escaping 3.3 Client-Side Libraries (Clientlibs) Architecture & Management
4 Chapter 4: Sling Models & OSGi Declarative Services
4.1 Sling Models Framework, Injectors & Model Exporter 4.2 OSGi Declarative Services, Component Lifecycle & Service Rankings
5 Chapter 5: Templates, Fragments & Business Workflows
5.1 Editable Templates, Structure, Initial Content & Content Policies 5.2 Content Fragments, Experience Fragments & Headless Delivery 5.3 AEM Workflows, Custom Process Steps & Launchers
6 Chapter 6: Build, Packaging & Cloud Manager CI/CD
6.1 Maven Project Structure & AEM Project Archetype 6.2 Content Package Types, Packaging Rules & FileVault Validation 6.3 Cloud Manager CI/CD Pipelines & Quality Gates 6.4 Rapid Development Environments (RDE) & Sling Repoinit Scripts
7 Chapter 7: Environment Maintenance & Content Distribution
7.1 AEM Maintenance Releases & Cloud Service Version Updates 7.2 AEM Deployment Topologies & Cloud Architecture 7.3 Replication Agents & Sling Content Distribution 7.4 Repository Maintenance: Revision Cleanup, Compaction & Purge Tasks
8 Chapter 8: Analyzing, Debugging & Diagnostic Tools
8.1 System Log Analysis & Diagnostic Tooling 8.2 Debugging Client-Side Libraries & Granite Dumplibs 8.3 Dispatcher Caching Diagnostics, X-Cache-Info & Local Validation 8.4 Environment Troubleshooting, Web Console & Developer Console
3.2 HTL (HTML Template Language) Block Statements & Context-Aware Escaping
Key Takeaways Explain This Topic AI
HTL enforces strict separation of markup and business logic by eliminating scriptlets, relying on data-sly-use to bind Sling Models and Java Use-API objects.
data-sly-resource triggers Sling Resource Resolution to render child or synthetic resources, whereas data-sly-include directly executes a local script without changing resource context.
HTL iteration statements provide automatic loop status metadata: itemList.index (0-based), itemList.count (1-based), itemList.first, itemList.last, itemList.odd, and itemList.even.
HTL provides automatic context-aware XSS escaping by analyzing the HTML AST, applying appropriate sanitization for HTML body, attributes, URIs, and scripts.
The context='unsafe' display context disables all security sanitization; its use on untrusted user-supplied input creates severe Cross-Site Scripting vulnerabilities.
Last updated: September 2026
3.2 HTL (HTML Template Language) Block Statements & Context-Aware Escaping
Exam Focus: HTL (HTML Template Language, formerly known as Sightly) is the mandatory templating engine for modern Adobe Experience Manager development. The AD0-E128 exam tests your deep understanding of HTL block statements ( data-sly-use , data-sly-resource , data-sly-include , data-sly-test , data-sly-list , data-sly-repeat , data-sly-template , data-sly-call , data-sly-attribute , data-sly-element ), built-in iteration metadata ( index , count , first , last , odd , even ), DOM unwrap mechanics with <sly> , and context-aware XSS escaping ( context='html' , context='attribute' , context='uri' , context='scriptString' , context='unsafe' ).
HTL Design Principles & Architectural Philosophy
In legacy AEM development, views were constructed using JavaServer Pages (JSP). JSPs permitted developers to embed raw Java scriptlets ( <% ... %> ) directly alongside HTML markup. This practice introduced severe architectural flaws:
Tight Coupling: Complex business logic, database queries, and repository writes leaked into the presentation layer.
Severe Security Vulnerabilities: Developers frequently forgot to apply manual HTML entity escaping, creating widespread Cross-Site Scripting (XSS) vulnerabilities.
Unmaintainability & Poor Tooling: Front-end developers could not easily read, preview, or edit JSPs without a running local AEM server.
HTL was engineered from the ground up to solve these problems by adhering to two strict tenets:
Strict Separation of Concerns: HTL contains zero support for raw Java or procedural scripting code. Presentation templates define only markup and data placeholders. All computation, business logic, data normalization, and backend calls must reside in backend Java (primarily Sling Models ).
Security by Default: HTL parses the HTML Abstract Syntax Tree (AST) at compile time. It automatically identifies the structural context of every dynamic expression and applies the appropriate context-aware output escaping to prevent XSS.
Valid HTML5 Markup: Every HTL statement is expressed as a standard HTML5 data-sly-* attribute or a synthetic <sly> tag. Templates remain valid HTML documents that can be parsed and styled by standard front-end design tools.
HTL Block Statements in Depth
HTL block statements are evaluated server-side by the Sling HTL compiler. Below is an exhaustive technical breakdown of each statement.
1. data-sly-use : Binding Backend Logic
The data-sly-use statement initializes and binds a backend logic provider to a local template variable. <!-- Binding a Sling Model -->
- <div data-sly-use.hero="com.myproject.core.models.HeroBannerModel"
- class="hero-banner">
- <h1>${hero.title}</h1>
- <p>${hero.description}</p>
- </div>
HTL supports three distinct Use-API backends:
Sling Models (Recommended): The class is automatically adapted from the current Resource or SlingHttpServletRequest .
Java Use-API ( WCMUsePojo or org.apache.sling.scripting.sightly.pojo.Use ): Legacy POJO-based approach where the class implements lifecycle methods.
JavaScript Use-API: Server-side JavaScript files located in the component directory (evaluated via the Rhino/Nashorn engine; deprecated for enterprise production).
Passing Parameters via data-sly-use
HTL allows passing dynamic parameters into Sling Models via expression options: <div data-sly-use.card="${'com.myproject.core.models.CardModel' @ title=properties.customTitle, theme='dark'}">
- <p class="theme-${card.theme}">${card.title}</p>
- </div>
Inside the Java Sling Model, these parameters are captured using the @RequestAttribute injector: @Model(adaptables = SlingHttpServletRequest.class)
- public class CardModel {
- @RequestAttribute(name = "theme")
- private String theme;
- @RequestAttribute(name = "title")
- private String title;
// getters...
- }
- 2. data-sly-resource : Including Child and Synthetic Resources
The data-sly-resource statement includes the rendering result of another JCR resource by triggering the full Apache Sling Resource Resolution pipeline. <!-- Including an existing child resource -->
<div data-sly-resource="${'image' @ resourceType='myproject/components/content/image'}"></div>
- <!-- Including with selectors and wrapper tag configuration -->
- <div data-sly-resource="${'teaser' @ resourceType='myproject/components/content/teaser',
- selectors='featured',
- decorationTagName='section',
- cssClassName='featured-teaser'}"></div>
Common data-sly-resource options:
resourceType : Overrides or explicitly sets the component used to render the target resource (essential when rendering synthetic child resources).
selectors : Passes one or more selectors to the Sling request (e.g., selectors=['card', 'compact'] ).
decorationTagName : Specifies the wrapper HTML tag generated by AEM (pass empty string '' to strip the wrapper tag entirely).
cssClassName : Appends custom CSS classes to the AEM decoration wrapper tag.
wcmmode : Overrides authoring mode for the included resource (e.g., wcmmode='disabled' ).
3. data-sly-include : Direct Script Inclusion
The data-sly-include statement directly executes and includes another script file located within the same component hierarchy: <sly data-sly-include="header.html" />
Critical Difference: data-sly-resource vs data-sly-include
Feature data-sly-resource data-sly-include
Sling Request Cycle Invokes full Sling Resource Resolution on a JCR path. Directly executes a script file in the current component folder.
Resource Context Switches context: resource points to the target resource node. Preserves context: resource and properties remain pointing to the current component.
Sling Models Instantiates a fresh Sling Model adapted to the child resource. Continues using the current component's Sling Model.
Primary Use Case Rendering child components, synthetic sub-nodes, or layout containers. Breaking down a monolithic component template into modular sub-templates.
4. data-sly-test : Conditional Rendering & Variable Definition
The data-sly-test statement conditionally renders the host element based on the truthiness of an expression: <div data-sly-test="${properties.ctaUrl}">
- <a href="${properties.ctaUrl}">Learn More</a>
- </div>
- Truthiness Rules in HTL
An expression evaluates to false if the value is:
- null
- Boolean false
- Empty string ""
- Numeric 0
- Empty array, Collection, or Map
Everything else evaluates to true .
Setting Reusable Variables
By appending an identifier (e.g., data-sly-test.hasTitle ), HTL saves the boolean outcome into a scoped variable: <sly data-sly-test.hasTitle="${properties.jcr:title}" />
- <div class="header" data-sly-test="${hasTitle}">
- <h1>${properties.jcr:title}</h1>
- </div>
- 5. data-sly-list and data-sly-repeat : Iteration & Loop Variables
Both statements iterate over Collections, Arrays, Iterators, and Maps. However, they handle host HTML elements differently:
data-sly-list : Renders the host element once as an outer container, repeating only its inner child elements.
data-sly-repeat : Duplicates the host element itself for every item in the collection. <!-- data-sly-list: <ul> rendered once, <li> repeated -->
- <ul data-sly-list.item="${model.navigationItems}">
- <li>${item.title}</li>
- </ul>
- <!-- data-sly-repeat: <div> repeated for every article -->
- <div data-sly-repeat.article="${model.articles}" class="article-card">
- <h2>${article.title}</h2>
- </div>
- Built-in Loop Metadata Variables
When iterating with data-sly-list.item (or data-sly-repeat.item ), HTL automatically creates an iteration status object named <variable>List (e.g., itemList ):
Loop Property Type Description
itemList.index int 0-based counter of the current iteration (0, 1, 2, ...).
itemList.count int 1-based counter of the current iteration (1, 2, 3, ...).
itemList.first boolean true if this is the first item in the collection ( index == 0 ).
itemList.last boolean true if this is the final item in the collection.
itemList.odd boolean true if count is odd (1, 3, 5, ...).
itemList.even boolean true if count is even (2, 4, 6, ...).
- Example utilizing loop status: <ul data-sly-list.slide="${carousel.slides}">
- <li class="slide ${slideList.first ? 'active' : ''} ${slideList.even ? 'row-even' : 'row-odd'}">
- <span>Slide ${slideList.count} of ${carousel.slides.size}</span>
- <h3>${slide.title}</h3>
- </li>
- </ul>
- 6. data-sly-template and data-sly-call : Reusable Template Macros
- HTL templates function as parameterized HTML macros: <!-- Defining a template macro -->
- <template data-sly-template.button="${@ text, linkUrl, variant}">
- <a href="${linkUrl}" class="btn btn-${variant || 'primary'}">${text}</a>
- </template>
- <!-- Calling the template in the same file -->
- <sly data-sly-call="${button @ text='Subscribe', linkUrl='/subscribe', variant='secondary'}" />
- Templates can also be imported from external files: <sly data-sly-use.lib="buttonLibrary.html"
- data-sly-call="${lib.button @ text='Contact Us', linkUrl='/contact'}" />
- 7. data-sly-attribute , data-sly-element , and <sly>
data-sly-attribute : Dynamically adds, updates, or removes attributes. If an attribute evaluates to false , null , or "" , HTL omits the attribute entirely from the rendered DOM.
data-sly-element : Dynamically switches the HTML tag name (e.g., changing <p> to <h2> based on author configuration: <h1 data-sly-element="${properties.headingTag || 'h2'}">${properties.title}</h1> ).
<sly> : A synthetic element used solely to hold HTL block statements. In the rendered HTML output, the <sly> tag is completely unwrapped and removed , leaving only its contents in the DOM.
Context-Aware XSS Escaping & Display Contexts
Cross-Site Scripting (XSS) occurs when malicious JavaScript is injected into web pages viewed by other users. HTL prevents XSS by parsing the HTML markup into an Abstract Syntax Tree (AST) and automatically applying context-aware encoding based on where the dynamic expression appears in the markup. <!-- Automatically escaped as HTML Body content (context='text') -->
<p>${properties.title}</p>
- <!-- Automatically escaped as an HTML Attribute value (context='attribute') -->
- <input type="text" value="${properties.authorName}" />
- <!-- Automatically validated as a safe URI (context='uri') -->
- <a href="${properties.linkUrl}">Visit</a>
- Comprehensive Display Contexts Reference
Developers can explicitly override the automatic escaping context using the @ context='...' option:
Display Context Description & Escaping Behavior Typical Use Case
context='text' Default for HTML element bodies. Converts special characters ( < , > , & , " , ' ) into HTML entities ( < , > , etc.). Outputting plain text titles, author names, descriptions.
context='html' Passes markup through AEM's AntiSamy / XSS Protection API . Preserves safe HTML formatting tags ( <p> , <b> , <a> ) while stripping dangerous tags ( <script> , <iframe> ) and event handlers ( onload , onclick ). Outputting Rich Text Editor (RTE) authored content.
context='attribute' Escapes quotation marks and special characters to ensure text cannot break out of an HTML attribute delimiter. Outputting dynamic values into data-* , aria-* , or title attributes.
context='uri' Validates protocol schemes (permits http , https , mailto , tel ; strictly blocks javascript: , vbscript: , data: ) and percent-encodes unsafe URI characters. Outputting dynamic URLs in <a href="..."> or <img src="..."> .
context='scriptString' Escapes quotation marks, newlines, and control characters for safe insertion inside a JavaScript string literal inside <script> tags. Emitting a string variable into an inline JavaScript snippet.
context='styleToken' Validates a single CSS token such as an identifier. Outputting a controlled CSS token; use styleString for a full style declaration string.
context='number' Emits a value only in a numeric context when it can be represented safely as a number. Emitting numeric values in markup or data attributes.
context='unsafe' Disables all escaping and sanitization entirely. Emits raw bytes directly to the HTTP response stream. Extreme Caution: Rendering trusted, pre-compiled SVG assets or trusted server-side HTML.
Critical Security Exam Warning: context='unsafe' Hazards
Exam Trap: Any question asking how to render user-supplied input, query parameters, or arbitrary author text must never use context='unsafe' . Using context='unsafe' on unvalidated input creates an immediate, critical XSS vulnerability. Static analysis may report unsafe rendering patterns, but the decisive rule is architectural: never render untrusted input with context='unsafe' ; validate or remove the need for raw output.