Sample ASP.NET and XSLT code to server both XHTML web
pages and XCRI CAP 1.2 XML from a single course discovery page
We can expand the functionality of the ASP.NET and XSLT course discovery page
from Sample
XSLT and ASP.NET code to create web pages from your course feed to serve
subsets of your XCRI CAP 1.2 feed as well as HTML pages. This will mean adding a
new XSLT stylesheet to produce a subset of the feed using the same parameters as
before (filtered by qualification, study mode and subject) and optionally
restricting the amount of course information passed through using a new profile
parameter. The Visual Basic.NET code is updated to support the two paths.
Contents
- Directory
structure
- The ASP.NET page, save
as default2.aspx
- The ASP.NET Visual
Basic code behind file, save as default2.aspx.vb
- The XCRI CAP subsetting
XSLT stylesheet, save as xcricap1p2subset.xslt
- Sample XCRI CAP 1.2
output
- Notes
Directory structure
The sample website has this structure. The enhanced course discovery page
lives in the /courses directory, and the course details page lives in the
/courses/course subdirectory. The XSLT stylesheets are in /xml/xsl/t/courses.
- courses
- default2.aspx
- default2.aspx.vb
- xml
- xsl
- t
- courses
- xcricap1p2toxhtmlcoursediscovery.xslt
- xcricap1p2subset.xslt
The ASP.NET page, save as default2.aspx
This page is virtually the same as before, although note that the code behind
file is now default2.aspx.vb, it inherits "courses_default2, and there is an
ASP.NET Label control to write useful feedback to for testing.
<%@ Page Title="Kelpie College Courses" Language="VB" MasterPageFile="~/kelpiecollege.master" AutoEventWireup="false" CodeFile="default2.aspx.vb" Inherits="courses_default2" debug="true" %>
<asp:Content ID="Content1" ContentPlaceHolderID="BreadcrumbPlaceHolder" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="NavigationPlaceHolder" runat="Server">
<asp:Label ID="lblRequest" runat="server" />
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder" runat="Server">
<asp:Xml ID="xmlCourseList" runat="server" />
</asp:Content>
The ASP.NET Visual Basic code behind file, save as
default2.aspx.vb
The code now has conditional branching for two sets of HTTP ACCEPT values,
one requesting a HTML web page, another requesting an XCRI CAP document.
Imports System.IO
Imports System.Xml
Imports System.Xml.XPath
Imports System.Xml.Xsl
Partial Class courses_default2
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Const chrSemiColon As Char = ";"c
Const chrComma As Char = ","c
Dim strRequestAccepts As String = Request.ServerVariables("HTTP_ACCEPT")
If Not strRequestAccepts.IndexOf(chrSemiColon) = -1 Then
strRequestAccepts = strRequestAccepts.Substring(0, strRequestAccepts.IndexOf(chrSemiColon))
End If
Dim chrDelimiters() As Char = {chrSemiColon, chrComma}
lblRequest.Text = "<h2>Request accepts</h2>"
Dim strRequestAcceptArray As String() = strRequestAccepts.Split(chrDelimiters)
Dim strRequestAccept
For Each strRequestAccept In strRequestAcceptArray
lblRequest.Text &= "<br />" & strRequestAccept
Next strRequestAccept
' Get parameters from query string.
Dim strQualification As String = Request.QueryString("qualification")
Dim strStudyMode As String = Request.QueryString("studymode")
Dim strSubject As String = Request.QueryString("subject")
Dim strPage As String = Request.QueryString("page")
Dim strPageSize As String = Request.QueryString("pagesize")
' Compile the style sheet.
Dim xctTransform1 As New XslCompiledTransform()
' Choose the transform stylesheet
Dim strStylesheetUri1 As String
If strRequestAcceptArray.Contains("text/html") Or strRequestAcceptArray.Contains("application/xhtml+xml") Then
strStylesheetUri1 = "http://www.kelpiecollege.org.uk/xml/xsl/t/courses/xcricap1p2toxhtmlcoursediscovery.xslt"
Else If strRequestAcceptArray.Contains("application/xcri-cap+xml")
strStylesheetUri1 = "http://www.kelpiecollege.org.uk/xml/xsl/t/courses/xcricap1p2subset.xslt"
End If
' Choose the source XML document.
Dim strDocumentUri1 As String = "http://www.kelpiecollege.org.uk/courses/xcri/cap/1.2"
xctTransform1.Load(strStylesheetUri1)
' Create the XsltArgumentList.
Dim argList1 As XsltArgumentList = New XsltArgumentList()
' Add parameters
If Not strQualification = "" Then
argList1.AddParam("qualification", "", strQualification)
End if
If Not strStudyMode = "" Then
argList1.AddParam("studyMode", "", strStudyMode)
End if
If Not strSubject = "" Then
argList1.AddParam("subject", "", strSubject)
End if
If Not strPage = "" Then
argList1.AddParam("page", "", strPage)
End if
If Not strPageSize = "" Then
argList1.AddParam("pageSize", "", strPageSize)
End if
' Create a memory stream to carry the output of the transformation.
Dim ms1 As MemoryStream = New MemoryStream()
' Transform the XCRI CAP 1.2
xctTransform1.Transform(strDocumentUri1, argList1, ms1)
' Load the results into an XPathDocument object.
ms1.Seek(0, SeekOrigin.Begin)
If strRequestAcceptArray.Contains("text/html") Or strRequestAcceptArray.Contains("application/xhtml+xml") Then 'add the course XHTML to the web page.
Dim xpnDoc1 As XPathNavigator
Dim xpdDoc1 As XPathDocument = New XPathDocument(ms1)
xpnDoc1 = xpdDoc1.CreateNavigator
xmlCourseList.XPathNavigator = xpnDoc1
Else If strRequestAcceptArray.Contains("application/xcri-cap+xml") 'replace the web page with an XCRI CAP 1.2 document.
Dim data As Byte()
data = ms1.ToArray()
ms1.Flush()
ms1.Close()
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.ContentType = "application/xcri-cap+xml" 'For testing purposes, you can use "application/xml" below, it will render in web browsers.
'HttpContext.Current.Response.ContentType = "application/xml"
HttpContext.Current.Response.AddHeader("Content-Length", data.Length.ToString())
HttpContext.Current.Response.BinaryWrite(data)
HttpContext.Current.Response.[End]()
End If
End Sub
End Class
The XCRI CAP subsetting XSLT stylesheet, save as
xcricap1p2subset.xslt
This XSLT stylesheet uses a similar approach to the
xcricap1p2toxhtmlcoursediscovery.xslt one listed in a previous example. This
time, though, it returns a subset of your XCRI CAP 1.2 course feed.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xcri="http://xcri.org/profiles/1.2/catalog"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mlo="http://purl.org/net/mlo"
xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:credit="http://purl.org/net/cm"
xmlns:xcriTerms="http://xcri.org/profiles/1.2/catalog/terms"
exclude-result-prefixes="xs xd"
version="2.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="no" indent="yes"/>
<xd:doc scope="stylesheet">
<xd:desc>
<xd:p><xd:b>Created on:</xd:b> 2012-04-17</xd:p>
<xd:p><xd:b>Author:</xd:b> Tavis Reddick</xd:p>
<xd:p>Takes an XCRI CAP 1.2 document and filters it on parameters, and returns either a full course profile or some
subset like title, URL and abstract only.</xd:p>
</xd:desc>
</xd:doc>
<xsl:param name="qualification" />
<xsl:param name="studyMode" />
<xsl:param name="subject" />
<xsl:param name="page" select="1" />
<xsl:param name="pageSize" select="20" />
<xsl:param name="profile" select="'abstract'" /><!-- 'abstract' or 'full' -->
<xsl:variable name="courses" select="/xcri:catalog/xcri:provider/xcri:course[($qualification = '' or $qualification =
mlo:qualification/dc:title) and ($studyMode = '' or $studyMode = xcri:presentation/xcri:studyMode/@identifier) and ($subject =
'' or $subject = dc:subject)]" />
<xsl:template match="/xcri:catalog">
<xsl:copy>
<xsl:copy-of select="@xsi:schemaLocation" />
<xsl:copy-of select="@generated" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="xcri:provider">
<xsl:copy>
<xsl:copy-of select="dcterms:title" />
<xsl:for-each select="$courses">
<xsl:sort select="dcterms:title" />
<xsl:choose>
<xsl:when test="$profile = 'full'">
<xsl:copy-of select="." />
</xsl:when>
<xsl:when test="$profile = 'abstract'">
<xsl:copy>
<xsl:copy-of select="dcterms:title" />
<xsl:copy-of select="mlo:url" />
<xsl:copy-of select="xcri:abstract" />
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Sample XCRI CAP 1.2 output
If you request the URL with a web browser, you will see a web page, because
the browser tells the page it will accept "text/html" or "application/xhtml+xml"
content types.
For example, http://www.kelpiecollege.org.uk/courses/default2.aspx?qualification=&studymode=FT&subject=&pagesize=20 will list all the Full time courses as before. However, if you request a special
"application/xcri-cap+xml" content type (from a custom web application that is
designed to consume XCRI CAP, or a REST-aware debugging tool) using the same
URL, you will get something like this:
<?xml version="1.0" encoding="utf-8"?>
<catalog xsi:schemaLocation="http://xcri.org/profiles/1.2/catalog http://www.xcri.co.uk/bindings/xcri_cap_1_2.xsd http://xcri.org/profiles/1.2/catalog/terms http://www.xcri.co.uk/bindings/xcri_cap_terms_1_2.xsd" generated="2012-04-18T01:29:29.417" xmlns="http://xcri.org/profiles/1.2/catalog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mlo="http://purl.org/net/mlo" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:credit="http://purl.org/net/cm" xmlns:xcriTerms="http://xcri.org/profiles/1.2/catalog/terms">
<provider>
<dcterms:title>Kelpie College</dcterms:title>
<course>
<dcterms:title>Conversational Cetacean Harbour Dolphin Dialect</dcterms:title>
<mlo:url>http://www.kelpiecollege.org.uk/courses(HDLANG)</mlo:url>
<abstract>Learn to speak the Harbour Dolphin dialect of Cetacean and converse, question and barter with these friendly and helpful creatures.</abstract>
</course>
<course>
<dcterms:title>Hive Mind Speak level 1</dcterms:title>
<mlo:url>http://www.kelpiecollege.org.uk/courses(HLANG1)</mlo:url>
<abstract>Learn the telepathic Mind Speak of the Hive, and commune humbly with our near-neighbours from the Tenth Planet!</abstract>
</course>
</provider>
</catalog>
Note that we are using the xcricap1p2subset.xslt style sheet's default
'abstract' profile here, which only returns course title, URL and abstract
(although it is a valid XCRI CAP 1.2 document, and your application should check
this). This would make a nice linked list on a remote site, for example.
Notes
This sample should be treated with the same kind of caution as the other
samples here:
- Important! In all this code, replace any references to "http://www.kelpiecollege.org.uk/" with your own site domain
name, or better still fix the code to use a relative address.
- This is not optimized, production-ready code. In fact, I think Microsoft
are bringing out a Web API framework which
should make this kind of requirement easier to code.
- There is no error handling.
A working demonstration of the web pages built from this code scan be found on the fictional Kelpie College website courses section.
For more information on the standard, see the XCRI Knowledge Base.
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
Back to Code and Examples for XCRI CAP 1.2.
Last updated:
.