XML Templates
A Closer Look at the Template Markup
As you already know, C1 CMS 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.
C1 CMS 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 in C1 CMS.
In short, 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 particular 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 />. Both of them 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>
Listing 2: Sample of using namespaces
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.
One of the most fundamental namespaces in C1 CMS is the XHTML namespace, http://www.w3.org/1999/xhtml . Simply stated, XML templates should always use XHTML as their overall structure in order to allow the full feature set of C1 CMS 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>
Listing 3: Minimal structure of a template’s markup
One of the features of C1 CMS 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.
In order to provide this service, C1 CMS 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”.)
Every result part rendered by C1 CMS must be a well-formed XML document. C1 CMS 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 C1 CMS 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.
(Please refer to the standard documentation on XML and XHTML for more information.)
The id attribute on XHTML elements is actively used by C1 CMS 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, please refer to “A Guide to XSLT Functions”.)
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.
Please note that 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>
Listing 4: Namespaces required by core C1 CMS template elements
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>
Listing 5: <rendering:page.title /> used
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>
Listing 6: <rendering:page.description /> used
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"/>
Listing 7: <rendering:placeholder /> with attributes
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 still keep a relation to the existing content defined on pages.
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. - 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 that 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>
Listing 8: <rendering:placeholder /> used
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>
Listing 9: Creating two content areas
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.
This element defines that a C1 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>
Listing 10: A sample of a function call with parameters nesting another function call
<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>
Listing 11: A simple function call
(You can read more on using functions in “A Guide to CMS Functions”.)
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>
Listing 12: <lang:string /> used
Please refer to the chapter “Localizing Templates“ in this guide for more information.
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="da-DK"> <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>
Listing 13: <lang:switch /> used
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.
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>
Listing 14: <asp:form /> used
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>
Listing 15: <asp:placeholder /> used