Ситема как функциональность с XSLT?
Недавно я задал вопрос об использовании XSL/t для создания макета сайта и дочерних страниц здесь. Где макет будет украшать дочернюю страницу. Я хочу расширить эту идею и придумать функциональность, подобную SiteMesh. Обратите внимание, что у меня будет очень небольшое количество файлов макета xsl, большинство моих файлов xsl должны быть для дочерних страниц. Макет довольно прост, он включает в себя заголовок, главное меню, нижний колонтитул, тело с содержимым div под ним. SiteMesh позволяет вам определять файлы шаблонов как довольно стандартный HTML-файл, а затем дочерние страницы, которые будут переопределять разделы родительского элемента. Например, вот базовый шаблон (декоратор) для sitemesh:
<%@ taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %>
<head>
<title>
<decorator:title default="SiteMesh Tutorial Example" /> - Site Title
</title>
<style type="text/css">@import "css/global.css";</style>
<decorator:head />
<body>
<div id="header">
<h2><a href="http://www.my-site.com/">Mysite.com</a> goes here</h2>
</div>
<div id="content">
<decorator:body />
</div>
</body>
</html>
И тогда вот пример дочерней страницы:
<html>
<head>
<title>Child Page</title>
<style type='text/css'>
p { margin: 10 }
</style>
</head>
<body>
Content Goes here
</body>
</html>
Как только декоратор применен к дочерней странице, результат содержит тело дочерней страницы, где находился декоратор: тело, и декоратор: голова также заменяется и т. Д. Довольно просто, как это работает, и довольно эффективный способ организация сайта.
Итак, теперь давайте предположим, что мы вместо этого используем XSL/T, и мы хотим использовать аналогичную структуру, в которой мы не переопределяем то, как выглядит макет, скорее мы определяем это, надеюсь, только один раз (или, возможно, несколько раз для страниц, которые не ' очень похоже), и мы заменяем разделы, если они есть у дочернего шаблона. Похоже, это будет очень просто, но проблема в том, что данные, которые поддерживают этот сайт, будут выглядеть (на самом деле не сайт блога, а просто пример того, с чем я имею дело)
<xml>
<section>Blogs</section>
<page>UserBlogs</page>
<data>
<blogs>
<blog>
<title>First Blog</title>
<author>John Doe</author>
<description>...</description>
</blog>
</blogs>
</data>
</xml>
Итак, давайте скажем, что у меня есть мастер-шаблон, подобный этому:
<html>
<head>
<title><!-- replace this with child title --> - Site Title</title>
<script src="common-scripts.js"></script>
<style type="text/css">@import "common.css" </style>
<!-- insert everything in the child <head> here except the title -->
</head>
<body>
<div id="header">Header/log that stuff here</div>
<div id="menu">
<ul><li><a href="#">Cat 1</a></li><li><a href="#">Cat 2</a></li></ul>
</div>
<div id="content">
<!-- replace this with everything between <body>...</body> in the child -->
</div>
<div id="footer">My Site, copyright, bla bla</div>
</body>
</html>
Итак, то, что я хочу сделать, это взять этот XML сверху (тот, что касается блогов) и применить его к моей дочерней странице, взять результат этого преобразования и применить его к моему основному шаблону (который будет копировать / применять элементы по мере необходимости). Я не уверен, есть ли способ сделать это в одной трансформации. В настоящее время архитектура такова, что мне предоставляется xml, как показано, и я должен построить это на странице. Я подумал, что, возможно, я мог бы сделать так, чтобы основной шаблон включал дочерний шаблон, а затем использовал xsl:call-template, обернутый в объявление xsl:variable для захвата результатов дочернего шаблона в текущем xml. Мне нужно каким-то образом использовать результаты этого преобразования для замены раздела title/header/content основных шаблонов.
Есть идеи, как это можно сделать?
Я вижу на этом сайте: http://www.devguru.com/technologies/xslt/quickref/xslt_element_calltemplate.html что вы можете захватить результаты xsl:call-шаблона в объявлении xsl:variable, я просто запутался, как затем вы можете использовать эти данные, кроме вывода их
Любая помощь будет оценена
1 ответ
С этим входом:
<xml>
<section>Blogs</section>
<page>UserBlogs</page>
<data>
<blogs>
<blog>
<title>First Blog</title>
<author>John Doe</author>
<description>...</description>
</blog>
</blogs>
</data>
</xml>
Этот "master.xml" документ:
<html>
<head>
<title><!-- replace this with child title --> - My Site</title>
<script src="common-scripts.js"></script>
<style type="text/css">@import "common.css" </style>
<!-- insert everything in the child <head> here except the title -->
</head>
<body>
<div id="header">Header/log that stuff here</div>
<div id="menu">
<ul>
<li>
<a href="#">Cat 1</a>
</li>
<li>
<a href="#">Cat 2</a>
</li>
</ul>
</div>
<div id="content">
<!-- replace this with everything between
<body>...</body> in the child -->
</div>
<div id="footer">My Site, copyright, bla bla</div>
</body>
</html>
Этот документ "child.xml":
<html>
<head>
<title>Child Page</title>
<style type='text/css'>p { margin: 10 }</style>
</head>
<body>
<h3 id="title">#</h3>
<dl>
<dt id="author">#</dt>
<dd id="description">#</dd>
</dl>
</body>
</html>
Эта таблица стилей:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:variable name="child" select="document('child.xml')"/>
<!-- From here to next comment could be in other stylesheet
like "master.xsl" and included with "xsl:include" -->
<xsl:variable name="master" select="document('master.xml')"/>
<xsl:template match="@*|node()">
<xsl:param name="context"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()">
<xsl:with-param name="context" select="$context"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="$master/*">
<xsl:with-param name="context" select="/"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="div[@id='content']">
<xsl:param name="context"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each select="$context/xml/data/blogs/blog">
<xsl:apply-templates select="$child/html/body/node()">
<xsl:with-param name="context" select="."/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="title/comment()">
<xsl:param name="context"/>
<xsl:value-of select="$context/xml/page"/>
</xsl:template>
<xsl:template match="head/comment()">
<xsl:param name="context"/>
<xsl:apply-templates
select="$child/html/head/node()[not(self::title)]">
<xsl:with-param name="context" select="$context"/>
</xsl:apply-templates>
</xsl:template>
<!-- Here ends the posible "master.xsl" to be included -->
<xsl:template match="@id[.='title']|@id[.='author']|@id[.='description']"/>
<xsl:template match="*[@id='title']/text()">
<xsl:param name="context"/>
<xsl:value-of select="$context/title"/>
</xsl:template>
<xsl:template match="*[@id='author']/text()">
<xsl:param name="context"/>
<xsl:value-of select="$context/author"/>
</xsl:template>
<xsl:template match="*[@id='description']/text()">
<xsl:param name="context"/>
<xsl:value-of select="$context/description"/>
</xsl:template>
</xsl:stylesheet>
Выход:
<html>
<head>
<title>UserBlogs - My Site</title>
<script src="common-scripts.js"></script>
<style type="text/css">@import "common.css" </style>
<style type="text/css">p { margin: 10 }</style>
</head>
<body>
<div id="header">Header/log that stuff here</div>
<div id="menu">
<ul>
<li>
<a href="#">Cat 1</a>
</li>
<li>
<a href="#">Cat 2</a>
</li>
</ul>
</div>
<div id="content">
<h3 id="title">First Blog</h3>
<dl>
<dt id="author">John Doe</dt>
<dd id="description">...</dd>
</dl>
</div>
<div id="footer">My Site, copyright, bla bla</div>
</body>
</html>
Примечание: это всего лишь пример. Могло быть лучше. Основные вопросы о структуре населения: логика пересекает структуру, а не данные, в основном с преобразованием идентичности; вам нужно иметь несколько якорей в макете для ссылки на данные (это широко открыто, чтобы улучшить, например, собственным пространством имен, конкретным шаблоном, таким как id="include:some-data"
, так далее.); вам нужно удалить эти якоря, если они @id
; для замены текста используйте пустые текстовые узлы в макете, это упрощает шаблон содержимого с помощью xsl:value-of
; "туннельный паттерн бедняка" (вызов Димитра) для передачи контекста данных, в основном из-за повторного заполнения. Другие проблемы: при работе с XHTML (лучше, чем HTML) следует позаботиться о: DOCTYPE в основном для IE7 (плохая улучшенная обработка CSS, в противном случае), пустые элементы объявлены в DTD (неправильное поведение с <br />
иначе). Не стесняйтесь проверять сайт, который я разместил ранее, чтобы увидеть, как я справился с этим.