使用 XSLT 将 XML 元素格式化为两个一组的 HTML

发布于 2024-10-29 07:04:44 字数 5144 浏览 1 评论 0原文

我有以下 XML 数据集(简化),其中可以有从零到无限的项目(通常有 2-10 个):

<item template="event_element">
   <mytitle>This is the first title</mytitle>
   <mydate>20110330T143004</mytitle>
   <mydescription>This is the first description</mytitle>
   <mylink>www.example.com</mytitle>
</item>
.
.
<item template="event_element">
   <mytitle>This is the Tenth title</mytitle>
   <mydate>20110330T143004</mytitle>
   <mydescription>This is the tenth description</mytitle>
   <mylink>www.example.com</mytitle>
</item>

我的最终结果应该是这样的,我可以得到几组项目(这将由 javascript 旋转):

<div class="body">
<div class="rel" id="arrangement">

    // First set of items goes here
    <div class="item">
        <div class="itm">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>MY DATE</span>
                        <strong>MY FIRST TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="itm last">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>30. mar 2011</span>
                        <strong>MY SECOND TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="clr"></div>
    </div>

    // Second set of items goes here
    <div class="item">
        <div class="itm">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>MY DATE</span>
                        <strong>MY THIRD TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="itm last">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>30. mar 2011</span>
                        <strong>MY FORTH TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="clr"></div>
    </div>

    <div class="clr"></div>
</div>

我的问题是逐步浏览我的项目(甚至应该按日期描述排序)并将它们分成两组。

就像今天一样,我被迫对这样的集合进行硬编码($eventfolder、$totalevents 变量已预定义):

<pre><code><div class="body">
  <div class="rel" id="arrangement">
    <xsl:if test="$totalevents &gt; 0">
      <div class="item">
        <xsl:for-each select="$eventfolder/item[@template='event_element' and position() &gt; 0 and position() &lt; 3]">
          <xsl:choose>
            <xsl:when test="position() &lt; $eventsperpage">        
          <div class="itm">
            <xsl:call-template name="renderEvent" />    
              </div>
            </xsl:when>
            <xsl:otherwise>
          <div class="itm last">
            <xsl:call-template name="renderEvent" />    
              </div>
              <div class="clr"></div>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each>     
      </div>
    </xsl:if>

    <xsl:if test="$totalevents &gt; 2">
      <div class="item">
        <xsl:for-each select="$eventfolder/item[@template='event_element' and position() &gt; 2 and position() &lt; 5]">
          <xsl:choose>
            <xsl:when test="position() &lt; $eventsperpage">        
          <div class="itm">
            <xsl:call-template name="renderEvent" />    
              </div>
            </xsl:when>
          <xsl:otherwise>
        <div class="itm last">
          <xsl:call-template name="renderEvent" />  
            </div>
            <div class="clr"></div>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>       
    </div>
  </xsl:if>

   <div class="clr"></div>
 </div>
</div>
</code></pre>

renderElement 模板仅呈现内部事件 HTML。

但如果我想显示多于 2 个的集合,或者甚至在每个集合中显示更多的项目,那么这种方法就不太实用了... xslt 文件会很大并且不可读...

对我如何解决这个问题有任何帮助,因为我不知道如何插入 HTML 标签,因为 XSLT 编译器看不到它们被关闭 - 即。 (当 test="position() = 1 插入 html 开始标签,然后当 test="position() = X 关闭标签时)。

提前致谢

I have the following XML dataset (simplified), where I can have from zero to endless items (usually there will be 2-10):

<item template="event_element">
   <mytitle>This is the first title</mytitle>
   <mydate>20110330T143004</mytitle>
   <mydescription>This is the first description</mytitle>
   <mylink>www.example.com</mytitle>
</item>
.
.
<item template="event_element">
   <mytitle>This is the Tenth title</mytitle>
   <mydate>20110330T143004</mytitle>
   <mydescription>This is the tenth description</mytitle>
   <mylink>www.example.com</mytitle>
</item>

My end result should be like this, where I can end up with several sets of items (which will be rotated by javascript):

