Sitemesh是否具有XSLT的功能? [英] Sitemesh like functionality with XSLT?

查看:61
本文介绍了Sitemesh是否具有XSLT的功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近问了一个有关使用XSL/t创建网站布局和子页面的问题这里 ..布局将装饰子页面的位置.我想扩展这个想法,并提出类似SiteMesh的功能.请注意,我将有少量的xsl布局文件,我的大多数xsl文件应用于子页面.布局是相当基本的,它包括一个页眉,一个主菜单,一个页脚,一个正文其下有一个内容div. SiteMesh允许您将模板文件定义为相当标准的html文件,然后将子页面定义为覆盖父页面的各个部分. 例如,这是sitemesh的基本模板(装饰器):

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" %>

<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>

然后这是一个子页面的示例:

And then here would be an example of a child page:

<html>
  <head>
    <title>Child Page</title>
    <style type='text/css'> 
     p { margin: 10 }    
    </style>
  </head>
  <body>
    Content Goes here
  </body>
</html>

将修饰符应用于子页面后,结果 包含 decorator:body 所在子页面的正文,以及 decorator:head 也将被替换,依此类推. 很简单,它的工作方式以及组织网站的相当有效的方式.

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.

因此,现在让我们说我们正在使用XSL/T,而我们想使用一个类似的结构,在该结构中,我们不会不断重新定义布局的外观,而是希望仅定义一次(或者可能对页面定义几次)不太相似),并且如果子模板包含这些部分,我们将替换掉这些部分. 听起来这很简单,但是问题是支持该站点的数据看起来像(不是真正的博客站点,而是作为我正在处理的示例)

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. Sounds like this would be very simple, but the problem is that the data backing this site will look like (not really a blog site but just as an example of what i'm dealing with)

<xml>
<section>Blogs</section>
<page>UserBlogs</page>
<data>
 <blogs>
   <blog>
     <title>First Blog</title>
     <author>John Doe</author>
     <description>...</description>
   </blog>
 </blogs>
</data>
</xml>

现在让我们说我有一个这样的主模板:

So now Lets say I have a master template like this:

<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部分.

So then what I want to do is take that xml from above (the one about blogs) and apply that to my child page, and take the result of that transformation and apply it to my master template (which will copy/apply elements as needed). I'm not sure if there is a way to do this in a single transformation. 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?

我在此网站上看到: http://www.devguru.com/technologies/xslt/quickref/xslt_element_calltemplate.html 您可以在xsl:variable声明中捕获xsl:call-template的结果,我只是感到困惑,您如何才能除了使用数据之外还使用这些数据.

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..

任何帮助将不胜感激

推荐答案

使用此输入:

<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"文档:

This "master.xml" document:

<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"文档:

This "child.xml" document:

<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即可简化内容模板; 穷人的隧道模式"(Dimitre称呼)用于传递数据上下文,主要是因为迭代人口.其他问题:处理XHTML(比HTML更好)时要注意:DOCTYPE主要用于IE7(否则,将失去改进的CSS处理),在DTD中声明的空元素(否则会导致<br />错误).可以自由查看我之前发布的网站,看看我是如何处理的.

Note: This is just an example. Could be better. The pricipal issues about population pattern: the logic is trasverse the layout, not the data, mostly with identity transform; you need to have some anchors into the layout to reference the data (this is wide open to improve, as example, by own namespace, by specific pattern like id="include:some-data", etc.); you need to remove those anchor if they are @id; for text replacement use dummy text nodes in layout, this simplifies the content template with just xsl:value-of; "poor man's tunnel pattern" (Dimitre calls) for passing data context, mostly because iterated population. Other issues: when dealing with XHTML (better than HTML) take care of: DOCTYPE mostly for IE7 (loose improved CSS handling, otherwise), empty elements declared in DTD (wrong behavior with <br /> otherwise). Be free to check the site I've posted earlier to see how I'd handled those.

这篇关于Sitemesh是否具有XSLT的功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