【问题标题】:How to wrap an `apply-template` element with a `div` element using XSLT?如何使用 XSLT 用 `div` 元素包装`apply-template` 元素?
【发布时间】:2013-06-12 17:38:41
【问题描述】:

我正在尝试用 div 标签包装重复的 system-folder 元素。我可以有两到三个system-folder 元素都用div 包裹。

system-page 元素可以是前面或后面的兄弟元素。

知道我需要改变什么来实现这个吗?我是否需要利用前面的兄弟并进行 3 次应用模板调用?

XML

<system-index-block current-time="1370982198860" name="index-block" type="folder">

  <system-page id="3499046a0a1e023a19a05c9328c6e360">
    <name>calendar</name>
    <title>College Catalog</title>
    <display-name>Enter a display name (For Navigation)</display-name>
    <path>/web/catalog/calendar</path>
  </system-page>

  <system-folder id="348ce18d0a1e023a19a05c93941a001d">
    <name>general</name>
    <display-name>General Information</display-name>
    <path>/web/catalog/general</path>
    <system-page id="348d29520a1e023a19a05c9362978f0d">
      <name>history</name>
      <title>History of the College</title>
      <display-name>Enter a display name (For Navigation)</display-name>
      <path>/web/catalog/general/history</path>
    </system-page>
  </system-folder>

  <system-folder id="348ce18d0a1e023a19a05c93941a001d">
    <name>general</name>
    <display-name>General Information</display-name>
    <path>/web/catalog/general</path>
    <system-page id="348d29520a1e023a19a05c9362978f0d">
      <name>history</name>
      <title>History of the College</title>
      <display-name>Enter a display name (For Navigation)</display-name>
      <path>/web/catalog/general/history</path>
    </system-page>
  </system-folder>

  <system-page current="true" id="341f70a80a1e023a19a05c93a172e372">
    <name>index</name>
    <title>College Catalog</title>
    <display-name>Enter a display name (For Navigation)</display-name>
    <path>/web/catalog/index</path>
  </system-page>

</system-index-block>

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="html" encoding="utf-8"/>

  <xsl:template match="/">
    <xsl:apply-templates select="node()" />
  </xsl:template>

  <xsl:template match="system-page">

    <xsl:variable name="x">
      <xsl:element name="a">
        <xsl:if test="@current='true'">
          <xsl:attribute name="class">current-nav-link</xsl:attribute>
        </xsl:if>
        <xsl:attribute name="href"><xsl:value-of select="path"/></xsl:attribute>
        <xsl:value-of select="title" />
      </xsl:element>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="parent::system-index-block">
        <div class="nav-entry-link">
          <xsl:copy-of select="$x" />
        </div>
      </xsl:when>
      <xsl:otherwise>
        <li>
          <xsl:copy-of select="$x" />
        </li>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="system-folder">
    <h2><xsl:value-of select="display-name" /></h2>
    <ul>
      <xsl:for-each select="system-page">
        <xsl:apply-templates select="current()" />
      </xsl:for-each>
    </ul>
  </xsl:template>

</xsl:stylesheet>

输出

<div class="nav-entry-link">
  <a href="/web/catalog/calendar">College Catalog</a>
</div>

<h2>General Information</h2>
<ul>
  <li>
    <a href="/web/catalog/general/history">History of the College</a>
  </li>
  <li>
    <a href="/web/catalog/general/payment">test</a>
  </li>
  <li>
    <a href="/web/catalog/general/governance">Governance</a>
  </li>
</ul>

<h2>General Information</h2>
<ul>
  <li>
    <a href="/web/catalog/general/history">History of the College</a>
  </li>
  <li>
    <a href="/web/catalog/general/payment">test</a>
  </li>
  <li>
    <a href="/web/catalog/general/governance">Governance</a>
  </li>
</ul>

<div class="nav-entry-link">
  <a class="current-nav-link" href="/web/catalog/index">College Catalog</a>
</div>

我想将所有 h2ul 元素包装成这样:

<div class="nav-entry-link">
  <a href="/web/catalog/calendar">College Catalog</a>
</div>
    <div class="accordion">
      <h2>test</h2>
      <ul>test</ul>
      <h2>test</h2>
      <ul>test</ul>
    </div>
