XSLT按条件对标记化的值进行分组

时间:2019-07-10 16:06:50

标签: xml xslt xslt-2.0 xslt-grouping

我很难将重复元素分组到新的xml中。

我的输入文件是

<Load>
    <DataArea>
        <tag>
            <row>A,Header</row>
        </tag>

        <tag>
            <row>B,20190701</row>
        </tag>
        <tag>
            <row>C,12345, 100.00, 200.00</row>
        </tag>
        <tag>
            <row>D,001, 25.00</row>
        </tag>
        <tag>
            <row>D,002, 35.00</row>
        </tag>
        <tag>
            <row>D,003, 45.00</row>
        </tag>

        <tag>
            <row>B,20190702</row>
        </tag>
        <tag>
            <row>C,12345, 300.00, 400.00</row>
        </tag>
        <tag>
            <row>D,004, 55.00</row>
        </tag>
        <tag>
            <row>D,005, 65.00</row>
        </tag>
        <tag>
            <row>D,006, 75.00</row>
        </tag>

    </DataArea>
</Load>

我必须标记逗号分隔的元素值,并想将其转换为下面的xml结构。

<Load>
    <DataArea>
        <Header>
            <A>Header</A>
        </Header>

        <Line>
            <!-- July 1 Record -->
            <B>20190701</B>
            <C>12345</C>
            <D>
                <code>001</code>
                <amount>25.00</amount>
            </D>
            <D>
                <code>002</code>
                <amount>35.00</amount>
            </D>
            <D>
                <code>003</code>
                <amount>45.00</amount>
            </D>
        </Line>

        <Line>
            <!-- July 2 Record -->
            <B>20190702</B>
            <C>12345</C>
            <D>
                <code>004</code>
                <amount>55.00</amount>
            </D>
            <D>
                <code>005</code>
                <amount>65.00</amount>
            </D>
            <D>
                <code>006</code>
                <amount>75.00</amount>
            </D>
        </Line>
    </DataArea>
</Load>

有2个<Lines></Lines>,因为只有两个日期 7月1 7月2 。日期表示为元素<B>

的值

每个<D>都有多个<Line>

我的问题是我无法将<B><C><D>组合在一起,并用<Line>括起来。 <D>应该属于正确的<B>或日期。

下面是我的xslt代码。

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*" />
    <xsl:template match="/">
        <Load>
            <DataArea>
                <Header>
                    <A>
                        <xsl:for-each select="Load/DataArea/tag">
                            <xsl:variable name="col"
                                select="tokenize(current(),',')" />
                            <xsl:if test="$col[1] = 'A' ">
                                <xsl:value-of select="$col[2]" />
                            </xsl:if>
                        </xsl:for-each>

                    </A>
                </Header>

                <xsl:for-each select="Load/DataArea/tag">
                    <xsl:variable name="column"
                        select="tokenize(current(),',')" />
                    <Line>
                        <xsl:if test="$column[1] = 'B' ">
                            <B>
                                <xsl:value-of select="$column[2]" />
                            </B>
                        </xsl:if>
                        <xsl:if test="$column[1] = 'C' ">
                            <C>
                                <xsl:value-of select="$column[2]" />
                            </C>
                        </xsl:if>
                        <xsl:for-each select="../tag">
                            <xsl:variable name="column"
                                select="tokenize(current(),',')" />
                            <xsl:if test="$column[1] = 'D' ">
                                <D>
                                    <code>
                                        <xsl:value-of select="$column[2]" />
                                    </code>
                                    <amount>
                                        <xsl:value-of select="$column[3]" />
                                    </amount>
                                </D>
                            </xsl:if>
                        </xsl:for-each>
                    </Line>
                </xsl:for-each>
            </DataArea>
        </Load>
    </xsl:template>
</xsl:stylesheet>

我得到每个循环的所有<D>,而不仅仅是属于Date / <B>的那些循环重复所有<D><Line>

我不确定如何解决这个问题,特别是我需要标记它们。

我将不胜感激。

谢谢。

1 个答案:

答案 0 :(得分:0)

我认为这可能是xsl:for-each-group属性为group-starting-with的工作。

尝试使用此XSLT,我已经简化了使用基本的A功能来获取starts-with标头的过程

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:template match="/">
    <Load>
      <DataArea>
        <Header>
          <A>
            <xsl:value-of select="substring-after(Load/DataArea/tag[starts-with(row, 'A,')], ',') " />
          </A>
        </Header>          
        <xsl:for-each-group select="Load/DataArea/tag[not(starts-with(row, 'A,'))]" group-starting-with="tag[starts-with(row, 'B,')]">
          <Line>
            <xsl:for-each select="current-group()">
              <xsl:variable name="column" select="tokenize(row,',')" />
              <xsl:element name="{$column[1]}">
              <xsl:choose>
                <xsl:when test="$column[1] = 'B' or $column[1] = 'C'">
                  <xsl:value-of select="$column[2]" />
                </xsl:when>
                <xsl:otherwise>
                  <code>
                    <xsl:value-of select="$column[2]" />
                  </code>
                  <amount>
                    <xsl:value-of select="$column[3]" />
                  </amount>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:element>
            </xsl:for-each>
          </Line>
        </xsl:for-each-group>
      </DataArea>
    </Load>
  </xsl:template>
</xsl:stylesheet>