XSLT for-each-group group-starting-with tail(current-group())

问题描述 投票:0回答:1

这是 Martin Honnen 在 here 上的回答的后续。

这是我对他的建议的尝试: XSLT 小提琴链接

以电子表格形式,数据如下所示:

在 XML 中,这是数据输入:

<VendorFile xmlns="http://etc/VendorFile">
    <Row xmlns="">
        <Meter>123</Meter>
        <State>TX</State>
        <StartDate/>
        <Volume/>
    </Row>
    <Row xmlns="">
        <Meter></Meter>
        <State></State>
        <StartDate>1/1/2024</StartDate>
        <Volume>100</Volume>
    </Row>
    <Row xmlns="">
        <Meter></Meter>
        <State></State>
        <StartDate>1/2/2024</StartDate>
        <Volume>110</Volume>
    </Row>
    <Row xmlns="">
        <Meter></Meter>
        <State></State>
        <StartDate>1/3/2024</StartDate>
        <Volume>107</Volume>
    </Row>
    <Row xmlns="">
        <Meter>456</Meter>
        <State>OK</State>
        <StartDate/>
        <Volume/>
    </Row>
    <Row xmlns="">
        <Meter></Meter>
        <State></State>
        <StartDate>1/1/2024</StartDate>
        <Volume>200</Volume>
    </Row>
    <Row xmlns="">
        <Meter></Meter>
        <State></State>
        <StartDate>1/2/2024</StartDate>
        <Volume>205</Volume>
    </Row>
    <Row xmlns="">
        <Meter></Meter>
        <State></State>
        <StartDate>1/3/2024</StartDate>
        <Volume>210</Volume>
    </Row>
</VendorFile> 

我尝试的 XSLT 是这样的(我已经包含了组标签以帮助理解):

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

  <xsl:output method="html" indent="yes" html-version="5"/>

    <xsl:template match="/">
     <output>
        <xsl:for-each-group select="//Row" group-starting-with="Row[normalize-space(Meter) and normalize-space(State)]">
          <group>
              <xsl:for-each select="current-group()">
                  <!-- tail = Returns all but the first item in a sequence. --> 
                   <xsl:apply-templates select="tail(current-group())"/>
                  </xsl:for-each>
             </group>       
        </xsl:for-each-group>
     <output>    
    </xsl:template>
    
<xsl:template match="Row">
    <Row>
    <!--<xsl:apply-templates select="current-group()[1]!(Meter, State), *"/>-->
      <Meter><xsl:value-of select="current-group()[1]!(Meter)"/></Meter>
      <State><xsl:value-of select="current-group()[1]!(State)"/></State>
      <StartDate><xsl:value-of select="StartDate"/></StartDate>
      <Volume><xsl:value-of select="Volume"/></Volume>
    </Row>
</xsl:template>

    
    <!--
    <xsl:template match="Row">
        <xsl:copy>
            <xsl:apply-templates select="current-group()[1]!(Meter, State), *"/>
        </xsl:copy>
    </xsl:template>
  -->

</xsl:stylesheet>

我当前的输出不是我想要的,但已经相当接近了。似乎每组的开始日期和数量都出现了 3 次。

<output>
   <group>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/1/2024</StartDate>
         <Volume>100</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/2/2024</StartDate>
         <Volume>110</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/3/2024</StartDate>
         <Volume>107</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/1/2024</StartDate>
         <Volume>100</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/2/2024</StartDate>
         <Volume>110</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/3/2024</StartDate>
         <Volume>107</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/1/2024</StartDate>
         <Volume>100</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/2/2024</StartDate>
         <Volume>110</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/3/2024</StartDate>
         <Volume>107</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/1/2024</StartDate>
         <Volume>100</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/2/2024</StartDate>
         <Volume>110</Volume>
      </Row>
      <Row><Meter>123</Meter><State>TX</State>
         <StartDate>1/3/2024</StartDate>
         <Volume>107</Volume>
      </Row>
   </group>
   <group>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/1/2024</StartDate>
         <Volume>200</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/2/2024</StartDate>
         <Volume>205</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/3/2024</StartDate>
         <Volume>210</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/1/2024</StartDate>
         <Volume>200</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/2/2024</StartDate>
         <Volume>205</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/3/2024</StartDate>
         <Volume>210</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/1/2024</StartDate>
         <Volume>200</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/2/2024</StartDate>
         <Volume>205</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/3/2024</StartDate>
         <Volume>210</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/1/2024</StartDate>
         <Volume>200</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/2/2024</StartDate>
         <Volume>205</Volume>
      </Row>
      <Row><Meter>456</Meter><State>OK</State>
         <StartDate>1/3/2024</StartDate>
         <Volume>210</Volume>
      </Row>
   </group>
</output>
xslt saxon xslt-3.0
1个回答
0
投票

你的主要错误正在改变

<xsl:for-each-group select="//Row" group-starting-with="Row[normalize-space(Meter) and normalize-space(State)]">
  <xsl:apply-templates select="tail(current-group())"/>
</xsl:for-each-group>

    <xsl:for-each-group select="//Row" group-starting-with="Row[normalize-space(Meter) and normalize-space(State)]">
      <group>
          <xsl:for-each select="current-group()">
              <!-- tail = Returns all but the first item in a sequence. --> 
               <xsl:apply-templates select="tail(current-group())"/>
              </xsl:for-each>
         </group>       
    </xsl:for-each-group>

这样你就插入了一个

for-each
,这不是建议的,但对于当前组中的每个项目都会处理当前组的尾部。

另请注意,我已经审阅了原始答案,并将

Row
的模板改进为

<xsl:template match="Row">
    <xsl:copy>
        <xsl:apply-templates select="current-group()[1]!(Meter, State), * except (Meter, State)"/>
    </xsl:copy>
</xsl:template>

然后我建议添加

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

© www.soinside.com 2019 - 2024. All rights reserved.