0

我对 XSLT 很陌生。我被困在我的项目中。我需要获取下面的 XML 并在下面生成所需的 HTML。

我需要获取“附加”小节下的子节点,并将它们两两分成 HTML 行,每行中都有一个左右元素。

我可以设法获得正确的左右元素。然后我可以将所有子节点分组到一个大行中,或者将每个子节点分组到一个单独的行中。但是,我无法在具有左右元素的一行中生成两个 HTML 组。

我需要将附加故事的数量限制为 show="" 属性。这将始终返回一个偶数。我有限制工作,我可以计算行数。但不能将它们分成两排。

我知道您需要使用复制节点,但我无法使其工作。

我有以下 XML:

<?xml version="1.0" ?>
<fullpage>
<section name="tops">
    <subsect name="featured" count="1">
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align></align>
            <size>2</size>
        </article>
    </subsect>
    <subsect name="additional" count="7" show="6">
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>left</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>right</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>left</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>right</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>left</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>right</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>left</align>
        </article>
    </subsect>
</section>
<section name="section2">
    <article>
        ...
    </article>
    <article>
        ...
    </article>
    <article>
        ...
    </article>
    <article>
        ...
    </article>
</section>
</fullpage>

到目前为止,这是 XSLT:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>

<xsl:variable name="topadd" select="fullpage/section[@name='tops']/subsect[@name='additional']/@show" />
<xsl:variable name="topaddrows" select="fullpage/section[@name='tops']/subsect[@name='additional']/@show div 2" />

<!-- top news -->
<div class="bucket">
    <xsl:for-each select="fullpage/section[@name='tops']/subsect[@name='featured']">
     <xsl:choose>
        <xsl:when test="article/size = '2'">
         <div class="col2Feature">
            <ul>
             <li> Two <xsl:value-of select="article/title"/> </li>
            </ul>
         </div>
        </xsl:when>
        <xsl:when test="article/size = '4'">
         <div class="col4Feature">
            <ul>
             <li> Four <xsl:value-of select="article/title"/> </li>
            </ul>
         </div>
        </xsl:when>
        <xsl:when test="article/size = '6'">
         <div class="col6Feature">
            <ul>
             <li> Six <xsl:value-of select="article/title"/> </li>
            </ul>
         </div>
        </xsl:when>
        <xsl:when test="article/size = '8'">
         <div class="col8Feature">
            <ul>
             <li> Eight <xsl:value-of select="article/title"/> </li>
            </ul>
         </div>
        </xsl:when>
     </xsl:choose>
     <!-- /feature -->

    </xsl:for-each>
</div>
<!-- /top news --> 

<xsl:value-of select="$topaddrows"/>
<xsl:for-each select="fullpage/section[@name='tops']/subsect[@name='additional']/article">
 <xsl:if test="not(position() > $topadd)">
    <xsl:choose>
     <xsl:when test="align = 'left'">
        <div class="bucketL">
         <ul>
            <li> <xsl:value-of select="title"/> </li>
         </ul>
        </div>
     </xsl:when>
     <xsl:when test="align = 'right'">
        <div class="bucketR">
         <ul>
            <li> <xsl:value-of select="title"/> </li>
         </ul>
        </div>
     </xsl:when>
    </xsl:choose>
 </xsl:if>
</xsl:for-each>

</body>
</html>
</xsl:template>
</xsl:stylesheet>

所需的 HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Document</title>
</head>

<body>
<div class="bucket">
<div class="col2Feature">
    <ul>
        <li> Two Title Element</li>
    </ul>
</div>
</div>
<div class="col2">
<div class="bucketL">
    <ul>
        <li>Title Element</li>
    </ul>
</div>
<div class="bucketR">
    <ul>
        <li>Title Element</li>
    </ul>
</div>
</div>
<div class="col2">
<div class="bucketL">
    <ul>
        <li>Title Element</li>
    </ul>
</div>
<div class="bucketR">
    <ul>
        <li>Title Element</li>
    </ul>
</div>
</div>
<div class="col2">
<div class="bucketL">
    <ul>
        <li>Title Element</li>
    </ul>
</div>
<div class="bucketR">
    <ul>
        <li>Title Element</li>
    </ul>
</div>
</div>
</body>
</html>
4

2 回答 2

0

实现您想要实现的方法是将当前的xsl:for-each更改为仅选择每个“行”中首先出现的文章元素。即位置1、3、5等中的文章元素...

<xsl:for-each select="fullpage/section[@name='tops']/subsect[@name='additional']
                      /article[position() mod 2 = 1]">

事实上,您也可以将您对文章元素总数的检查添加到条件中,以避免进行xsl:if检查。

<xsl:for-each select="fullpage/section[@name='tops']/subsect[@name='additional']
                      /article[not(position() > $topadd)][position() mod 2 = 1]">

然后,在这个 XSLT 循环中,您可以输出当前文章的标题和下一篇文章,就像这样

<div class="col2">
    <div class="bucketL">
     <ul>
        <li> <xsl:value-of select="title"/> </li>
     </ul>
    </div>
    <div class="bucketR">
     <ul>
        <li> <xsl:value-of select="following-sibling::article[1]/title"/> </li>
     </ul>
    </div>
</div>

但是,如果您热衷于学习 XSLT,那么值得指出您的 XSLT 可以稍微提高一下,因为有很多重复的代码。

例如,您fullpage/section[@name='tops']在许多地方使用 xpath 表达式。您可以通过使用模板匹配来简化这一点,这就是 XSLT 的用武之地。您将从选择顶部开始,如下所示:

