.net 具有动态内容区域的XSLT布局

.net 具有动态内容区域的XSLT布局,.net,xml,xslt,.net,Xml,Xslt,我正在重新构建我们网站的UI部分,它完全基于javascript/ajax(没有充分的理由,而且效率相当低),这样后端现在就可以生成大部分内容。这是一个C#.net应用程序 几乎我们所有的页面(可能有40-50页)都有相同的基本布局。我是XSLT新手,但我在MVC框架方面做了很多工作,比如Spring(java,使用Sitemesh进行布局)、Symfony(PHP)、rails以及其他一些框架。我喜欢能够有一个或多个通用模板,然后有一个特定的“内容”部分,其中包含页面特定的内容。我不明白XSL

我正在重新构建我们网站的UI部分,它完全基于javascript/ajax(没有充分的理由,而且效率相当低),这样后端现在就可以生成大部分内容。这是一个C#.net应用程序

几乎我们所有的页面(可能有40-50页)都有相同的基本布局。我是XSLT新手,但我在MVC框架方面做了很多工作,比如Spring(java,使用Sitemesh进行布局)、Symfony(PHP)、rails以及其他一些框架。我喜欢能够有一个或多个通用模板,然后有一个特定的“内容”部分,其中包含页面特定的内容。我不明白XSLT是如何做到这一点的。对于这个应用程序,我在支持xslt页面的xml中有一个可用的值,我们称之为ContentXSL,谁的值是xsl文件的名称 我想用于页面的内容部分。我知道这是不可能的,但最好使用:

 <xsl:call-template name="{$ContentXSL}" />

然后我可以简单地把它放在内容部分。。但是这是不可能的,因此我需要一个大规模的choose语句,根据ContentPage变量调用正确的模板。。这也意味着在Layout.xsl文件中,我必须包含所有40-50个xsl文档。。我想开销会很大,但我不确定。如果网站流量很大,这样做合理吗

其他常见的方法是什么?似乎大多数现代框架都允许您使用这种模式来装饰内容。在Symfony的例子中,它工作得非常好,并且非常灵活(有插槽等等)

我知道另一个可能的解决方案是有40个独立的文件,所有这些文件都有类似的标记,并包括像页眉和页脚这样的特殊部分。这意味着,如果我想改变我的网站布局的整体结构,我必须编辑所有40-50页(非常烦人)

更新--更多解释

我想进一步解释这一点,因为我有一些需要大量工程才能改变的要求。 首先,后端将传递给我一些xml,让我知道网站URL中的查询参数。。此外,它还将传递给我构建页面所需的数据(数据采用业务数据的形式,没有html或类似的内容)。 数据与此类似:

<xml>
 <section>Blogs</section>
 <page>showAll</section>
  <data>
   <blogs>
     <blog>
       <author>somebody</author>
       <title></title>
       <content>..</content>
    </blog>
    </blog>..</blog>
   </blogs>    
  </data>
</xml>

博客
showAll
某人
..
..
现在我们想要的是这样一个页面模板:

<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:msxsl='urn:schemas-microsoft-com:xslt'>  
 <xsl:output omit-xml-declaration='yes' method='html' media-type='text/html' indent='yes' />
 <xsl:include href="Header.xsl"/>
 <xsl:include href="Nav.xsl"/> 
 <xsl:template name='MainLayout' match='*'>
 <html>
  <head>
   <title></title>
  </head>
  <body>
    <div id="header"><xsl:call-template name="Header" /></div>
    <div id="nav"><xsl:call-template name="Nav" /></div>
    <div id="content">
      [here is where i want to use the xsl from {/xml/section}/{/xml/page}.xsl]
    </div>
  </body>
</html>
</xsl:template>    
</xsl:stylesheet>

[这里是我想使用来自{/xml/section}/{/xml/page}.xsl的xsl的地方]
现在,对于本页的内容,我将有以下文件: Blogs/showAll.xsl

<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:msxsl='urn:schemas-microsoft-com:xslt'>  
      <xsl:output omit-xml-declaration='yes' method='html' media-type='text/html' indent='yes' />
<xsl:template name='Blogs_ShowAll'>
  <div id="blogs-showAll">
   ..iterate over /xml/data/blogs converting to html
  </div>
</xsl:template>
</xsl:stylesheet>

…迭代/xml/data/blogs转换为html
到目前为止,这些解决方案都很好,但我只能完全消化其中的一个(其中提到包括所有xsl文件并使用xsl:choose选择正确的一个)。 我不知道如何将FXSL方法应用于手头的问题。 请注意,我并不反对使用sitemesh类型的方法,我指定了html/body标记以及子项中的所有标记,并让它将子项的body部分中的内容替换到版面的content div中(同样,如果子项中有标题标记,则替换版面中的标题标记——诸如此类)

