【问题标题】:Iteration, or copying in XSL, based on a count. How do I do it?基于计数的迭代或 XSL 中的复制。我该怎么做?
【发布时间】:2010-05-12 19:39:02
【问题描述】:

我正在尝试从 XML 数据创建一个清单列表(制表符分隔的文本,用于输出)。问题是,我需要根据在 XML 中找到的数字,取出我创建的行并多次列出(迭代???)。所以,从下面的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<library>
  <aisle label="AA">
    <row>bb</row>
    <shelf>a</shelf>
    <books>4</books>
  </aisle>
  <aisle label="BB">
    <row>cc</row>
    <shelf>d</shelf>
    <books>3</books>
  </aisle>
</library>

我需要获取在“books”中找到的值,然后复制文本行该次数。结果如下所示:

Aisle   Row Shelf   Titles
AA     bb   a   
AA     bb   a   
AA     bb   a   
AA     bb   a   
BB     cc   d   
BB     cc   d   
BB     cc   d   

这样盘点员就可以在每个架子上找到标题。我有我的 XSL 的基本结构,但我不确定如何执行“迭代”部分。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" version="2.0">

<xsl:output omit-xml-declaration="yes"/>
<xsl:variable name="tab" select="'&#09;'"/>
<xsl:variable name="newline" select="'&#10;'"/>

<xsl:template match="/">
    <!-- Start Spreadsheet header -->
    <xsl:text>Aisle</xsl:text>
    <xsl:value-of select="$tab"/>
    <xsl:text>Row</xsl:text>
    <xsl:value-of select="$tab"/>
    <xsl:text>Shelf</xsl:text>
    <xsl:value-of select="$tab"/>
    <xsl:text>Titles</xsl:text>
    <xsl:value-of select="$newline"/>
    <!-- End spreadsheet header -->

    <!-- Start entering values from XML -->
    <xsl:for-each select="library/aisle">
        <xsl:value-of select="@label"/>
        <xsl:value-of select="$tab"/>
        <xsl:value-of select="row"/>
        <xsl:value-of select="$tab"/>
        <xsl:value-of select="shelf"/>
        <xsl:value-of select="$tab"/>
        <xsl:value-of select="$tab"/>
        <xsl:value-of select="$newline"/>
    </xsl:for-each>
    <!-- End of values from XML -->

    <!-- Iteration of the above needed, based on count value in "books" -->

</xsl:template>
</xsl:stylesheet>

任何帮助将不胜感激。对于初学者来说,“迭代”这个词是否合适?

谢谢!

【问题讨论】:

  • 好问题! (+1)。请参阅我对简单 XSLT 1.0 递归解决方案的回答。 :)
  • 一般评论:好的,所以这两种解决方案都运行良好,尽管我使用了 XSLT 2.0。我在我的 cmets 中列出的所有“致命错误”都不是代码的错误,而是由旧的“垃圾进垃圾出”问题引起的,经过反复试验,我终于发现实际上有原始 XML 数据中的问题。再次感谢 Dimitre 的帮助!

标签: xslt copy iteration


【解决方案1】:

还有一个更简单的 XSLT 2.0 非递归解决方案:

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  exclude-result-prefixes="xs" 
  >
  <xsl:output method="text"/>

  <xsl:template match="/*">
    Aisle   Row Shelf   Titles&#xA;<xsl:text/>
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="aisle">
    <xsl:variable name="vText" select=
      "concat(@label, '&#9;', row, '&#9;', shelf)"
    />

    <xsl:for-each select="1 to xs:integer(books)">
      <xsl:value-of select="concat($vText, '&#xA;')"/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

【讨论】:

  • 太奇怪了。也就是说,我真正的 XSL 比我的示例复杂得多,因此“books”实际上是一个变量(更像 $bookCount),在这个 2.0 中也给我一个错误“无法将零长度字符串转换为一个整数',而且,就像 1.0 版本一样,仍然给我我需要的结果。无论如何,它似乎有效,所以谢谢!
【解决方案2】:

这是一个简单的递归 XSLT 1.0 解决方案

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="/*">
Aisle   Row Shelf   Titles&#xA;<xsl:text/>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="aisle">
   <xsl:call-template name="makeRows">
     <xsl:with-param name="pText"
     select="concat(@label, '&#9;', row, '&#9;', shelf)"/>
     <xsl:with-param name="pNumRows" select="books"/>
   </xsl:call-template>
 </xsl:template>

 <xsl:template name="makeRows">
  <xsl:param name="pText"/>
  <xsl:param name="pNumRows" select="0"/>

  <xsl:if test="$pNumRows > 0">
    <xsl:value-of select="concat($pText, '&#xA;')"/>

    <xsl:call-template name="makeRows">
      <xsl:with-param name="pText" select="$pText"/>
      <xsl:with-param name="pNumRows" select="$pNumRows -1"/>
    </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时

<library>
  <aisle label="AA">
    <row>bb</row>
    <shelf>a</shelf>
    <books>4</books>
  </aisle>
  <aisle label="BB">
    <row>cc</row>
    <shelf>d</shelf>
    <books>3</books>
  </aisle>
</library>

产生想要的正确结果

Aisle   Row Shelf   Titles
AA  bb  a
AA  bb  a
AA  bb  a
AA  bb  a
BB  cc  d
BB  cc  d
BB  cc  d

【讨论】:

  • 嗯,我刚看到 XSL 2.0 版本。也许我应该试试。在此版本中,我在 处收到“致命”错误,告诉我,“'>' 的第一个操作数的必需项类型是数字。无法转换字符串“”到双倍”我是否需要在某处表明它是类似于 type="numeric" 的东西?
【解决方案3】:
<xsl:param name="pNumRows" select="0"/>

&lt;xsl:param name="pNumRows"&gt;0&lt;/xsl:param&gt;

我认为它会起作用

【讨论】:

    猜你喜欢
    • 2015-11-13
    • 1970-01-01
    • 2018-01-16
    • 2023-03-25
    • 2012-05-26
    • 1970-01-01
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    相关资源
    最近更新 更多