<xsl:apply-templates select="fullpage/section[@name='tops']"/>

然后,在与部分匹配的模板中,您将执行此操作,这比当前的xsl:for-each略短

<xsl:apply-templates select="subsect[@name='additional']/article[not(position() &gt; $topadd)][position() mod 2 = 1]"/>

您也可以使用属性值模板。例如,要为您的“特色”部分输出属性,您可以这样做

<div class="col{article/size}Feature">

花括号表示要计算的表达式,而不是字面输出。

试试这个 XSLT。当应用于您的 XML 时,它应该有望提供您需要的输出。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:variable name="topadd" select="/fullpage/section[@name='tops']/subsect[@name='additional']/@show"/>
   <xsl:variable name="topaddrows" select="$topadd div 2"/>

   <xsl:template match="/">
      <html>
         <body>
            <div class="bucket">
               <xsl:apply-templates select="fullpage/section[@name='tops']"/>
            </div>
         </body>
      </html>
   </xsl:template>

   <xsl:template match="section">
      <xsl:apply-templates select="subsect[@name='featured']"/>
      <xsl:apply-templates select="subsect[@name='additional']/article[not(position() &gt; $topadd)][position() mod 2 = 1]"/>
   </xsl:template>

   <xsl:template match="subsect">
      <div class="col{article/size}Feature">
         <ul>
            <li>
               <xsl:choose>
                  <xsl:when test="article/size = '2'"> Two </xsl:when>
                  <xsl:when test="article/size = '4'"> Four </xsl:when>
                  <xsl:when test="article/size = '6'"> Six </xsl:when>
                  <xsl:when test="article/size = '8'"> Eight </xsl:when>
               </xsl:choose>
               <xsl:value-of select="article/title"/>
            </li>
         </ul>
      </div>
   </xsl:template>

   <xsl:template match="article">
      <div class="col2">
         <xsl:apply-templates select="title"/>
         <xsl:apply-templates select="following-sibling::article[1]/title">
            <xsl:with-param name="class" select="'bucketR'"/>
         </xsl:apply-templates>
      </div>
   </xsl:template>

   <xsl:template match="title">
      <xsl:param name="class" select="'bucketL'"/>
      <div class="{$class}">
         <ul>
            <li>
               <xsl:value-of select="."/>
            </li>
         </ul>
      </div>
   </xsl:template>
</xsl:stylesheet>

还要注意最终模板中参数的使用,这样可以为左右标题输出不同的类名。

于 2013-08-08T22:40:15.270 回答
0

下面是一个简单地根据大小计算行的解决方案,没有内置在样式表中的任何假设。我不得不猜测你从哪里得到一些类名,但我想你可以修改它。这使用 XSLT 2.0 ...如果您坚持使用 XSLT 1.0,那么您可以跟进 Tim 的解决方案。下面的解决方案说明了我教我的学生按计算分组而不是按内容分组(许多学生认为您必须按内容分组)。

t:\ftemp>type joe.xml 
<?xml version="1.0" ?>
<fullpage>
<section name="tops">
    <subsect name="featured" count="1">
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align></align>
            <size>2</size>
        </article>
    </subsect>
    <subsect name="additional" count="7" show="6">
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>left</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>right</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>left</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>right</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>left</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>right</align>
        </article>
        <article>
            <url>http://www.myurl.com</url>
            <title>Title Element</title>
            <description>Description</description>
            <align>left</align>
        </article>
    </subsect>
</section>
</fullpage>
t:\ftemp>call xslt2 joe.xml joe.xsl 
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <title>Untitled Document</title>
   </head>
   <body>
      <div class="bucket">
         <div class="col2Feature">
            <ul>
               <li>Title Element</li>
            </ul>
         </div>
      </div>
      <div class="col2">
         <div class="bucketL">
            <ul>
               <li>Title Element</li>
            </ul>
         </div>
         <div class="bucketR">
            <ul>
               <li>Title Element</li>
            </ul>
         </div>
      </div>
      <div class="col2">
         <div class="bucketL">
            <ul>
               <li>Title Element</li>
            </ul>
         </div>
         <div class="bucketR">
            <ul>
               <li>Title Element</li>
            </ul>
         </div>
      </div>
      <div class="col2">
         <div class="bucketL">
            <ul>
               <li>Title Element</li>
            </ul>
         </div>
         <div class="bucketR">
            <ul>
               <li>Title Element</li>
            </ul>
         </div>
      </div>
   </body>
</html>
t:\ftemp>type joe.xsl 
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml"
                version="2.0">

<xsl:output indent="yes" 
            doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>

<xsl:template match="/">
<html>
<head>
<title>Untitled Document</title>
</head>

<body>
  <xsl:apply-templates select="fullpage/section"/>
</body>
</html>
</xsl:template>

<xsl:template match="section">
  <xsl:variable name="cols" select="subsect[1]/article/size"/>
  <div class="bucket">
    <div class="col{$cols}Feature">
      <ul>
        <li>
          <xsl:apply-templates select="subsect[1]/article/title/node()"/>
        </li>
      </ul>
    </div>
  </div>
  <xsl:for-each-group group-by="(position()-1) idiv $cols"
    select="subsect[2]/article[position()&lt;=current()/subsect[2]/@show]">
    <div class="col{$cols}">
      <xsl:for-each select="current-group()">
        <div class="bucket{upper-case(substring(align,1,1))}">
          <ul>
            <li><xsl:apply-templates select="title/node()"/></li>
          </ul>
        </div>
      </xsl:for-each>
    </div>
  </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>rem Done! 
于 2013-08-08T23:57:12.250 回答