foreach 期间 "position()" 中数字增加的断点

Breakpoint of number increase in "position()" during foreach

我在“foreach”期间增加了一个属性值中的数字。由于名称为“product-1”、“product-2”等的每个键的数组有 4 个值,我需要将数字增加到仅从 0 到 3,然后从 0 到 3 重复,直到处理对象结束。

我的原始 JSON 数据包含更多产品。产品的数量未知,并且可能会不时发生变化。我将 JSON 数据最小化以更好地适应问题。

除了属性文本值从 0 增加到 6 之外,所有代码都工作正常。

问题:

如何调整代码,使属性文本值的数量从 0 增加到 3,然后作为“foreach”的一部分重复。


JSON数据:

<data>
{
  "store": {
    "product-1": [0, 3, 2, 1],
    "product-2": [4, 7, 6, 5]
  },
  "other": {
    "Xxx": 42
  }
}
</data>

XSL:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:item="http://www.example.org/1"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  exclude-result-prefixes="fn"
  expand-text="yes"
>

  <xsl:output method="xml" indent="yes"/>

  <xsl:mode on-no-match="shallow-skip"/>

  <!-- Parse JSON to XML -->

  <xsl:template match="data">
    <inventory>
      <xsl:apply-templates select="json-to-xml(.)/*"/>
    </inventory>
  </xsl:template>

  <!-- Attribute setting -->

  <xsl:attribute-set name="datasheet-result">
    <xsl:attribute name="unitRef">USD</xsl:attribute>
  </xsl:attribute-set>

  <!-- Template -->

  <xsl:template match="*[@key = 'store']">

    <xsl:for-each select="*/*">
      <xsl:element name="item:{parent::*/@key}" use-attribute-sets="datasheet-result">
        <xsl:attribute name="contextRef">period{position() - 1}</xsl:attribute>
        <xsl:value-of select="text()"/>
      </xsl:element>
    </xsl:for-each>

  </xsl:template>

</xsl:transform>

结果:

<?xml version="1.0" encoding="UTF-8"?>
<inventory xmlns:item="http://www.example.org/1">
   <item:product-1 unitRef="USD" contextRef="period0">0</item:product-1>
   <item:product-1 unitRef="USD" contextRef="period1">3</item:product-1>
   <item:product-1 unitRef="USD" contextRef="period2">2</item:product-1>
   <item:product-1 unitRef="USD" contextRef="period3">1</item:product-1>
   <item:product-2 unitRef="USD" contextRef="period4">4</item:product-2>
   <item:product-2 unitRef="USD" contextRef="period5">7</item:product-2>
   <item:product-2 unitRef="USD" contextRef="period6">6</item:product-2>
   <item:product-2 unitRef="USD" contextRef="period7">5</item:product-2>
</inventory>

想要的结果:

<?xml version="1.0" encoding="UTF-8"?>
<inventory xmlns:item="http://www.example.org/1">
   <item:product-1 unitRef="USD" contextRef="period0">0</item:product-1>
   <item:product-1 unitRef="USD" contextRef="period1">3</item:product-1>
   <item:product-1 unitRef="USD" contextRef="period2">2</item:product-1>
   <item:product-1 unitRef="USD" contextRef="period3">1</item:product-1>
   <item:product-2 unitRef="USD" contextRef="period0">4</item:product-2>
   <item:product-2 unitRef="USD" contextRef="period1">7</item:product-2>
   <item:product-2 unitRef="USD" contextRef="period2">6</item:product-2>
   <item:product-2 unitRef="USD" contextRef="period3">5</item:product-2>
</inventory>

像这样使用xsl:for-每次2次:

  <xsl:template match="*[@key = 'store']">
    <xsl:for-each select="*">
      <xsl:for-each select="*">
        <xsl:element name="item:{parent::*/@key}" use-attribute-sets="datasheet-result">
          <xsl:attribute name="contextRef">period{position() - 1}</xsl:attribute>
          <xsl:value-of select="text()"/>
        </xsl:element>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>

Siebe 为您提供了一个使用两个嵌套 for-each 的示例,以便 position() 匹配您想要的结果,另一种选择是使用 xsl:number,例如<xsl:attribute name="contextRef">period<xsl:number start-at="0"/></xsl:attribute> 是最短的例子。

至于 xsl:number 的工作原理,最短的 <xsl:number/> 基本上将相同“类型”的兄弟节点计算为上下文节点,并输出该数字加一。通常有多种使用它的选项,请参阅 XSLT 的任何介绍,例如 https://cranesoftwrights.github.io/books/ptux/index.htm 可以免费下载 XSLT 2 和 1 介绍的 PDF 副本(“使用 XSLT 和 XPath 的实用转换”)和在第 8 章“构建结果树”中有第 3 节“编号说明”/“源树编号”。

当然可以随意浏览规格部分 https://www.w3.org/TR/xslt-30/#number