需要实现XSL解决方案,但有问题

时间:2016-05-11 13:17:35

标签: xml xslt

无法让我的实际用例工作。我的代码目前是

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template name="bundle-main">
    <div
      class="container"
      data-page-type="bundle"
      >
      <div class="row">
        <xsl:for-each select="//bundles-entry-by-bundle/entry/components/item">
          <xsl:variable name="id" select="@id" />
          <xsl:if test="@section-handle = 'components-text'">
            <xsl:for-each select="//*[concat(@section-handle,'-entry-by-bundle')]/entry[@id = $id]">
              <xsl:call-template name="components-text"/>
            </xsl:for-each>
          </xsl:if>
          <xsl:if test="@section-handle = 'components-link'">
            <xsl:for-each select="//*[concat(@section-handle,'-entry-by-bundle')]/entry[@id = $id]">
              <xsl:call-template name="components-link"/>
            </xsl:for-each>
          </xsl:if>
        </xsl:for-each>
      </div>
    </div>
  </xsl:template>
</xsl:stylesheet>

打印一行,但需要实现12列包装。我的尝试不值得发布,因为它不太有效。我相信键选择器会像

sum(*[name() = concat($stack-items/@section-handle, '-entry-by-bundle')]/entry[@id = //bundles-entry-by-bundle/entry/components/item/@id]/columns/item/@handle) >= 12 or $i >= count($items)

这是XML

<?xml version="1.0" encoding="utf-8" ?>
<data>
  <bundles-entry-by-bundle>
    <section id="1" handle="bundles">Bundles</section>
    <entry id="3">
      <components>
        <item id="10" handle="perfect-fit-finder-4-columns" section-handle="components-link" section-name="Components: Link">Perfect fit finder (4 columns)</item>
        <item id="13" handle="collection-morning-run-8-column" section-handle="components-link" section-name="Components: Link">Collection: Morning run (8 column)</item>
        <item id="14" handle="collection-weekend-adventures-4-column" section-handle="components-link" section-name="Components: Link">Collection: Weekend Adventures (4 column)</item>
      </components>
    </entry>
  </bundles-entry-by-bundle>
  <fl-languages>
    <current-language handle="en" language="en" region="">English</current-language>
    <supported-languages>
      <item handle="en" main="yes">English</item>
      <item handle="fr">Français</item>
      <item handle="es">Español</item>
    </supported-languages>
  </fl-languages>
  <components-text-entry-by-bundle>
    <section id="4" handle="components-text">Components: Text</section>
    <error>No records found.</error>
  </components-text-entry-by-bundle>
  <components-link-entry-by-bundle>
    <section id="6" handle="components-link">Components: Link</section>
    <entry id="14">
      <headline-above mode="formatted" handle="collection-2" word-count="1" lang="en" handle-en="collection-2" handle-fr="" handle-es="">Collection</headline-above>
      <headline mode="formatted" handle="weekend-adventures" word-count="2" lang="en" handle-en="weekend-adventures" handle-fr="" handle-es="">Weekend Adventures</headline>
      <color has-color="no" />
      <columns>
        <item handle="4">4</item>
      </columns>
      <square-image size="23.28 MB" bytes="24413135" path="/uploads/components-link" type="image/jpeg">
        <filename>weekend-collection-en-1462960850.jpg</filename>
        <meta creation="2016-05-11T02:00:51-08:00" width="4656" height="4656" />
      </square-image>
      <click-hint>No</click-hint>
      <style>
        <item handle="modern">Modern</item>
      </style>
    </entry>
    <entry id="13">
      <headline-above mode="formatted" handle="collection" word-count="1" lang="en" handle-en="collection" handle-fr="" handle-es="">Collection</headline-above>
      <headline mode="formatted" handle="morning-run" word-count="2" lang="en" handle-en="morning-run" handle-fr="" handle-es="">Morning Run</headline>
      <color has-color="no" />
      <columns>
        <item handle="8">8</item>
      </columns>
      <square-image size="257 KB" bytes="263474" path="/uploads/components-link" type="image/jpeg">
        <filename>morning-run-square-en-1462939487.jpg</filename>
        <meta creation="2016-05-10T20:04:47-08:00" width="995" height="995" />
      </square-image>
      <wide-image size="457 KB" bytes="468427" path="/uploads/components-link" type="image/jpeg">
        <filename>morning-run-en-1462939487.jpg</filename>
        <meta creation="2016-05-10T20:04:47-08:00" width="2096" height="995" />
      </wide-image>
      <click-hint>No</click-hint>
      <style>
        <item handle="modern">Modern</item>
      </style>
    </entry>
    <entry id="10">
      <headline mode="formatted" handle="perfect-fit-finder" word-count="3" lang="en" handle-en="perfect-fit-finder" handle-fr="" handle-es="">Perfect fit finder</headline>
      <color r="0" g="168" b="225" has-color="yes">#00a8e1</color>
      <columns>
        <item handle="4">4</item>
      </columns>
      <icon size="2 KB" bytes="2102" path="/uploads/components-link" type="image/svg+xml">
        <filename>shoe-icon-en-1462909181.svg</filename>
        <meta creation="2016-05-10T11:39:41-08:00" width="100" height="41.7" />
      </icon>
      <click-hint>Yes</click-hint>
      <style>
        <item handle="bold">Bold</item>
      </style>
    </entry>
  </components-link-entry-by-bundle>
</data>

以下是我想用上述XML实现并替换我的XSL的solution

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

<xsl:template match="/root">
    <xsl:copy>
        <xsl:call-template name="aggregate">
            <xsl:with-param name="items" select="item"/>
        </xsl:call-template>
    </xsl:copy>
</xsl:template>

<xsl:template name="aggregate">
    <xsl:param name="items" select="/.."/>
    <xsl:param name="i" select="1"/>
    <xsl:variable name="stack-items" select="$items[position() &lt;= $i]" />
    <xsl:choose>
        <xsl:when test="sum($stack-items/@columns) >= 12 or $i >= count($items)">
            <row>
                <xsl:copy-of select="$stack-items"/>
            </row>
            <xsl:if test="$i &lt; count($items)">
                <xsl:call-template name="aggregate">
                    <xsl:with-param name="items" select="$items[position() > $i]"/>
                </xsl:call-template>
            </xsl:if>
        </xsl:when>
        <xsl:otherwise>
            <xsl:call-template name="aggregate">
                <xsl:with-param name="items" select="$items"/>
                <xsl:with-param name="i" select="$i + 1"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:3)

这段代码显然是错误的:

//*[concat(@section-handle,'-entry-by-bundle')]

因为在谓词中使用字符串时,如果字符串非空,则有效值为true,这种情况总是如此。

我怀疑您正在尝试选择名称等于(@ section-handle,&#39; -entry-by-bundle&#39;)的串联的元素。这似乎是您应该使用模板规则而不是命名模板的情况。 (&#34; Silly xsl&#34;有完美的机制满足您的要求,而您却无视它!)。替换此代码:

        <xsl:for-each select="//bundles-entry-by-bundle/entry/components/item">
          <xsl:variable name="id" select="@id" />
          <!-- silly xsl will not let us programatically call templates -->
          <xsl:if test="@section-handle = 'components-text'">
            <xsl:for-each select="//*[concat(@section-handle,'-entry-by-bundle')]/entry[@id = $id]">
              <xsl:call-template name="components-text"/>
            </xsl:for-each>
          </xsl:if>
          <xsl:if test="@section-handle = 'components-link'">
            <xsl:for-each select="//*[concat(@section-handle,'-entry-by-bundle')]/entry[@id = $id]">
              <xsl:call-template name="components-link"/>
            </xsl:for-each>
          </xsl:if>
        </xsl:for-each>

通过

<xsl:for-each select="//bundles-entry-by-bundle/entry/components/item">
   <xsl:apply-templates select="//*[name()=concat(current()/@section-handle, '-entry-by-bundle'/>
</xsl:template>

<xsl:template match="component-text-entry-by-bundle">
  <!-- your component-text template -->
</xsl:template>

<xsl:template match="component-link-entry-by-bundle">
  <!-- your component-link template -->
</xsl:template>