注意事项

<num>2</num>
  increment(2) = 3

  double(2) = 4
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <html>
   <xsl:apply-templates select="*/page"/>
  </html>
 </xsl:template>

 <xsl:template match="page[. = 'showAll']">
   <!-- Transform all data to html -->
   <xsl:apply-templates select="../*/blogs" mode="showAll"/>
 </xsl:template>

 <xsl:template match="page[. = 'showBrief']">
   <!-- Transform the data to Summary html -->
      <xsl:apply-templates select="../*/blogs" mode="showBrief"/>
 </xsl:template>

 <xsl:template match="blogs" mode="showAll">
  <h1>All Blogs: </h1>
  <table border="1">
    <xsl:apply-templates mode="showAll"/>
  </table>
 </xsl:template>

 <xsl:template match="blog" mode="showAll">
  <tr>
    <td>Blog of <xsl:value-of select="author"/></td>
    <td><xsl:value-of select="title"/></td>
  </tr>
  <tr>
    <td colspan="2"><xsl:apply-templates select="content/node()" mode="showAll"/></td>
  </tr>
  <xsl:if test="not(position()=last())">
   <tr><td colspan="2">&#xA0;</td></tr>
  </xsl:if>
 </xsl:template>

  <xsl:template match="blogs" mode="showBrief">
  <h1>Blogs Summary: </h1>
  <table border="1">
    <xsl:apply-templates mode="showBrief"/>
  </table>
  </xsl:template>

   <xsl:template match="blog" mode="showBrief">
     <tr>
      <td>
        <xsl:value-of select="concat(author, ': ', title)"/>
      </td>
     </tr>
   </xsl:template>

</xsl:stylesheet>
<html>
   <h1>All Blogs: </h1>
   <table border="1">
      <tr>
         <td>Blog of John Smith</td>
         <td>All about golden fish</td>
      </tr>
      <tr>
         <td colspan="2">
            Here I publish my latest achievements
                   in raising golden fish.

         </td>
      </tr>
      <tr>
         <td colspan="2">&nbsp;</td>
      </tr>
      <tr>
         <td>Blog of Mary Jones</td>
         <td>Knitting, Knitting, Knitting</td>
      </tr>
      <tr>
         <td colspan="2">
                   How to knit a sharf.

         </td>
      </tr>
   </table>
</html>
 <page>showBrief</page>
<html>
   <h1>Blogs Summary: </h1>
   <table border="1">
      <tr>
         <td>John Smith: All about golden fish</td>
      </tr>
      <tr>
         <td>Mary Jones: Knitting, Knitting, Knitting</td>
      </tr>
   </table>
</html>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:import href="showAll.xsl"/>
 <xsl:import href="showBrief.xsl"/>

 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <html>
   <xsl:apply-templates select="*/page"/>
  </html>
 </xsl:template>
