Sitemesh like functionality with XSLT?

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


  
    <decorator:title default="SiteMesh Tutorial Example" /> - Site Title
  
  
  
  
    
    

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

Итак, давайте скажем, что у меня есть главный шаблон, подобный следующему:



  <!-- replace this with child title --> - Site Title
  
  
  



  
  
  

Итак, что я хочу сделать, это взять этот 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

1
задан Community 23 May 2017 в 10:32
поделиться

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 (неправильное поведение с
в противном случае) . Не стесняйтесь проверить сайт, который я опубликовал ранее, чтобы узнать, как я с этим справился.

2
ответ дан 2 September 2019 в 21:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: