summaryrefslogtreecommitdiffstats
path: root/docs/content/en/functions/transform
diff options
context:
space:
mode:
Diffstat (limited to 'docs/content/en/functions/transform')
-rw-r--r--docs/content/en/functions/transform/CanHighlight.md18
-rw-r--r--docs/content/en/functions/transform/Emojify.md30
-rw-r--r--docs/content/en/functions/transform/HTMLEscape.md30
-rw-r--r--docs/content/en/functions/transform/HTMLUnescape.md30
-rw-r--r--docs/content/en/functions/transform/Highlight.md107
-rw-r--r--docs/content/en/functions/transform/HighlightCodeBlock.md38
-rw-r--r--docs/content/en/functions/transform/Markdownify.md31
-rw-r--r--docs/content/en/functions/transform/Plainify.md16
-rw-r--r--docs/content/en/functions/transform/Remarshal.md92
-rw-r--r--docs/content/en/functions/transform/Unmarshal.md292
-rw-r--r--docs/content/en/functions/transform/XMLEscape.md40
-rw-r--r--docs/content/en/functions/transform/_index.md12
12 files changed, 736 insertions, 0 deletions
diff --git a/docs/content/en/functions/transform/CanHighlight.md b/docs/content/en/functions/transform/CanHighlight.md
new file mode 100644
index 000000000..039cb12b7
--- /dev/null
+++ b/docs/content/en/functions/transform/CanHighlight.md
@@ -0,0 +1,18 @@
+---
+title: transform.CanHighlight
+description: Reports whether the given code language is supported by the Chroma highlighter.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/transform/Highlight
+ - functions/transform/HighlightCodeBlock
+ returnType: bool
+ signatures: [transform.CanHighlight LANGUAGE]
+---
+
+```go-html-template
+{{ transform.CanHighlight "go" }} → true
+{{ transform.CanHighlight "klingon" }} → false
+```
diff --git a/docs/content/en/functions/transform/Emojify.md b/docs/content/en/functions/transform/Emojify.md
new file mode 100644
index 000000000..d9f0adf67
--- /dev/null
+++ b/docs/content/en/functions/transform/Emojify.md
@@ -0,0 +1,30 @@
+---
+title: transform.Emojify
+description: Runs a string through the Emoji emoticons processor.
+categories: []
+keywords: []
+action:
+ aliases: [emojify]
+ related: []
+ returnType: template.HTML
+ signatures: [transform.Emojify INPUT]
+aliases: [/functions/emojify]
+---
+
+`emojify` runs a passed string through the Emoji emoticons processor.
+
+See the list of [emoji shortcodes] for available emoticons.
+
+The `emojify` function can be called in your templates but not directly in your content files by default. For emojis in content files, set `enableEmoji` to `true` in your site's [configuration]. Then you can write emoji shorthand directly into your content files;
+
+
+```text
+I :heart: Hugo!
+```
+
+I :heart: Hugo!
+
+[configuration]: /getting-started/configuration/
+[emoji shortcodes]: /quick-reference/emojis/
+[sc]: /templates/shortcode-templates/
+[scsource]: https://github.com/gohugoio/hugo/tree/master/docs/layouts/shortcodes
diff --git a/docs/content/en/functions/transform/HTMLEscape.md b/docs/content/en/functions/transform/HTMLEscape.md
new file mode 100644
index 000000000..bb522769c
--- /dev/null
+++ b/docs/content/en/functions/transform/HTMLEscape.md
@@ -0,0 +1,30 @@
+---
+title: transform.HTMLEscape
+description: Returns the given string, escaping special characters by replacing them with HTML entities.
+categories: []
+keywords: []
+action:
+ aliases: [htmlEscape]
+ related:
+ - functions/transform/HTMLUnescape
+ returnType: string
+ signatures: [transform.HTMLEscape INPUT]
+aliases: [/functions/htmlescape]
+---
+
+The `transform.HTMLEscape` function escapes five special characters by replacing them with [HTML entities]:
+
+- `&` → `&`
+- `<` → `&lt;`
+- `>` → `&gt;`
+- `'` → `&#39;`
+- `"` → `&#34;`
+
+For example:
+
+```go-html-template
+{{ htmlEscape "Lilo & Stitch" }} → Lilo &amp; Stitch
+{{ htmlEscape "7 > 6" }} → 7 &gt; 6
+```
+
+[html entities]: https://developer.mozilla.org/en-US/docs/Glossary/Entity
diff --git a/docs/content/en/functions/transform/HTMLUnescape.md b/docs/content/en/functions/transform/HTMLUnescape.md
new file mode 100644
index 000000000..180318077
--- /dev/null
+++ b/docs/content/en/functions/transform/HTMLUnescape.md
@@ -0,0 +1,30 @@
+---
+title: transform.HTMLUnescape
+description: Returns the given string, replacing each HTML entity with its corresponding character.
+categories: []
+keywords: []
+action:
+ aliases: [htmlUnescape]
+ related:
+ - functions/transform/HTMLEscape
+ returnType: string
+ signatures: [transform.HTMLUnescape INPUT]
+aliases: [/functions/htmlunescape]
+---
+
+The `transform.HTMLUnescape` function replaces [HTML entities] with their corresponding characters.
+
+```go-html-template
+{{ htmlUnescape "Lilo &amp; Stitch" }} → Lilo & Stitch
+{{ htmlUnescape "7 &gt; 6" }} → 7 > 6
+```
+
+In most contexts Go's [html/template] package will escape special characters. To bypass this behavior, pass the unescaped string through the [`safeHTML`] function.
+
+```go-html-template
+{{ htmlUnescape "Lilo &amp; Stitch" | safeHTML }}
+```
+
+[`safehtml`]: /functions/safe/html
+[html entities]: https://developer.mozilla.org/en-us/docs/glossary/entity
+[html/template]: https://pkg.go.dev/html/template
diff --git a/docs/content/en/functions/transform/Highlight.md b/docs/content/en/functions/transform/Highlight.md
new file mode 100644
index 000000000..29d0efdef
--- /dev/null
+++ b/docs/content/en/functions/transform/Highlight.md
@@ -0,0 +1,107 @@
+---
+title: transform.Highlight
+description: Renders code with a syntax highlighter.
+categories: []
+keywords: []
+action:
+ aliases: [highlight]
+ related:
+ - functions/transform/CanHighlight
+ - functions/transform/HighlightCodeBlock
+ returnType: template.HTML
+ signatures: ['transform.Highlight INPUT LANG [OPTIONS]']
+aliases: [/functions/highlight]
+toc: true
+---
+
+The `highlight` function uses the [Chroma] syntax highlighter, supporting over 200 languages with more than 40 available styles.
+
+## Arguments
+
+INPUT
+: The code to highlight.
+
+LANG
+: The language of the code to highlight. Choose from one of the [supported languages]. Case-insensitive.
+
+OPTIONS
+: A map, or comma-separated list, of zero or more [options]. Set default values in [site configuration].
+
+## Options
+
+lineNos
+: Boolean. Default is `false`.\
+Display a number at the beginning of each line.
+
+lineNumbersInTable
+: Boolean. Default is `true`.\
+Render the highlighted code in an HTML table with two cells. The left table cell contains the line numbers. The right table cell contains the code, allowing a user to select and copy the code without line numbers. Irrelevant if `lineNos` is `false`.
+
+anchorLineNos
+: Boolean. Default is `false`.\
+Render each line number as an HTML anchor element, and set the `id` attribute of the surrounding `<span>` to the line number. Irrelevant if `lineNos` is `false`.
+
+lineAnchors
+: String. Default is `""`.\
+When rendering a line number as an HTML anchor element, prepend this value to the `id` attribute of the surrounding `<span>`. This provides unique `id` attributes when a page contains two or more code blocks. Irrelevant if `lineNos` or `anchorLineNos` is `false`.
+
+lineNoStart
+: Integer. Default is `1`.\
+The number to display at the beginning of the first line. Irrelevant if `lineNos` is `false`.
+
+hl_Lines
+: String. Default is `""`.\
+A space-delimited list of lines to emphasize within the highlighted code. To emphasize lines 2, 3, 4, and 7, set this value to `2-4 7`. This option is independent of the `lineNoStart` option.
+
+hl_inline
+: Boolean. Default is `false`.\
+Render the highlighted code without a wrapping container.
+
+style
+: String. Default is `monokai`.\
+The CSS styles to apply to the highlighted code. See the [style gallery] for examples. Case-sensitive.
+
+noClasses
+: Boolean. Default is `true`.\
+Use inline CSS styles instead of an external CSS file. To use an external CSS file, set this value to `false` and [generate the file with the hugo client][hugo client].
+
+tabWidth
+: Integer. Default is `4`.\
+Substitute this number of spaces for each tab character in your highlighted code. Irrelevant if `noClasses` is `false`.
+
+guessSyntax
+: Boolean. Default is `false`.\
+If the `LANG` argument is blank or an unrecognized language, auto-detect the language if possible, otherwise use a fallback language.
+
+{{% note %}}
+Instead of specifying both `lineNos` and `lineNumbersInTable`, you can use the following shorthand notation:
+
+lineNos=inline
+: equivalent to `lineNos=true` and `lineNumbersInTable=false`
+
+lineNos=table
+: equivalent to `lineNos=true` and `lineNumbersInTable=true`
+{{% /note %}}
+
+## Examples
+
+```go-html-template
+{{ $input := `fmt.Println("Hello World!")` }}
+{{ transform.Highlight $input "go" }}
+
+{{ $input := `console.log('Hello World!');` }}
+{{ $lang := "js" }}
+{{ transform.Highlight $input $lang "lineNos=table, style=api" }}
+
+{{ $input := `echo "Hello World!"` }}
+{{ $lang := "bash" }}
+{{ $opts := dict "lineNos" "table" "style" "dracula" }}
+{{ transform.Highlight $input $lang $opts }}
+```
+
+[Chroma]: https://github.com/alecthomas/chroma
+[hugo client]: /commands/hugo_gen_chromastyles
+[options]: #options
+[site configuration]: /getting-started/configuration-markup#highlight
+[style gallery]: https://xyproto.github.io/splash/docs/
+[supported languages]: /content-management/syntax-highlighting#list-of-chroma-highlighting-languages
diff --git a/docs/content/en/functions/transform/HighlightCodeBlock.md b/docs/content/en/functions/transform/HighlightCodeBlock.md
new file mode 100644
index 000000000..dc396bad0
--- /dev/null
+++ b/docs/content/en/functions/transform/HighlightCodeBlock.md
@@ -0,0 +1,38 @@
+---
+title: transform.HighlightCodeBlock
+description: Highlights code received in context within a code block render hook.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/transform/CanHighlight
+ - functions/transform/Highlight
+ returnType: highlight.HighlightResult
+ signatures: ['transform.HighlightCodeBlock CONTEXT [OPTIONS]']
+---
+
+This function is only useful within a code block render hook.
+
+Given the context passed into a code block render hook, `transform.HighlightCodeBlock` returns a `HighlightResult` object with two methods.
+
+.Wrapped
+: (`template.HTML`) Returns highlighted code wrapped in `<div>`, `<pre>`, and `<code>` elements. This is identical to the value returned by the transform.Highlight function.
+
+.Inner
+: (`template.HTML`) Returns highlighted code without any wrapping elements, allowing you to create your own wrapper.
+
+```go-html-template
+{{ $result := transform.HighlightCodeBlock . }}
+{{ $result.Wrapped }}
+```
+
+To override the default [highlighting options]:
+
+```go-html-template
+{{ $opts := merge .Options (dict "linenos" true) }}
+{{ $result := transform.HighlightCodeBlock . $opts }}
+{{ $result.Wrapped }}
+```
+
+[highlighting options]: /functions/transform/highlight/#options
diff --git a/docs/content/en/functions/transform/Markdownify.md b/docs/content/en/functions/transform/Markdownify.md
new file mode 100644
index 000000000..8fb1e48ce
--- /dev/null
+++ b/docs/content/en/functions/transform/Markdownify.md
@@ -0,0 +1,31 @@
+---
+title: transform.Markdownify
+description: Renders markdown to HTML.
+categories: []
+keywords: []
+action:
+ aliases: [markdownify]
+ related:
+ - methods/page/RenderString
+ - methods/page/RenderShortcodes
+ returnType: template.HTML
+ signatures: [transform.Markdownify INPUT]
+aliases: [/functions/markdownify]
+---
+
+```go-html-template
+<h2>{{ .Title | markdownify }}</h2>
+```
+
+If the resulting HTML is a single paragraph, Hugo removes the wrapping `p` tags to produce inline HTML as required per the example above.
+
+To keep the wrapping `p` tags for a single paragraph, use the [`RenderString`] method on the `Page` object, setting the `display` option to `block`.
+
+[`RenderString`]: /methods/page/renderstring/
+
+{{% note %}}
+Although the `markdownify` function honors [markdown render hooks] when rendering markdown to HTML, use the `RenderString` method instead of `markdownify` if a render hook accesses `.Page` context. See issue [#9692] for details.
+
+[markdown render hooks]: /templates/render-hooks/
+[#9692]: https://github.com/gohugoio/hugo/issues/9692
+{{% /note %}}
diff --git a/docs/content/en/functions/transform/Plainify.md b/docs/content/en/functions/transform/Plainify.md
new file mode 100644
index 000000000..040145170
--- /dev/null
+++ b/docs/content/en/functions/transform/Plainify.md
@@ -0,0 +1,16 @@
+---
+title: transform.Plainify
+description: Returns a string with all HTML tags removed.
+categories: []
+keywords: []
+action:
+ aliases: [plainify]
+ related: []
+ returnType: string
+ signatures: [transform.Plainify INPUT]
+aliases: [/functions/plainify]
+---
+
+```go-html-template
+{{ "<b>BatMan</b>" | plainify }} → BatMan
+```
diff --git a/docs/content/en/functions/transform/Remarshal.md b/docs/content/en/functions/transform/Remarshal.md
new file mode 100644
index 000000000..24ef4381d
--- /dev/null
+++ b/docs/content/en/functions/transform/Remarshal.md
@@ -0,0 +1,92 @@
+---
+title: transform.Remarshal
+description: Marshals a string of serialized data, or a map, into a string of serialized data in the specified format.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/encoding/Jsonify
+ - functions/transform/Unmarshal
+ returnType: string
+ signatures: [transform.Remarshal FORMAT INPUT]
+aliases: [/functions/transform.remarshal]
+---
+
+The format must be one of `json`, `toml`, `yaml`, or `xml`. If the input is a string of serialized data, it must be valid JSON, TOML, YAML, or XML.
+
+{{% note %}}
+This function is primarily a helper for Hugo's documentation, used to convert configuration and front matter examples to JSON, TOML, and YAML.
+
+This is not a general purpose converter, and may change without notice if required for Hugo's documentation site.
+{{% /note %}}
+
+Example 1
+: Convert a string of TOML to JSON.
+
+```go-html-template
+{{ $s := `
+ baseURL = 'https://example.org/'
+ languageCode = 'en-US'
+ title = 'ABC Widgets'
+`}}
+<pre>{{ transform.Remarshal "json" $s }}</pre>
+```
+
+Resulting HTML:
+
+```html
+<pre>{
+ &#34;baseURL&#34;: &#34;https://example.org/&#34;,
+ &#34;languageCode&#34;: &#34;en-US&#34;,
+ &#34;title&#34;: &#34;ABC Widgets&#34;
+}
+</pre>
+```
+
+Rendered in browser:
+
+```text
+{
+ "baseURL": "https://example.org/",
+ "languageCode": "en-US",
+ "title": "ABC Widgets"
+}
+```
+
+Example 2
+: Convert a map to YAML.
+
+```go-html-template
+{{ $m := dict
+ "a" "Hugo rocks!"
+ "b" (dict "question" "What is 6x7?" "answer" 42)
+ "c" (slice "foo" "bar")
+}}
+<pre>{{ transform.Remarshal "yaml" $m }}</pre>
+```
+
+Resulting HTML:
+
+```html
+<pre>a: Hugo rocks!
+b:
+ answer: 42
+ question: What is 6x7?
+c:
+- foo
+- bar
+</pre>
+```
+
+Rendered in browser:
+
+```text
+a: Hugo rocks!
+b:
+ answer: 42
+ question: What is 6x7?
+c:
+- foo
+- bar
+```
diff --git a/docs/content/en/functions/transform/Unmarshal.md b/docs/content/en/functions/transform/Unmarshal.md
new file mode 100644
index 000000000..bc2b663e3
--- /dev/null
+++ b/docs/content/en/functions/transform/Unmarshal.md
@@ -0,0 +1,292 @@
+---
+title: transform.Unmarshal
+description: Parses serialized data and returns a map or an array. Supports CSV, JSON, TOML, YAML, and XML.
+categories: []
+keywords: []
+action:
+ aliases: [unmarshal]
+ related:
+ - functions/transform/Remarshal
+ - functions/resources/Get
+ - functions/resources/GetRemote
+ - functions/encoding/Jsonify
+ returnType: any
+ signatures: ['transform.Unmarshal [OPTIONS] INPUT']
+toc: true
+aliases: [/functions/transform.unmarshal]
+---
+
+The input can be a string or a [resource].
+
+## Unmarshal a string
+
+```go-html-template
+{{ $string := `
+title: Les Misérables
+author: Victor Hugo
+`}}
+
+{{ $book := unmarshal $string }}
+{{ $book.title }} → Les Misérables
+{{ $book.author }} → Victor Hugo
+```
+
+## Unmarshal a resource
+
+Use the `transform.Unmarshal` function with global, page, and remote resources.
+
+### Global resource
+
+A global resource is a file within the assets directory, or within any directory mounted to the assets directory.
+
+```text
+assets/
+└── data/
+ └── books.json
+```
+
+```go-html-template
+{{ $data := "" }}
+{{ $path := "data/books.json" }}
+{{ with resources.Get $path }}
+ {{ with unmarshal . }}
+ {{ $data = . }}
+ {{ end }}
+{{ else }}
+ {{ errorf "Unable to get global resource %q" $path }}
+{{ end }}
+
+{{ range where $data "author" "Victor Hugo" }}
+ {{ .title }} → Les Misérables
+{{ end }}
+```
+
+### Page resource
+
+A page resource is a file within a [page bundle].
+
+```text
+content/
+├── post/
+│ └── book-reviews/
+│ ├── books.json
+│ └── index.md
+└── _index.md
+```
+
+```go-html-template
+{{ $data := "" }}
+{{ $path := "books.json" }}
+{{ with .Resources.Get $path }}
+ {{ with unmarshal . }}
+ {{ $data = . }}
+ {{ end }}
+{{ else }}
+ {{ errorf "Unable to get page resource %q" $path }}
+{{ end }}
+
+{{ range where $data "author" "Victor Hugo" }}
+ {{ .title }} → Les Misérables
+{{ end }}
+```
+
+### Remote resource
+
+A remote resource is a file on a remote server, accessible via HTTP or HTTPS.
+
+```go-html-template
+{{ $data := "" }}
+{{ $url := "https://example.org/books.json" }}
+{{ with resources.GetRemote $url }}
+ {{ with .Err }}
+ {{ errorf "%s" . }}
+ {{ else }}
+ {{ $data = . | transform.Unmarshal }}
+ {{ end }}
+{{ else }}
+ {{ errorf "Unable to get remote resource %q" $url }}
+{{ end }}
+
+{{ range where $data "author" "Victor Hugo" }}
+ {{ .title }} → Les Misérables
+{{ end }}
+```
+
+[resource]: /getting-started/glossary/#resource
+[page bundle]: /content-management/page-bundles
+
+## Options
+
+When unmarshaling a CSV file, provide an optional map of options.
+
+delimiter
+: (`string`) The delimiter used, default is `,`.
+
+comment
+: (`string`) The comment character used in the CSV. If set, lines beginning with the comment character without preceding whitespace are ignored.
+
+lazyQuotes {{< new-in 0.122.0 >}}
+: (`bool`) If true, a quote may appear in an unquoted field and a non-doubled quote may appear in a quoted field. Default is `false`.
+
+```go-html-template
+{{ $csv := "a;b;c" | transform.Unmarshal (dict "delimiter" ";") }}
+```
+
+## Working with XML
+
+When unmarshaling an XML file, do not include the root node when accessing data. For example, after unmarshaling the RSS feed below, access the feed title with `$data.channel.title`.
+
+```xml
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
+ <channel>
+ <title>Books on Example Site</title>
+ <link>https://example.org/books/</link>
+ <description>Recent content in Books on Example Site</description>
+ <language>en-US</language>
+ <atom:link href="https://example.org/books/index.xml" rel="self" type="application/rss+xml" />
+ <item>
+ <title>The Hunchback of Notre Dame</title>
+ <description>Written by Victor Hugo</description>
+ <link>https://example.org/books/the-hunchback-of-notre-dame/</link>
+ <pubDate>Mon, 09 Oct 2023 09:27:12 -0700</pubDate>
+ <guid>https://example.org/books/the-hunchback-of-notre-dame/</guid>
+ </item>
+ <item>
+ <title>Les Misérables</title>
+ <description>Written by Victor Hugo</description>
+ <link>https://example.org/books/les-miserables/</link>
+ <pubDate>Mon, 09 Oct 2023 09:27:11 -0700</pubDate>
+ <guid>https://example.org/books/les-miserables/</guid>
+ </item>
+ </channel>
+</rss>
+```
+
+Get the remote data:
+
+```go-html-template
+{{ $data := "" }}
+{{ $url := "https://example.org/books/index.xml" }}
+{{ with resources.GetRemote $url }}
+ {{ with .Err }}
+ {{ errorf "%s" . }}
+ {{ else }}
+ {{ $data = . | transform.Unmarshal }}
+ {{ end }}
+{{ else }}
+ {{ errorf "Unable to get remote resource %q" $url }}
+{{ end }}
+```
+
+Inspect the data structure:
+
+```go-html-template
+<pre>{{ jsonify (dict "indent" " ") $data }}</pre>
+```
+
+List the book titles:
+
+```go-html-template
+{{ with $data.channel.item }}
+ <ul>
+ {{ range . }}
+ <li>{{ .title }}</li>
+ {{ end }}
+ </ul>
+{{ end }}
+```
+
+Hugo renders this to:
+
+```html
+<ul>
+ <li>The Hunchback of Notre Dame</li>
+ <li>Les Misérables</li>
+</ul>
+```
+
+### XML attributes and namespaces
+
+Let's add a `lang` attribute to the `title` nodes of our RSS feed, and a namespaced node for the ISBN number:
+
+```xml
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<rss version="2.0"
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ xmlns:isbn="http://schemas.isbn.org/ns/1999/basic.dtd"
+>
+ <channel>
+ <title>Books on Example Site</title>
+ <link>https://example.org/books/</link>
+ <description>Recent content in Books on Example Site</description>
+ <language>en-US</language>
+ <atom:link href="https://example.org/books/index.xml" rel="self" type="application/rss+xml" />
+ <item>
+ <title lang="fr">The Hunchback of Notre Dame</title>
+ <description>Written by Victor Hugo</description>
+ <isbn:number>9780140443530</isbn:number>
+ <link>https://example.org/books/the-hunchback-of-notre-dame/</link>
+ <pubDate>Mon, 09 Oct 2023 09:27:12 -0700</pubDate>
+ <guid>https://example.org/books/the-hunchback-of-notre-dame/</guid>
+ </item>
+ <item>
+ <title lang="en">Les Misérables</title>
+ <description>Written by Victor Hugo</description>
+ <isbn:number>9780451419439</isbn:number>
+ <link>https://example.org/books/les-miserables/</link>
+ <pubDate>Mon, 09 Oct 2023 09:27:11 -0700</pubDate>
+ <guid>https://example.org/books/les-miserables/</guid>
+ </item>
+ </channel>
+</rss>
+```
+
+After retrieving the remote data, inspect the data structure:
+
+```go-html-template
+<pre>{{ jsonify (dict "indent" " ") $data }}</pre>
+```
+
+Each item node looks like this:
+
+```json
+{
+ "description": "Written by Victor Hugo",
+ "guid": "https://example.org/books/the-hunchback-of-notre-dame/",
+ "link": "https://example.org/books/the-hunchback-of-notre-dame/",
+ "number": "9780140443530",
+ "pubDate": "Mon, 09 Oct 2023 09:27:12 -0700",
+ "title": {
+ "#text": "The Hunchback of Notre Dame",
+ "-lang": "fr"
+ }
+}
+```
+
+The title keys do not begin with an underscore or a letter---they are not valid [identifiers]. Use the [`index`] function to access the values:
+
+```go-html-template
+{{ with $data.channel.item }}
+ <ul>
+ {{ range . }}
+ {{ $title := index .title "#text" }}
+ {{ $lang := index .title "-lang" }}
+ {{ $ISBN := .number }}
+ <li>{{ $title }} ({{ $lang }}) {{ $ISBN }}</li>
+ {{ end }}
+ </ul>
+{{ end }}
+```
+
+Hugo renders this to:
+
+```html
+<ul>
+ <li>The Hunchback of Notre Dame (fr) 9780140443530</li>
+ <li>Les Misérables (en) 9780451419439</li>
+</ul>
+```
+
+[`index`]: /functions/collections/indexfunction
+[identifiers]: https://go.dev/ref/spec#Identifiers
diff --git a/docs/content/en/functions/transform/XMLEscape.md b/docs/content/en/functions/transform/XMLEscape.md
new file mode 100644
index 000000000..d0aafc4bd
--- /dev/null
+++ b/docs/content/en/functions/transform/XMLEscape.md
@@ -0,0 +1,40 @@
+---
+title: transform.XMLEscape
+description: Returns the given string, removing disallowed characters then escaping the result to its XML equivalent.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related: []
+ returnType: string
+ signatures: [transform.XMLEscape INPUT]
+---
+
+{{< new-in 0.121.0 >}}
+
+The `transform.XMLEscape` function removes [disallowed characters] as defined in the XML specification, then escapes the result by replacing the following characters with [HTML entities]:
+
+- `"` → `&#34;`
+- `'` → `&#39;`
+- `&` → `&amp;`
+- `<` → `&lt;`
+- `>` → `&gt;`
+- `\t` → `&#x9;`
+- `\n` → `&#xA;`
+- `\r` → `&#xD;`
+
+For example:
+
+```go-html-template
+{{ transform.XMLEscape "<p>abc</p>" }} → &lt;p&gt;abc&lt;/p&gt;
+```
+
+When using `transform.XMLEscape` in a template rendered by Go's [html/template] package, declare the string to be safe HTML to avoid double escaping. For example, in an RSS template:
+
+{{< code file="layouts/_default/rss.xml" >}}
+<description>{{ .Summary | transform.XMLEscape | safeHTML }}</description>
+{{< /code >}}
+
+[disallowed characters]: https://www.w3.org/TR/xml/#charsets
+[html entities]: https://developer.mozilla.org/en-us/docs/glossary/entity
+[html/template]: https://pkg.go.dev/html/template
diff --git a/docs/content/en/functions/transform/_index.md b/docs/content/en/functions/transform/_index.md
new file mode 100644
index 000000000..70e286b24
--- /dev/null
+++ b/docs/content/en/functions/transform/_index.md
@@ -0,0 +1,12 @@
+---
+title: Transform functions
+linkTitle: transform
+description: Template functions to transform values from one format to another.
+categories: []
+keywords: []
+menu:
+ docs:
+ parent: functions
+---
+
+Use these functions to transform values from one format to another.