</xsl:stylesheet>
  • 元素可以通过全局级参数从外部传递到转换。这意味着转换不知道将执行哪些函数

  • 通过模板匹配
    fun
    元素来模拟函数,这些元素的
    名称
    属性具有特定值

  • 如果您想阅读和理解FXSL,以下是两种最好的材料:

  • (适用于XSLT 1.0)
  • (用于XSLT 2.0)

  • 迪米特里的例子很好

    这里有一种方法也可以做到这一点。。一个有点难看的解决方案,但确实奏效了

    primary.xsl

    <xsl:variable name="ContentXSL" select="/your/xml/settings/@content" />
    
    <!-- Reference templates -->
    <xsl:include href="template1.xsl" />
    <xsl:include href="template2.xsl" />
    <xsl:include href="template3.xsl" />
    <xsl:include href="template4.xsl" />
    
    <xsl:template match="/">
      <html>
        <head>
          <title>..</title>
        </head>
      </html>
      <body>
        <xsl:call-template name="getcontent" />
      </body>
    </xsl:template>
    
    <xsl:template name="getcontent">
      <xsl:choose>
        <xsl:when test="$ContentXSL = 'template1'">
          <xsl:apply-templates match="/your/xml/structure" mode="template1" />
        </xsl:when>
        <xsl:when test="$ContentXSL = 'template2'">
          <xsl:apply-templates match="/your/xml/structure" mode="template2" />
        </xsl:when>
        <xsl:when test="$ContentXSL = 'template3'">
          <xsl:apply-templates match="/your/xml/structure" mode="template3" />
        </xsl:when>
        <xsl:when test="$ContentXSL = 'template4'">
          <xsl:apply-templates match="/your/xml/structure" mode="template4" />
        </xsl:when>
        <xsl:otherwise>
          <!-- Default template? -->
          <xsl:apply-templates match="/your/xml/structure" mode="template1" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>
    
    
    ..
    
    template1.xsl

    <xsl:template match="/your/xml/structure" mode="template1">
      Template 1<br />
    </xsl:template>
    
    
    模板1
    template2.xsl

    <xsl:template match="/your/xml/structure" mode="template2">
      Template 2<br />
    </xsl:template>
    
    
    模板2
    template3.xsl

    <xsl:template match="/your/xml/structure" mode="template3">
      Template 3<br />
    </xsl:template>
    
    
    模板3
    template4.xsl

    <xsl:template match="/your/xml/structure" mode="template4">
      Template 4<br />
    </xsl:template>
    
    
    模板4

    除了优秀的Dimitre的答案推荐了一种实现高阶函数的方法外,您还可以使用母版页和子页与某种代码隐藏相结合的方法,如下所示:

    <xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:msxsl='urn:schemas-microsoft-com:xslt'>  
     <xsl:output omit-xml-declaration='yes' method='html' media-type='text/html' indent='yes' />
     <xsl:include href="Header.xsl"/>
     <xsl:include href="Nav.xsl"/> 
     <xsl:template name='MainLayout' match='*'>
     <html>
      <head>
       <title></title>
      </head>
      <body>
        <div id="header"><xsl:call-template name="Header" /></div>
        <div id="nav"><xsl:call-template name="Nav" /></div>
        <div id="content">
          [here is where i want to use the xsl from {/xml/section}/{/xml/page}.xsl]
        </div>
      </body>
    </html>
    </xsl:template>    
    </xsl:stylesheet>
    
    MasterContent.xml:

    <title>Test for XSLT</title>
    
    XSLT的测试 MasterLayout.xml:

    <html>
        <head>
            <title></title>
        </head>
        <body>
            <p>This is master page</p>
        </body>
    </html>
    
    
    这是母版页

    Master.xsl:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:param name="pMasterLayout" select="document('MasterLayout.xml')"/>
        <xsl:param name="pMasterContent" select="document('MasterContent.xml')"/>
        <xsl:output method="xml"/>
        <xsl:template match="/">
            <xsl:apply-templates select="$pMasterLayout/*"/>
        </xsl:template>
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="title">
            <xsl:copy>
                <xsl:value-of select="$pMasterContent/title"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    
    
    
    子布局:

    <html>
        <head>
            <title></title>
        </head>
        <body>
            <h1></h1>
        </body>
    </html>
    
    
    
    因此,此转换(“Child.xsl”):

    
    
    使用此输入(“ChildContent”):

    子内容
    
    输出:

    <html>
        <head>
            <title>Test for XSLT</title>
        </head>
        <body>
            <h1>Child Content</h1>
        </body>
    </html>
    
    
    XSLT测试
    子内容
    
    注意

    在aranedabienesraices.com.ar上查看一个更好的实例
    我建议使用
    @id
    作为锚来填充布局中的内容(您可以去掉那些带有空模板的内容)。此方法不会将您绑定到任何供应商IDE(使用XSLT概念)来构建布局页面。

    OP提供了有关其问题的其他详细信息,此答案提供了现在请求的其他解决方案

    I。
    <html>
       <h1>All Blogs: </h1>
       <table border="1">
          <tr>
             <td>Blog of John Smith</td>
             <td>All about golden fish</td>
          </tr>
          <tr>
             <td colspan="2">
                Here I publish my latest achievements
                       in raising golden fish.
    
             </td>
          </tr>
          <tr>
             <td colspan="2">&nbsp;</td>
          </tr>
          <tr>
             <td>Blog of Mary Jones</td>
             <td>Knitting, Knitting, Knitting</td>
          </tr>
          <tr>
             <td colspan="2">
                       How to knit a sharf.
    
             </td>
          </tr>
       </table>
    </html>
    
     <page>showBrief</page>
    
    <html>
       <h1>Blogs Summary: </h1>
       <table border="1">
          <tr>
             <td>John Smith: All about golden fish</td>
          </tr>
          <tr>
             <td>Mary Jones: Knitting, Knitting, Knitting</td>
          </tr>
       </table>
    </html>
    
    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:import href="showAll.xsl"/>
     <xsl:import href="showBrief.xsl"/>
    
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="/">
      <html>
       <xsl:apply-templates select="*/page"/>
      </html>
     </xsl:template>
    </xsl:stylesheet>