XSL分组与1.0

时间:2013-07-16 08:30:52

标签: xslt xpath key grouping

我有一个像以下那样的XML。

<Doc>
<row>
  <Col1>13820PKS-</Col1> 
  <Col6>01</Col6> 
  <Col9>1507462800</Col9> 
  <Col12>15074628</Col12> 
  <Col14>4</Col14> 
  </row>
<row>
  <Col1>13820PKS-</Col1> 
  <Col6>01</Col6> 
  <Col9>1507462800</Col9> 
  <Col12>15074629</Col12> 
  <Col14>5</Col14> 
  </row>
 <row>
  <Col1>13820PKS-</Col1> 
  <Col6>01</Col6> 
  <Col9>1808502801</Col9> 
  <Col12>18085021</Col12> 
  <Col14>1</Col14> 
  </row>
 <row>
  <Col1>13820PKS-</Col1> 
  <Col6>02</Col6> 
  <Col9>2710004100</Col9> 
  <Col12>2710004100</Col12> 
  <Col14>1</Col14> 
  </row>
</Doc>

该文件实际上有超过2000行。 最终结果应该是

<Doc>
    <ListID id="01">
        <MainArt>
            <ItemCode>13820PKS-</ItemCode>
            <List>
                <SubArt>
                    <ItemCode>1507462800</ItemCode>
                    <SubArtList>
                        <row>
                            <ItemCode>15074628</ItemCode>
                            <Quantity>4</Quantity>
                        </row>
                        <row>
                            <ItemCode>15074629</ItemCode>
                            <Quantity>5</Quantity>
                        </row>
                    </SubArtList>
                </SubArt>
                <SubArt>
                    <ItemCode>1808502801</ItemCode>
                    <SubArtList>
                        <row>
                            <ItemCode>18085021</ItemCode>
                            <Quantity>1</Quantity>
                        </row>
                    </SubArtList>
                </SubArt>
            </List>
        </MainArt>
    </ListID>
    <ListID id="02">
        <MainArt>
            <ItemCode>13820PKS-</ItemCode>
            <List>
                <SubArt>
                    <ItemCode>2710004100</ItemCode>
                    <SubArtList>
                        <row>
                            <ItemCode>2710004100</ItemCode>
                            <Quantity>1</Quantity>
                        </row>
                    </SubArtList>
                </SubArt>
            </List>
        </MainArt>
    </ListID>
</Doc>

我仍在学习阶段,并没有真正掌握模板的技能。我尝试使用递归for-each循环,但这也没有用。 任何帮助将不胜感激。感谢

1 个答案:

答案 0 :(得分:0)

通过三个级别的多重分组,您自己并不容易!但这就是你做的......

首先,您要按最高级别的 Col6 元素进行分组,因此您可以通过 Col6定义一个键来查找元素价值。

<xsl:key name="Col6" match="row" use="Col6"/>

因此,对于给定值,该键将返回 Col6 元素等于该值的所有元素。

现在,为了获得'不同' Col6 值,您会看到所有元素,但只选择首先出现的元素。 Col6 键的组。这样就完成了,

<xsl:apply-templates 
     select="row[generate-id() = generate-id(key('Col6', Col6)[1])]" 
     mode="Col6" />

(注意在这里使用模式,因为最终的XSLT将有多个匹配元素的模板,因此您需要区分它们。)

现在,在匹配 Col6 元素的模板中,您需要按 Col1 元素进行分组。这是一个稍微复杂的地方,因为您需要定义一个键,它是 Col6 Col1 元素的组合。 (允许两个 Col1 元素可能具有不同的 Col6 值)

<xsl:key name="Col1" match="row" use="concat(Col6, '|', Col1)"/>

请注意使用管道|字符来分隔值。这可以是任何字符,只要它不会出现在 Col6 Col1

然后在当前的 Col6 中获取不同的 Col1 元素,你会这样做

<xsl:apply-templates 
     select="key('Col6', Col6)
             [generate-id() = generate-id(key('Col1', concat(Col6, '|', Col1))[1])]"
     mode="Col1" />

最后,对于 Col9 元素,您将拥有一个三重连接键。

<xsl:key name="Col9" match="row" use="concat(Col6, '|', Col1, '|', Col9)"/>

可以类似的方式使用它来获取当前 Col1 中的所有 Col9 元素。

完全放弃,给出以下XSLT

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

  <xsl:key name="Col6" match="row" use="Col6"/>
  <xsl:key name="Col1" match="row" use="concat(Col6, '|', Col1)"/>
  <xsl:key name="Col9" match="row" use="concat(Col6, '|', Col1, '|', Col9)"/>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates select="row[generate-id() = generate-id(key('Col6', Col6)[1])]" mode="Col6" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="row" mode="Col6">
    <ListID id="{Col6}">
      <xsl:apply-templates select="key('Col6', Col6)[generate-id() = generate-id(key('Col1', concat(Col6, '|', Col1))[1])]" mode="Col1" />
    </ListID>
  </xsl:template>

  <xsl:template match="row" mode="Col1">
    <MainArt>
      <ItemCode>
        <xsl:value-of select="Col1"/>
      </ItemCode>
      <List>
        <xsl:apply-templates select="key('Col1', concat(Col6, '|', Col1))[generate-id() = generate-id(key('Col9', concat(Col6, '|', Col1, '|', Col9))[1])]" mode="Col9" />
      </List>
    </MainArt>
  </xsl:template>

  <xsl:template match="row" mode="Col9">
    <SubArt>
      <ItemCode>
        <xsl:value-of select="Col9"/>
      </ItemCode>
      <SubArtList>
        <xsl:apply-templates select="key('Col9', concat(Col6, '|', Col1, '|', Col9))" mode="Col12" />
      </SubArtList>
    </SubArt>
  </xsl:template>

  <xsl:template match="row" mode="Col12">
    <row>
      <ItemCode>
        <xsl:value-of select="Col12"/>
      </ItemCode>
      <Quantity>
        <xsl:value-of select="Col14"/>
      </Quantity>
    </row>
  </xsl:template>
</xsl:stylesheet>

当应用于您的示例XML时,输出以下内容

<Doc>
  <ListID id="01">
    <MainArt>
      <ItemCode>13820PKS-</ItemCode>
      <List>
        <SubArt>
          <ItemCode>1507462800</ItemCode>
          <SubArtList>
            <row>
              <ItemCode>15074628</ItemCode>
              <Quantity>4</Quantity>
            </row>
            <row>
              <ItemCode>15074629</ItemCode>
              <Quantity>5</Quantity>
            </row>
          </SubArtList>
        </SubArt>
        <SubArt>
          <ItemCode>1808502801</ItemCode>
          <SubArtList>
            <row>
              <ItemCode>18085021</ItemCode>
              <Quantity>1</Quantity>
            </row>
          </SubArtList>
        </SubArt>
      </List>
    </MainArt>
  </ListID>
  <ListID id="02">
    <MainArt>
      <ItemCode>13820PKS-</ItemCode>
      <List>
        <SubArt>
          <ItemCode>2710004100</ItemCode>
          <SubArtList>
            <row>
              <ItemCode>2710004100</ItemCode>
              <Quantity>1</Quantity>
            </row>
          </SubArtList>
        </SubArt>
      </List>
    </MainArt>
  </ListID>
</Doc>