<div class="nav-entry-link">
  <a href="/web/catalog/calendar">College Catalog</a>
</div>

【问题讨论】:

  • 这个很不清楚。您是说您想要包含在&lt;div class="nav-entry-link"&gt; 元素中的所有顶级system-folder 序列的h2ul 元素? system-foldersystem-page 元素是否以任意顺序散布,您是否要保持该顺序? system-page 元素的序列呢?您是否也希望将它们包装在单独的 div 元素中,就像您在当前 XML 输出中显示的那样?
  • 系统文件夹元素是系统页面的兄弟元素。对于手风琴,系统文件夹将仅包含在 1 个 div 中。不是系统文件夹子级的系统页面应该有单独的 div。
  • 顺序可能会保持一致。

标签: xslt


【解决方案1】:

试试这样的:

添加一个模板,该模板忽略具有直接前同级系统文件夹的系统文件夹。

<xsl:template match="system-folder[preceding-sibling::*[1][name() = 'system-folder']]" />

还有一个生成差异的模板

<xsl:template match="system-folder">
    <div>
        <xsl:apply-templates select="." mode="following" />
    </div>
</xsl:template>

并递归调用以下兄弟姐妹。 试试这个:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="html" encoding="utf-8"/>

    <xsl:template match="/">
        <xsl:apply-templates select="node()" />
    </xsl:template>

    <xsl:template match="system-page">

        <xsl:variable name="x">
            <xsl:element name="a">
                <xsl:if test="@current='true'">
                    <xsl:attribute name="class">current-nav-link</xsl:attribute>
                </xsl:if>
                <xsl:attribute name="href">
                    <xsl:value-of select="path"/>
                </xsl:attribute>
                <xsl:value-of select="title" />
            </xsl:element>
        </xsl:variable>

        <xsl:choose>
            <xsl:when test="parent::system-index-block">
                <div class="nav-entry-link">
                    <xsl:copy-of select="$x" />
                </div>
            </xsl:when>
            <xsl:otherwise>
                <li>
                    <xsl:copy-of select="$x" />
                </li>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="system-folder[preceding-sibling::*[1][name() = 'system-folder']]" />
    <xsl:template match="system-folder">
        <div>
            <xsl:apply-templates select="." mode="following" />
        </div>
    </xsl:template>
    <xsl:template match="system-folder" mode="following">

        <h2>
            <xsl:value-of select="display-name" />
        </h2>
        <ul>
            <xsl:for-each select="system-page">
                <xsl:apply-templates select="current()" />
            </xsl:for-each>
        </ul>
        <xsl:apply-templates select="following-sibling::*[1][name() = 'system-folder']" mode="following" />
    </xsl:template>

</xsl:stylesheet>

这将生成以下输出:

<div class="nav-entry-link">
    <a href="/web/catalog/calendar">College Catalog</a>
</div>

<div>
    <h2>General Information</h2>
    <ul>
        <li>
            <a href="/web/catalog/general/history">History of the College</a>
        </li>
    </ul>
    <h2>General Information</h2>
    <ul>
        <li>
            <a href="/web/catalog/general/history">History of the College</a>
        </li>
    </ul>
</div>



<div class="nav-entry-link">
    <a class="current-nav-link" href="/web/catalog/index">College Catalog</a>
</div>

【讨论】:

  • 哇,它做到了!谢谢你。我现在要检查代码。这是什么意思:preceding-sibling::*[1][name() = 'system-folder']]
  • preceding-sibling::* 查找当前属于同一个父元素之前的所有元素。 [1] 从这里获取第一个元素(当前元素之前的元素)。 [name() = 'system-folder'] 测试此元素是否为系统文件夹。
  • 所以当 XSLT 处理器处理应用模板时,node() 会落在第一个系统文件夹上,从那里会发生什么?
  • 它将再次为这个系统文件夹生成常用的 div 和 apply-templates,但 mode=follwing。它生成&lt;h2&gt; 等并递归调用相同的模板(用于直接跟随),而直接跟随“系统文件夹”
  • 谢谢,我不熟悉 mode=following,所以我想我有一些阅读要做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多