A Closer Look at the Template Markup
Experience Management inserts some very basic template markup for you in a newly created XML template. Let’s have a closer look at each major element of this inserted markup.
XML Namespaces and XHTML
Experience Management utilizes XML namespaces to identify different types of markup and it is highly recommended that developers have a good conceptual understanding of XML namespaces when working with front-end development.
XML Namespaces
XML namespaces are a mechanism that allows a computer program (and humans) to uniquely distinguish XML elements from each other, even in XML documents that contain a mix of data from different subsystems where element names might clash. By declaring that an element belongs to a certain namespace, you typically declare that it should be handled by a specific subsystem, making other subsystems take a hands-off approach to that element.
If you examine the markup of a page template, you will notice that the <html /> element contain a lot of namespace declarations in the form of xmlns=“(URL1)” and xmlns:xxx=“(URL2)”. These items define that ‘from this element and down, elements with no prefix belong to the namespace (URL1), and elements with the prefix “xxx” belong to the namespace (URL2)’. “
An element with no prefix looks like this <form /> while a prefixed element looks like this <xxx:form />. They can belong to a namespace, though.
<sample xmlns="http//collection/" xmlns:a="http://animal/" xmlns:p="http://plant/"> <title>This belongs to the collection namespace</title> <a:title>This belongs to the animal namespace</a:title> <p:title>This belongs to the plant namespace</p:title> </sample>
In the XML snippet above you can see how the same element “title” can be used by multiple subsystems without interfering with each other. The “animal” subsystem can simply ignore elements not bound to the “http://animal/” namespace.
XHTML Namespace
One of the most fundamental namespaces in Experience Management is the XHTML namespace, http://www.w3.org/1999/xhtml . Simply stated, XML templates should always use XHTML as their overall structure to allow the full feature set of Experience Management to be utilized.
The minimal structure of a page template’s markup code should look like this:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>...</title> </head> <body>...</body> </html>
One of the features of Experience Management is the ability to inject markup (for example, script and CSS declarations and includes) into a page’s <head /> section from sub-functions written in Razor, ASP.NET, XSLT and more. This is highly convenient for front-end developers since you do not need to change the central page templates and can keep your code and markup in one place.
To provide this service, Experience Management must be able to identify the resulting pages <head /> element with 100% certainty and to do so a well-formed XHTML document is expected.
You can read more on this in A Guide to XSLT Functions
XHTML and Validation
Every result part rendered by Experience Management must be a well-formed XML document. Experience Management validates the results and throws exceptions when they are not valid. If the output of the XML template is not structured as an XHTML document, all XHTML-related services in Experience Management are automatically disabled.
XHTML has the same depth of expression as HTML, but also conforms to XML syntax. This means XHTML can be validated. To most, XHTML will feel stricter than HTML.
The Role of the id Attribute
The id attribute on XHTML elements is actively used by Experience Management in the following ways:
- The value of the id attribute must be unique – two elements cannot have the same ID.
- An XHTML container such as <div /> can be assigned an id, which will automatically make it available to ASP.NET developers (see the section on <asp:placeholder />).
- XHTML elements (for example, style or script includes) added to a page’s <head /> section will be “replaced” by <head /> element output, if the same ID is used. (For more information about replacing <head /> elements, see“A Guide to XSLT Functions”.)
Core XML Template Elements
Apart from having the overall layout of an XHTML document, XML templates also contain markup that controls the placement of content and functionality. In the following few sections is a description of the core elements you can use in XML templates.
Note: The namespace prefixes in the tag names used in this section expect the following namespace declarations in your template:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:rendering="http://www.composite.net/ns/rendering/1.0" xmlns:f="http://www.composite.net/ns/function/1.0" xmlns:lang="http://www.composite.net/ns/localization/1.0" xmlns:asp="http://www.composite.net/ns/asp.net/controls"> ... </html>
rendering:page.title
The <rendering:page.title /> element inserts the title of the page being rendered. The value is user-defined and can be set on the Settings tab when editing a page.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:rendering="http://www.composite.net/ns/rendering/1.0" > <head> <title><rendering:page.title /></title> </head> <body> <h1><rendering:page.title /></h1> </body> </html>
rendering:page.description
The <rendering:page.description /> element inserts the description of the page being rendered. The value is user-defined and can be set on the Settings tab when editing a page.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:rendering="http://www.composite.net/ns/rendering/1.0" > <head> <title><rendering:page.title /></title> </head> <body> <h1><rendering:page.title /></h1> <rendering:page.metatag.description /> </body> </html>
This element defines a unique content placeholder. When rendered, the content for the current page will be inserted at its place. You can have multiple (or zero) <rendering:placeholder /> elements in your template.
When editing pages based on a particular XML template, the system will automatically show WYSIWYG editors for each <rendering:placeholder /> element defined in the template’s markup. You can thus add a new content area to a template by simply adding a new <rendering:placeholder /> element to it, and pages based on this template will automatically support the new placeholder.
<rendering:placeholder
id="{a locally unique ID}"
title="{a human readable title}"
default="{true | false}"
xmlns:rendering="http://www.composite.net/ns/rendering/1.0"/>
When adding a new <rendering:placeholder /> element, you should set its mandatory attributes in a proper way:
- The id attribute uniquely identifies the placeholder and ensures that you can move the element around and keeps a relation to the existing content defined on pages.
- The title attribute serves as the label for a template in the page’s WYSIWYG editor.
- The default attribute defines which placeholder should be shown by default when users edit a page. Only one placeholder can have the default attribute set to ‘true’.
Note: If you have multiple templates, it is highly recommended that you should use the same IDs across those templates. This ensures that the user editing a page can switch between different templates and move the content seamlessly to the new template’s placeholders.
When the <rendering:placeholder/> element is rendered, the page content is wrapped in a ASP.NET Placeholder Control with the specified ID, making it possible to read and manipulate the content from ASP.NET code.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:rendering="http://www.composite.net/ns/rendering/1.0" > <head> <title>...</title> </head> <body> <rendering:placeholder id="content" title="Content" /> </body> </html>
For two content areas you should use different IDs and titles:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:rendering="http://www.composite.net/ns/rendering/1.0" > <head /> <body> <rendering:placeholder id="content" title="Content" default="true"/> <rendering:placeholder id="contentright" title="Content (Right)" default="false" /> </body> </html>
The IDs and titles should be unique within the template.
The specific content areas, where an editor can type XHTML in, fully depend on the template related to the page.
f:function
This element defines that a function should be invoked and its result - inserted in its place. The <f:function /> elements can invoke Razor functions, XSLT functions, User Control functions, Visual functions, C# functions and SQL functions. The function invoked depends on the name specified.
You can provide parameter values to functions by nesting <f:param /> elements within the <f:function /> element, and even nesting other function calls or placeholders in parameters:
<f:function name="…" xmlns:f="http://www.composite.net/ns/function/1.0"> <f:param name="…" value="…" /> <f:param name="…"> <f:function name="…" /> </f:param> <f:param name="…"> <rendering:placeholder id="…" xmlns:rendering="http://www.composite.net/ns/rendering/1.0"/> </f:param> </f:function>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://www.composite.net/ns/function/1.0" > <head> <title>...</title> </head> <body> <f:function name="Composite.Pages.QuickSitemap" /> </body> </html>
You can read more on using functions in “A Guide to CMS Functions”.
lang:string
This element defines that a localized string – a string matching the language of the current page request - should be retrieved from a string resource repository and inserted in its place. The value of the key attribute defines which repository and string to use.
Using the <lang:string /> element makes sense when you would like to keep all strings specific to languages in a central repository for easy language versioning.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:lang="http://www.composite.net/ns/localization/1.0" > <head> <title>...</title> </head> <body> <lang:string key="Resource, Resources.Resource.Name" /> </body> </html>
See Localizing Templates in this guide for more information.
lang:switch
This element defines that a specific string or markup fragment should be selected based on the language of the page being rendered. This enables you to write localized content inline in your markup.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:lang="http://www.composite.net/ns/localization/1.0" > <head> <title>...</title> </head> <body> <lang:switch> <lang:when culture="fr-ca"> <img src="~/dk-logo.png" title="Dansk logo"/> </lang:when> <lang:when culture="en-US"> <img src="~/us-logo.png" title="American logo"/> </lang:when> <lang:default> No logo available </lang:default> </lang:switch> </body> </html>
Each localized version of the content should be placed within the <lang:when/> element. The <lang:switch/> element can contain as many <lang:when/> elements as you need – normally for each language installed on the website.
In case a language is used, which is not represented with one of the <lang:when> element, the system will use the default content, which you place within the <lang:default/> element. There can be only one <lang:default/> element in <lang:switch/>.
You can use as many <lang:switch/> elements as you need within a template.
asp:form
This element defines that an ASP.NET Form should be created and inserted on a page. ASP.NET Controls that must run inside an ASP.NET form should be placed within this element.
Typically it makes sense to have the <asp:form /> tag as a normal part of a template, ensuring that ASP.NET features are always available.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:asp="http://www.composite.net/ns/asp.net/controls" > <head> <title>...</title> </head> <body> <asp:form> <h1>ASP.NET post-back supported here</h1> </asp:form> </body> </html>
asp:placeholder
This element defines that an ASP.NET Placeholder with the specified ID should be inserted in its place. ASP.NET code running on the page will be able to get a reference to the placeholder by its ID using the ASP.NET’s this.Page.FindControl( id ) method and modify the content of this section of the page.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:asp="http://www.composite.net/ns/asp.net/controls" >
<head>
<title>...</title>
</head>
<body>
<asp:form>
<asp:placeholder id="info">
<h1>this.Page.FindControl("info") finds me!</h1>
</asp:placeholder>
</asp:form>
</body>
</html>