<div class="body">
<div class="rel" id="arrangement">

    // First set of items goes here
    <div class="item">
        <div class="itm">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>MY DATE</span>
                        <strong>MY FIRST TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="itm last">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>30. mar 2011</span>
                        <strong>MY SECOND TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="clr"></div>
    </div>

    // Second set of items goes here
    <div class="item">
        <div class="itm">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>MY DATE</span>
                        <strong>MY THIRD TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="itm last">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>30. mar 2011</span>
                        <strong>MY FORTH TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="clr"></div>
    </div>

    <div class="clr"></div>
</div>

My problem is stepping through my items (that should even be sorted by the date desc) and grouping them in sets of two.

As it is today I have been forced to hardcode the sets like this (the $eventfolder, $totalevents variables have been predefined):

<pre><code><div class="body">
  <div class="rel" id="arrangement">
    <xsl:if test="$totalevents > 0">
      <div class="item">
        <xsl:for-each select="$eventfolder/item[@template='event_element' and position() > 0 and position() < 3]">
          <xsl:choose>
            <xsl:when test="position() < $eventsperpage">        
          <div class="itm">
            <xsl:call-template name="renderEvent" />    
              </div>
            </xsl:when>
            <xsl:otherwise>
          <div class="itm last">
            <xsl:call-template name="renderEvent" />    
              </div>
              <div class="clr"></div>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each>     
      </div>
    </xsl:if>

    <xsl:if test="$totalevents > 2">
      <div class="item">
        <xsl:for-each select="$eventfolder/item[@template='event_element' and position() > 2 and position() < 5]">
          <xsl:choose>
            <xsl:when test="position() < $eventsperpage">        
          <div class="itm">
            <xsl:call-template name="renderEvent" />    
              </div>
            </xsl:when>
          <xsl:otherwise>
        <div class="itm last">
          <xsl:call-template name="renderEvent" />  
            </div>
            <div class="clr"></div>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>       
    </div>
  </xsl:if>

   <div class="clr"></div>
 </div>
</div>
</code></pre>

The renderElement template simply renders the inside event HTML.

But that way is not very practical if I wanted to show more sets than 2 - or even show more items in each set... The xslt file would be big and unreadable...

Any help to how I can solve this problem, since I cant figure out how to insert HTML tags as the XSLT compiler cant see them being closed - ie. (when test="position() = 1 insert html start tag and then later when test="position() = X close the tag).

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

思念满溢 2024-11-05 07:04:44

在不涉及您的方法所引发的更大问题的情况下,在 XSLT 中,一次对包含 n 个元素的元素列表进行分组的方法是这样的:

<xsl:apply-templates select="*[(position()-1) mod $n = 0]" mode="group"/>

...它将应用组模式模板到第一个、第 n+1 个、第 2n+ 个元素当前元素的第 1 个等子元素。组模式模板如下所示:

<xsl:template match="*" mode="group">
   <group>
      <xsl:apply-templates 
           select=".|following-sibling::*[position() < $n]"/>
   </group>
</xsl:template>

这将创建一个 group 元素,并在该元素内将模板应用于当前元素及其后续 n-1 个同级元素。

最终效果是,只要 n 是正整数,上面的代码就会创建包含源树中 n 个连续元素的 group 元素。在您的示例中,您将创建一个 div 而不是 group 以及其他更改。

Without getting into the larger issues raised by your approach, in XSLT the way to group a list of elements n elements at a time is this:

<xsl:apply-templates select="*[(position()-1) mod $n = 0]" mode="group"/>

...which will apply the group-mode template to the first, n+1th, 2n+1th, etc. child elements of the current element. The group-mode template looks like this:

<xsl:template match="*" mode="group">
   <group>
      <xsl:apply-templates 
           select=".|following-sibling::*[position() < $n]"/>
   </group>
</xsl:template>

This creates a group element, and within that element, applies templates to the current element and its n-1 following siblings.

The net effect is that as long as n is a positive integer, the above will create group elements containing n consecutive elements from the source tree. In your example, you'd create a div instead of a group, among other changes.

烟雨凡馨 2024-11-05 07:04:44

关于:

