I recently asked a question about using XSL/t for creating a site layout and child pages Here.. Where the layout would decorate the child page. I want to expand on that idea and come up with SiteMesh like functionality. Note that I'm going to have a very small number of xsl layout files, most of my xsl files should be for the child pages.. The layout is fairly basic, it includes a header, a main menu, a footer, a body with a content div under it. SiteMesh allows you to define template files as a fairly standard html file, and then child pages which will override sections of the parent. For instance, here is a basic template (decorator) for sitemesh:
<%@ taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %>
- Site Title
Mysite.com goes here
And then here would be an example of a child page:
Child Page
Content Goes here
Once the decorator is applied to the child page, the result contains the body of the child page where the decorator:body was at, and the decorator:head gets replaced as well, etc.. Pretty simple how it works and fairly effective way of organizing a site.
So now lets say we are using XSL/T instead and we want to use a similar structure where we don't keep redefining what the layout looks like, rather we define that hopefully only once (or maybe a few times for pages that aren't very similar), and we replace out sections if the child template has them. Похоже, это было бы очень просто, но проблема в том, что данные, поддерживающие этот сайт, будут выглядеть (на самом деле не сайт блога, а просто как пример того, с чем я имею дело)
Blogs
UserBlogs
First Blog
John Doe
...
Итак, давайте скажем, что у меня есть главный шаблон, подобный следующему:
- Site Title
Header/log that stuff here
Итак, что я хочу сделать, это взять этот XML сверху (тот, что касается блогов) и применить его к моей дочерней странице, взять результат этого преобразования и применить его к моему основному шаблону ( который будет копировать / применять элементы по мере необходимости). Я не уверен, есть ли способ сделать это в одной трансформации. Currently the architecture is such that I'm provided with the xml as shown, and I have to construct that into a page.. I thought maybe I could have the master template include the child template, then use xsl:call-template wrapped in an xsl:variable declaration to capture the results of the child template on the current xml.. I need to somehow take the results of that transformation to replace the master templates title/header/content section.
Any idea how this can be done?
I see on this site: http://www.devguru.com/technologies/xslt/quickref/xslt_element_calltemplate.html that you can capture the results of a xsl:call-template in the xsl:variable declaration I'm just confused how you can then use that data besides ouputing it..
Any help would be appreciated
При этом вводе:
<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 (неправильное поведение с
в противном случае) . Не стесняйтесь проверить сайт, который я опубликовал ранее, чтобы узнать, как я с этим справился.