Ситема как функциональность с XSLT? - PullRequest
1 голос
/ 20 августа 2010

Я недавно задал вопрос об использовании 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>

После применения декоратора кдочерняя страница, результат содержит тело дочерней страницы, в которой находился декоратор : body , и декоратор : head также заменяется и т. д. Довольно просто, как этоработает и довольно эффективный способ организации сайта.

Итак, теперь давайте предположим, что мы вместо этого используем 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-template в объявлении xsl: variable Я просто запутался, как вы можете затем использовать эти данные помимовыводить его ..

Любая помощь будет оценена

1 Ответ

2 голосов
/ 20 августа 2010

С этим вводом:

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

...