对我如何解决这个问题有任何帮助吗
问题,因为我不知道如何
插入 HTML 标签作为 XSLT
编译器看不到它们被关闭 -
IE。 (当 test="position() = 1 插入
html 开始标记,然后当
test="position() = X 关闭标签)。

您对问题的思考是错误的。XSLT 生成树,而不是标签。您创建元素,而不是元素的一半。

以下样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!--  the number of items to include in each group -->
    <xsl:variable name="group" select="2" />
    <xsl:template match="/">
        <xsl:apply-templates
            select="events/item[@template='event_element']
                               [(position() - 1)  mod $group = 0]" />
    </xsl:template>
    <xsl:template match="item[@template='event_element']" mode="inner">
        <div class="itm">
            <div class="in">
                <p>
                    <a href="{mylink}" title="{mydescription}">
                        <span><xsl:value-of select="mydate" /></span>
                        <strong><xsl:value-of select="mytitle" /></strong>
                        <xsl:value-of select="mydescription" />
                    </a>
                </p>
            </div>
        </div>
    </xsl:template>
    <xsl:template match="item[@template='event_element']">
        <div class="item">
            <xsl:apply-templates
                select=".|following-sibling::item[@template='event_element']
                                                 [position() < $group]"
                mode="inner" />
            <div class="clr" />
        </div>
    </xsl:template>
</xsl:stylesheet>

应用对此输入:

<events>
<item template="event_element">
   <mytitle>This is the first title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the first description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the second title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the third title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the fourth title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the fifth title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
</events>

产生以下输出:

<div class="item">
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the first description">
                    <span>20110330T143004</span>
                    <strong>This is the first title</strong>
                    This is the first description
                </a>
            </p>
        </div>
    </div>
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the second title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="clr" />
</div>
<div class="item">
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the third title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the fourth title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="clr" />
</div>
<div class="item">
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the fifth title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="clr" />
</div>

通过修改 group 变量的值来更改每个组中包含的项目数。

Regarding:

Any help to how I can solve this
problem, since I cant figure out how
to insert HTML tags as the XSLT
compiler cant see them being closed -
ie. (when test="position() = 1 insert
html start tag and then later when
test="position() = X close the tag).

You're thinking about the problem wrong. XSLT generates trees, not tags. You create elements, not halves of elements.

The following stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!--  the number of items to include in each group -->
    <xsl:variable name="group" select="2" />
    <xsl:template match="/">
        <xsl:apply-templates
            select="events/item[@template='event_element']
                               [(position() - 1)  mod $group = 0]" />
    </xsl:template>
    <xsl:template match="item[@template='event_element']" mode="inner">
        <div class="itm">
            <div class="in">
                <p>
                    <a href="{mylink}" title="{mydescription}">
                        <span><xsl:value-of select="mydate" /></span>
                        <strong><xsl:value-of select="mytitle" /></strong>
                        <xsl:value-of select="mydescription" />
                    </a>
                </p>
            </div>
        </div>
    </xsl:template>
    <xsl:template match="item[@template='event_element']">
        <div class="item">
            <xsl:apply-templates
                select=".|following-sibling::item[@template='event_element']
                                                 [position() < $group]"
                mode="inner" />
            <div class="clr" />
        </div>
    </xsl:template>
</xsl:stylesheet>

Applied to this input:

<events>
<item template="event_element">
   <mytitle>This is the first title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the first description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the second title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the third title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the fourth title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the fifth title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
</events>

Produces the following output:

<div class="item">
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the first description">
                    <span>20110330T143004</span>
                    <strong>This is the first title</strong>
                    This is the first description
                </a>
            </p>
        </div>
    </div>
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the second title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="clr" />
</div>
<div class="item">
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the third title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the fourth title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="clr" />
</div>
<div class="item">
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the fifth title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="clr" />
</div>

Change the number of items to include in each group by modifying the value of the group variable.

晨曦慕雪 2024-11-05 07:04:44
<xsl:template match="items">
<div>
<xsl:apply-template select="item"/>
</div>
</xsl:template>

<xsl:apply-templates match="item">
do stuff here
</xsl:apply-templates>

你在使用类似的东西吗?

<xsl:template match="items">
<div>
<xsl:apply-template select="item"/>
</div>
</xsl:template>

<xsl:apply-templates match="item">
do stuff here
</xsl:apply-templates>

are you using something similar to this?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文