b2c-isml

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ISML Skill

ISML 使用指南

This skill guides you through creating and working with ISML (Isomorphic Markup Language) templates in Salesforce B2C Commerce. ISML templates combine HTML with dynamic server-side tags.
本指南将指导你在Salesforce B2C Commerce中创建和使用ISML(同构标记语言)模板。ISML模板将HTML与动态服务器端标签相结合。

Overview

概述

ISML templates are server-side templates that generate HTML. They use special tags prefixed with
is
and expressions in
${...}
syntax to embed dynamic content.
ISML模板是用于生成HTML的服务器端模板。它们使用以
is
为前缀的特殊标签和
${...}
语法的表达式来嵌入动态内容。

File Location

文件位置

Templates reside in the cartridge's
templates
directory:
/my-cartridge
    /cartridge
        /templates
            /default                    # Default locale
                /product
                    detail.isml
                    tile.isml
                /home
                    homepage.isml
                /util
                    modules.isml        # Custom tag definitions
            /fr_FR                      # French-specific templates
                /product
                    detail.isml
模板存放在 cartridge 的
templates
目录中:
/my-cartridge
    /cartridge
        /templates
            /default                    # 默认语言区域
                /product
                    detail.isml
                    tile.isml
                /home
                    homepage.isml
                /util
                    modules.isml        # 自定义标签定义
            /fr_FR                      # 法语专属模板
                /product
                    detail.isml

Essential Tags

核心标签

Conditional Logic

条件逻辑

html
<isif condition="${product.available}">
    <span class="in-stock">In Stock</span>
<iselseif condition="${product.preorderable}">
    <span class="preorder">Pre-order</span>
<iselse>
    <span class="out-of-stock">Out of Stock</span>
</isif>
html
<isif condition="${product.available}">
    <span class="in-stock">有货</span>
<iselseif condition="${product.preorderable}">
    <span class="preorder">可预订</span>
<iselse>
    <span class="out-of-stock">缺货</span>
</isif>

Loops

循环

html
<isloop items="${products}" var="product" status="loopstate">
    <div class="product ${loopstate.odd ? 'odd' : 'even'}">
        <span>${loopstate.count}. ${product.name}</span>
        <isif condition="${loopstate.first}">
            <span class="badge">Featured</span>
        </isif>
    </div>
</isloop>
Loop status properties:
  • count
    - Iteration number (1-based)
  • index
    - Current index (0-based)
  • first
    - Boolean, true on first iteration
  • last
    - Boolean, true on last iteration
  • odd
    - Boolean, true on odd iterations
  • even
    - Boolean, true on even iterations
html
<isloop items="${products}" var="product" status="loopstate">
    <div class="product ${loopstate.odd ? 'odd' : 'even'}">
        <span>${loopstate.count}. ${product.name}</span>
        <isif condition="${loopstate.first}">
            <span class="badge">精选</span>
        </isif>
    </div>
</isloop>
循环状态属性:
  • count
    - 迭代次数(从1开始)
  • index
    - 当前索引(从0开始)
  • first
    - 布尔值,首次迭代时为true
  • last
    - 布尔值,最后一次迭代时为true
  • odd
    - 布尔值,奇数次迭代时为true
  • even
    - 布尔值,偶数次迭代时为true

Variables

变量

html
<!-- Set a variable (scope is required) -->
<isset name="productName" value="${product.name}" scope="page"/>

<!-- Use the variable -->
<span>${productName}</span>

<!-- Remove a variable -->
<isremove name="productName" scope="page"/>
Scopes (required):
page
,
request
,
session
,
pdict
html
<!-- 设置变量(必须指定作用域) -->
<isset name="productName" value="${product.name}" scope="page"/>

<!-- 使用变量 -->
<span>${productName}</span>

<!-- 移除变量 -->
<isremove name="productName" scope="page"/>
作用域(必填):
page
,
request
,
session
,
pdict

Output

输出

html
<!-- Basic output (HTML encoded by default) -->
<isprint value="${product.name}"/>

<!-- Unencoded output (use carefully) -->
<isprint value="${htmlContent}" encoding="off"/>

<!-- Formatted number -->
<isprint value="${price}" style="CURRENCY"/>

<!-- Formatted date -->
<isprint value="${order.creationDate}" style="DATE_SHORT"/>
html
<!-- 基础输出(默认自动HTML编码) -->
<isprint value="${product.name}"/>

<!-- 未编码输出(谨慎使用) -->
<isprint value="${htmlContent}" encoding="off"/>

<!-- 格式化数字 -->
<isprint value="${price}" style="CURRENCY"/>

<!-- 格式化日期 -->
<isprint value="${order.creationDate}" style="DATE_SHORT"/>

Include Templates

引用模板

html
<!-- Include local template -->
<isinclude template="product/components/price"/>

<!-- Include with URL (remote include) -->
<isinclude url="${URLUtils.url('Product-GetPrice', 'pid', product.ID)}"/>
html
<!-- 引用本地模板 -->
<isinclude template="product/components/price"/>

<!-- 通过URL引用(远程引用) -->
<isinclude url="${URLUtils.url('Product-GetPrice', 'pid', product.ID)}"/>

Decorator Pattern

装饰器模式

Base decorator (layouts/pagelayout.isml):
html
<!DOCTYPE html>
<html>
<head>
    <title>${pdict.pageTitle}</title>
</head>
<body>
    <header>
        <isinclude template="components/header"/>
    </header>
    <main>
        <isreplace/>  <!-- Content inserted here -->
    </main>
    <footer>
        <isinclude template="components/footer"/>
    </footer>
</body>
</html>
Page using decorator:
html
<isdecorate template="layouts/pagelayout">
    <isslot id="home-banner" context="global"/>
    <div class="homepage-content">
        <h1>${pdict.welcomeMessage}</h1>
    </div>
</isdecorate>
基础装饰器(layouts/pagelayout.isml):
html
<!DOCTYPE html>
<html>
<head>
    <title>${pdict.pageTitle}</title>
</head>
<body>
    <header>
        <isinclude template="components/header"/>
    </header>
    <main>
        <isreplace/>  <!-- 内容将插入此处 -->
    </main>
    <footer>
        <isinclude template="components/footer"/>
    </footer>
</body>
</html>
使用装饰器的页面:
html
<isdecorate template="layouts/pagelayout">
    <isslot id="home-banner" context="global"/>
    <div class="homepage-content">
        <h1>${pdict.welcomeMessage}</h1>
    </div>
</isdecorate>

Expressions

表达式

Expressions use
${...}
syntax to embed dynamic values:
html
<!-- Property access -->
${product.name}
${product.price.sales.value}

<!-- Method calls -->
${product.getAvailabilityModel().isInStock()}

<!-- Built-in objects -->
${pdict.myVariable}           <!-- Controller data -->
${session.customer.firstName} <!-- Session data -->
${request.httpParameterMap.pid.stringValue}

<!-- Operators -->
${price > 100 ? 'expensive' : 'affordable'}
${firstName + ' ' + lastName}
${quantity * unitPrice}
表达式使用
${...}
语法嵌入动态值:
html
<!-- 属性访问 -->
${product.name}
${product.price.sales.value}

<!-- 方法调用 -->
${product.getAvailabilityModel().isInStock()}

<!-- 内置对象 -->
${pdict.myVariable}           <!-- 控制器数据 -->
${session.customer.firstName} <!-- 会话数据 -->
${request.httpParameterMap.pid.stringValue}

<!-- 运算符 -->
${price > 100 ? '高价' : '平价'}
${firstName + ' ' + lastName}
${quantity * unitPrice}

Built-in Utilities

内置工具

URLUtils

URLUtils

html
<!-- Controller URL -->
<a href="${URLUtils.url('Product-Show', 'pid', product.ID)}">View</a>

<!-- HTTPS URL -->
<a href="${URLUtils.https('Account-Show')}">My Account</a>

<!-- Static resource -->
<img src="${URLUtils.staticURL('/images/logo.png')}" alt="Logo"/>

<!-- Absolute URL -->
<a href="${URLUtils.abs('Home-Show')}">Home</a>
html
<!-- 控制器URL -->
<a href="${URLUtils.url('Product-Show', 'pid', product.ID)}">查看详情</a>

