【问题标题】:XSLT - Previous Value & Increment CounterXSLT - 以前的值和增量计数器
【发布时间】:2020-01-29 22:39:44
【问题描述】:

我正在尝试在 XSLT 中实现一些 php 代码逻辑。

xml结构看起来像

输入:

<parent>
    <child>
        <id>1</id>
        <value>11</value>
    </child>
    <child>
        <id>2</id>
        <value>22</value>
    </child>
    <child>
        <id></id>
        <value>22</value>
    </child>
    <child>
        <id></id>
        <value>00</value>
    </child>
    <child>
        <id></id>
        <value>00</value>
    </child>
<parent>

我试图在XSLT中实现的php(逻辑)中的sudo代码如下:

var Index = 1;
for each "child"{
    if( "id" is not empty ){
        Index += "id" + 1;
    }else{
        if( previous "value" == current "value" ){
            "id" = Index;
            Index++;
        }else{
            "id" = 1;
            Index = 2;
        }
    }
}

据我所知,在 XSLT 中,我们无法在每次迭代中更新计数器/变量。我相信我可以使用preceding-sibling 将之前的值与当前值进行比较,但是如何计算那个时候的索引呢?我可以使用 XSLT 2.0,如果这样更容易/更简单。

有什么想法建议吗?

转换后的输出应如下所示:

输出:

<parent>
    <child>
        <id>1</id>
        <value>11</value>
    </child>
    <child>
        <id>2</id>
        <value>22</value>
    </child>
    <child>
        <id>6</id> <!-- "id" = "Index" calculated so far, since current value (22) = previous value (22) -->
        <value>22</value>
    </child>
    <child>
        <id>1</id> <!-- "id" = 1 since current value (00) != previous value (22) -->
        <value>00</value>
    </child>
    <child>
        <id>2</id> <!-- "id" = "Index" calculated so far, since currnet value (00) = previous value (00) --> 
        <value>00</value>
    </child>
<parent>

【问题讨论】:

  • 这种迭代和增量,如果你想要开始的话,可以在 XSLT 3 中使用xsl:iterate 或者可能以声明方式使用累加器来完成。由于大多数使用 XSLT 2 的人使用自 2017 年以来的 Saxon 9 和 Saxon 9.8 支持 XSLT 3,您可能需要检查您是否不能走这条路。
  • 为什么是&lt;id&gt;6&lt;/id&gt;
  • @michael.hor257k 因为我们从 Index = 1 开始;每次迭代 id != empty 我们都会做Index += id + 1。因此,在第一次迭代之后,由于 id = 1,Index 将为 3。第二次迭代 id = 2,索引将变为 6。在第三次迭代中使用它来填充 id。

标签: xml xslt xslt-1.0 xslt-2.0


【解决方案1】:

这是使用 XSLT 3 和 xsl:iterate 的尝试:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    expand-text="yes"
    version="3.0">

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

  <xsl:template match="parent">
      <xsl:copy>
          <xsl:iterate select="child">
              <xsl:param name="index" select="1"/>
              <xsl:param name="previous-value" select="()"/>
              <xsl:variable name="value" select="value"/>
              <xsl:variable name="id" 
                select="(id[has-children()], if ($value = $previous-value) then $index else 1)[1]"/>
              <xsl:variable name="index"
                select="if (id[has-children()])
                        then $index + $id + 1
                        else if ($value = $previous-value)
                        then $index + 1
                        else 2"/>
              <xsl:apply-templates select=".">
                  <xsl:with-param name="id" select="$id" tunnel="yes"/>
              </xsl:apply-templates>
              <xsl:next-iteration>
                  <xsl:with-param name="index" select="$index"/>
                  <xsl:with-param name="previous-value" select="$value"/>
              </xsl:next-iteration>
          </xsl:iterate>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="id[not(has-children())]">
      <xsl:param name="id" tunnel="yes"/>
      <xsl:copy>{$id}</xsl:copy>
  </xsl:template>

</xsl:stylesheet>

【讨论】:

  • 谢谢,Martin,我会检查我们的 XSLT 引擎是否支持 XSLT 3.0。再次感谢您提供解决方案!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-19
  • 1970-01-01
  • 1970-01-01
  • 2022-08-18
  • 2020-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多