<!-- HTTPS URL -->
<a href="${URLUtils.https('Account-Show')}">我的账户</a>

<!-- 静态资源 -->
<img src="${URLUtils.staticURL('/images/logo.png')}" alt="Logo"/>

<!-- 绝对URL -->
<a href="${URLUtils.abs('Home-Show')}">首页</a>

Resource (Localization)

Resource(本地化)

html
<!-- Get localized string -->
${Resource.msg('button.addtocart', 'product', null)}

<!-- With parameters -->
${Resource.msgf('cart.items', 'cart', null, cartCount)}
html
<!-- 获取本地化字符串 -->
${Resource.msg('button.addtocart', 'product', null)}

<!-- 带参数 -->
${Resource.msgf('cart.items', 'cart', null, cartCount)}

StringUtils

StringUtils

html
<!-- Truncate text -->
${StringUtils.truncate(description, 100, '...')}

<!-- Format number -->
${StringUtils.formatNumber(quantity, '###,###')}
html
<!-- 截断文本 -->
${StringUtils.truncate(description, 100, '...')}

<!-- 格式化数字 -->
${StringUtils.formatNumber(quantity, '###,###')}

Custom Modules

自定义模块

Define reusable custom tags in
util/modules.isml
:
html
<!-- Definition in util/modules.isml -->
<ismodule template="components/productcard"
          name="productcard"
          attribute="product"
          attribute="showPrice"
          attribute="showRating"/>

<!-- Usage in any template -->
<isinclude template="util/modules"/>
<isproductcard product="${product}" showPrice="${true}" showRating="${true}"/>
Component template (components/productcard.isml):
html
<div class="product-card">
    <img src="${product.image.url}" alt="${product.name}"/>
    <h3>${product.name}</h3>
    <isif condition="${pdict.showPrice}">
        <span class="price">${product.price.sales.formatted}</span>
    </isif>
    <isif condition="${pdict.showRating && product.rating}">
        <span class="rating">${product.rating} stars</span>
    </isif>
</div>
util/modules.isml
中定义可复用的自定义标签:
html
<!-- 在util/modules.isml中定义 -->
<ismodule template="components/productcard"
          name="productcard"
          attribute="product"
          attribute="showPrice"
          attribute="showRating"/>

<!-- 在任意模板中使用 -->
<isinclude template="util/modules"/>
<isproductcard product="${product}" showPrice="${true}" showRating="${true}"/>
组件模板(components/productcard.isml):
html
<div class="product-card">
    <img src="${product.image.url}" alt="${product.name}"/>
    <h3>${product.name}</h3>
    <isif condition="${pdict.showPrice}">
        <span class="price">${product.price.sales.formatted}</span>
    </isif>
    <isif condition="${pdict.showRating && product.rating}">
        <span class="rating">${product.rating} 星</span>
    </isif>
</div>

Caching

缓存

html
<!-- Cache for 24 hours -->
<iscache type="relative" hour="24"/>

<!-- Daily cache (expires at midnight) -->
<iscache type="daily" hour="0" minute="0"/>

<!-- Vary cache by parameter -->
<iscache type="relative" hour="1" varyby="price_promotion"/>
Place
<iscache>
at the beginning of the template.
html
<!-- 缓存24小时 -->
<iscache type="relative" hour="24"/>

<!-- 每日缓存(午夜过期) -->
<iscache type="daily" hour="0" minute="0"/>

<!-- 根据参数区分缓存 -->
<iscache type="relative" hour="1" varyby="price_promotion"/>
<iscache>
放在模板开头。

Content Type

内容类型

html
<!-- Set content type (must be first in template) -->
<iscontent type="text/html" charset="UTF-8"/>

<!-- For JSON responses -->
<iscontent type="application/json" charset="UTF-8"/>

<!-- For XML -->
<iscontent type="application/xml" charset="UTF-8"/>
html
<!-- 设置内容类型(必须在模板最开头) -->
<iscontent type="text/html" charset="UTF-8"/>

<!-- 用于JSON响应 -->
<iscontent type="application/json" charset="UTF-8"/>

<!-- 用于XML -->
<iscontent type="application/xml" charset="UTF-8"/>

Embedded Scripts

嵌入式脚本

html
<isscript>
    var ProductMgr = require('dw/catalog/ProductMgr');
    var product = ProductMgr.getProduct(pdict.pid);
    var price = product.priceModel.price;
</isscript>

<span>${price.toFormattedString()}</span>
Best Practice: Keep
<isscript>
blocks minimal. Move complex logic to controllers or helper scripts.
html
<isscript>
    var ProductMgr = require('dw/catalog/ProductMgr');
    var product = ProductMgr.getProduct(pdict.pid);
    var price = product.priceModel.price;
</isscript>

<span>${price.toFormattedString()}</span>
最佳实践: 尽量减少
<isscript>
代码块的内容。将复杂逻辑移至控制器或辅助脚本中。

Comments

注释

html
<!-- HTML comment (visible in source) -->

<iscomment>
    ISML comment - stripped from output.
    Use for documentation and hiding sensitive info.
</iscomment>
html
<!-- HTML注释(在源码中可见) -->

<iscomment>
    ISML注释 - 会从输出中移除。
    用于文档编写和隐藏敏感信息。
</iscomment>

Tag Location Constraints

标签位置限制

Not all ISML tags can be used anywhere. Important constraints:
TagAllowed Location
<iscontent>
Must be before DOCTYPE declaration
<isredirect>
Must be before DOCTYPE declaration
<isprint>
Only in
<body>
<isbreak>
Only in
<body>
, inside
<isloop>
<iscontinue>
Only in
<body>
, inside
<isloop>
<isnext>
Inside
<isloop>
<isreplace>
Must be within
<isdecorate>
tags
<isactivedatahead>
Only in
<head>
Tags that can be used anywhere:
<isif>
,
<isloop>
,
<isinclude>
,
<isset>
,
<isremove>
,
<iscache>
,
<iscomment>
,
<ismodule>
,
<iscookie>
,
<isstatus>
.
并非所有ISML标签都可以在任意位置使用。重要限制如下:
标签允许位置
<iscontent>
必须在DOCTYPE声明之前
<isredirect>
必须在DOCTYPE声明之前
<isprint>
仅可在
<body>
中使用
<isbreak>
仅可在
<body>
中且位于
<isloop>
内部
<iscontinue>
仅可在
<body>
中且位于
<isloop>
内部
<isnext>
位于
<isloop>
内部
<isreplace>
必须在
<isdecorate>
标签内
<isactivedatahead>
仅可在
<head>
中使用
可在任意位置使用的标签:
<isif>
,
<isloop>
,
<isinclude>
,
<isset>
,
<isremove>
,
<iscache>
,
<iscomment>
,
<ismodule>
,
<iscookie>
,
<isstatus>

Best Practices

最佳实践

  1. Use
    <iscomment>
    instead of HTML comments for sensitive info
  2. Place
    <iscontent>
    first
    in templates that need it
  3. Define modules in
    util/modules.isml
    for consistency
  4. Keep templates simple - move logic to controllers/helpers
  5. Use decorators for consistent page layouts
  6. Enable caching on cacheable pages with
    <iscache>
  7. Encode output - default encoding prevents XSS
  1. 使用
    <iscomment>
    替代HTML注释来隐藏敏感信息
  2. <iscontent>
    放在最开头
    在需要设置内容类型的模板中
  3. util/modules.isml
    中定义模块
    以保持一致性
  4. 保持模板简洁 - 将逻辑移至控制器/辅助脚本
  5. 使用装饰器 实现一致的页面布局
  6. 为可缓存页面启用缓存 使用
    <iscache>
    标签
  7. 对输出进行编码 - 默认编码可防止XSS攻击

Detailed Reference

详细参考

For comprehensive tag documentation:
  • Tags Reference - All ISML tags with examples
  • Expressions Reference - Expression syntax and built-in functions
如需完整的标签文档:
  • 标签参考 - 所有ISML标签及示例
  • 表达式参考 - 表达式语法和内置函数